Skip to content

Commit a38685b

Browse files
mifeillejoshuaocero
authored andcommitted
CV3-47 implement use celery to delete archived data (#510)
- configure celery beat - implement use celery to delete archived data that is over 30 days old [Delivers CV3-47]
1 parent 756adc6 commit a38685b

File tree

9 files changed

+147
-67
lines changed

9 files changed

+147
-67
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,6 @@ converge_db/
139139
# google calendar data
140140
events.json
141141
calendar_list.json
142+
143+
# maintain consistent coding styles
144+
.editorconfig
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""include cascading deletion on room tags
2+
3+
Revision ID: c058d462a21d
4+
Revises: 98e4dbfc868a
5+
Create Date: 2019-11-04 17:45:56.163962
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = 'c058d462a21d'
14+
down_revision = '98e4dbfc868a'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
op.drop_constraint('room_tags_tag_id_fkey',
21+
'room_tags', type_='foreignkey')
22+
op.create_foreign_key(None, 'room_tags', 'tags', [
23+
'tag_id'], ['id'], ondelete='CASCADE')
24+
op.drop_constraint('room_tags_room_id_fkey',
25+
'room_tags', type_='foreignkey')
26+
op.create_foreign_key(None, 'room_tags', 'rooms', [
27+
'room_id'], ['id'], ondelete='CASCADE')
28+
29+
30+
def downgrade():
31+
op.drop_constraint('room_tags_room_id_fkey',
32+
'room_tags', type_='foreignkey')
33+
op.create_foreign_key('room_tags_room_id_fkey', 'room_tags',
34+
'rooms', ['room_id'], ['id'])
35+
op.drop_constraint('room_tags_tag_id_fkey', 'room_tags', type_='foreignkey')
36+
op.create_foreign_key('room_tags_tag_id_fkey', 'room_tags',
37+
'tags', ['tag_id'], ['id'])

api/events/models.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
from helpers.database import Base
77
from utilities.utility import Utility, StateType
88
from helpers.events_filter.events_filter import (
9-
validate_date_input,
10-
format_range_dates,
9+
validate_date_input,
10+
format_range_dates,
1111
)
1212

1313

1414
class Events(Base, Utility):
1515
__tablename__ = 'events'
16-
id = Column(Integer, Sequence('events_id_seq', start=1, increment=1), primary_key=True) # noqa
16+
id = Column(Integer, Sequence('events_id_seq', start=1, increment=1), primary_key=True) # noqa
1717
event_id = Column(String, nullable=False)
1818
room_id = Column(Integer, ForeignKey('rooms.id', ondelete="CASCADE"))
1919
event_title = Column(String, nullable=True)
@@ -38,19 +38,19 @@ def filter_events_by_date_range(query, start_date, end_date):
3838
validate_date_input(start_date, end_date)
3939
if not start_date and not end_date:
4040
events = query.filter(
41-
Events.state == 'active'
42-
).all()
41+
Events.state == 'active'
42+
).all()
4343
if not events:
4444
raise GraphQLError('Events do not exist')
4545
return events
4646

4747
start_date, end_date = format_range_dates(start_date, end_date)
4848

4949
events = query.filter(
50-
Events.state == 'active',
51-
Events.start_time >= start_date,
52-
Events.end_time <= end_date
53-
).all()
50+
Events.state == 'active',
51+
Events.start_time >= start_date,
52+
Events.end_time <= end_date
53+
).all()
5454
if not events:
5555
raise GraphQLError('Events do not exist for the date range')
5656
return events
@@ -64,9 +64,9 @@ def filter_event_by_room(room_id, start_date, end_date):
6464
validate_date_input(start_date, end_date)
6565
if not start_date and not end_date:
6666
events = Events.query.filter_by(
67-
room_id = room_id,
68-
state = 'active'
69-
).all()
67+
room_id=room_id,
68+
state='active'
69+
).all()
7070
if not events:
7171
raise GraphQLError('Events do not exist')
7272
return events
@@ -78,7 +78,7 @@ def filter_event_by_room(room_id, start_date, end_date):
7878
Events.state == 'active',
7979
Events.start_time >= start_date,
8080
Events.end_time <= end_date
81-
).all()
81+
).all()
8282
if not events:
8383
raise GraphQLError('Events do not exist for the date range')
8484
return events

api/events/schema.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class Arguments:
5252
def mutate(self, info, **kwargs):
5353
room_id, event = check_event_in_db(self, info, "checked_in", **kwargs)
5454
if kwargs.get('check_in_time'):
55-
update_device_last_activity(info, room_id, kwargs['check_in_time'], 'check in')
55+
update_device_last_activity(
56+
info, room_id, kwargs['check_in_time'], 'check in')
5657
if not event:
5758
event = EventsModel(
5859
event_id=kwargs['event_id'],
@@ -85,10 +86,11 @@ def mutate(self, info, **kwargs):
8586
room_id, event = check_event_in_db(self, info, "cancelled", **kwargs)
8687
try:
8788
device_last_seen = parser.parse(
88-
kwargs['start_time']) + timedelta(minutes=10)
89+
kwargs['start_time']) + timedelta(minutes=10)
8990
except ValueError:
9091
raise GraphQLError("Invalid start time")
91-
update_device_last_activity(info, room_id, device_last_seen, 'cancel meeting')
92+
update_device_last_activity(
93+
info, room_id, device_last_seen, 'cancel meeting')
9294
if not event:
9395
event = EventsModel(
9496
event_id=kwargs['event_id'],
@@ -102,15 +104,15 @@ def mutate(self, info, **kwargs):
102104
auto_cancelled=True)
103105
event.save()
104106
calendar_event = get_single_calendar_event(
105-
kwargs['calendar_id'],
106-
kwargs['event_id']
107-
)
107+
kwargs['calendar_id'],
108+
kwargs['event_id']
109+
)
108110
event_reject_reason = 'after 10 minutes'
109111
if not notification.event_cancellation_notification(
110-
calendar_event,
111-
room_id,
112-
event_reject_reason
113-
):
112+
calendar_event,
113+
room_id,
114+
event_reject_reason
115+
):
114116
raise GraphQLError("Event cancelled but email not sent")
115117
return CancelEvent(event=event)
116118

@@ -131,12 +133,13 @@ class Arguments:
131133
def mutate(self, info, **kwargs):
132134
room_id, event = check_event_in_db(self, info, "ended", **kwargs)
133135
if kwargs.get('meeting_end_time'):
134-
update_device_last_activity(info, room_id, kwargs['meeting_end_time'], 'end meeting')
136+
update_device_last_activity(
137+
info, room_id, kwargs['meeting_end_time'], 'end meeting')
135138
if not event:
136139
event = EventsModel(
137140
event_id=kwargs['event_id'],
138141
meeting_end_time=kwargs['meeting_end_time']
139-
)
142+
)
140143
event.save()
141144

142145
return EndEvent(event=event)
@@ -264,7 +267,7 @@ class Query(graphene.ObjectType):
264267
\n- end_date: The date and time to end selection in range \
265268
when filtering by the time period\
266269
\n- page: Page number to select when paginating\
267-
\n- per_page: The maximum number of events per page when paginating") # noqa
270+
\n- per_page: The maximum number of events per page when paginating") # noqa
268271

269272
all_events_by_room = graphene.Field(
270273
RoomEvents,
@@ -278,7 +281,6 @@ class Query(graphene.ObjectType):
278281
\n- end_date: The date and time to end selection in range \
279282
when filtering by the time period")
280283

281-
282284
@Auth.user_roles('Admin', 'Default User', 'Super Admin')
283285
def resolve_all_events(self, info, **kwargs):
284286
start_date = kwargs.get('start_date')
@@ -289,7 +291,7 @@ def resolve_all_events(self, info, **kwargs):
289291
query = Events.get_query(info)
290292
response = filter_events_by_date_range(
291293
query, start_date, end_date
292-
)
294+
)
293295
sort_events_by_date(response)
294296

295297
if page and per_page:
@@ -310,7 +312,6 @@ def resolve_all_events(self, info, **kwargs):
310312
pages=pages)
311313

312314
return PaginateEvents(events=response)
313-
314315

315316
@Auth.user_roles('Admin', 'Super Admin')
316317
def resolve_all_events_by_room(self, info, **kwargs):
@@ -319,13 +320,13 @@ def resolve_all_events_by_room(self, info, **kwargs):
319320
start_date = kwargs.get('start_date')
320321
end_date = kwargs.get('end_date')
321322
room = RoomModel.query.filter_by(
322-
calendar_id = calendar_id
323-
).first()
323+
calendar_id=calendar_id
324+
).first()
324325
if not room:
325326
raise GraphQLError("No rooms with the given CalendarId")
326327
response = filter_event_by_room(
327328
room.id, start_date, end_date
328-
)
329+
)
329330
sort_events_by_date(response)
330331

331332
return RoomEvents(events=response)

config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from celery.schedules import crontab
23
basedir = os.path.abspath(os.path.dirname(__file__))
34

45

@@ -18,6 +19,13 @@ class Config:
1819
# Celery configuration
1920
CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL')
2021
CELERY_RESULT_BACKEND = os.getenv('CELERY_RESULT_BACKEND')
22+
CELERY_IMPORTS = ["services.data_deletion.clean_archived_data"]
23+
CELERYBEAT_SCHEDULE = {
24+
'clean_archived_data': {
25+
'task': 'clean_archived_data.delete_archived_data',
26+
'schedule': crontab(hour=23, minute=00)
27+
},
28+
}
2129

2230
@staticmethod
2331
def init_app(app):

docker/dev/start_redis.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
#done
55
cd /app
66
export $(cat .env | xargs)
7-
celery worker -A cworker.celery --loglevel=info
7+
celery worker -A cworker.celery --loglevel=info & celery beat -A cworker.celery --schedule=/tmp/celerybeat-schedule --loglevel=info --pidfile=/tmp/celerybeat.pid
Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
query_all_events_by_room_with_dates = '''
22
query{
3-
allEventsByRoom(calendarId:"andela.com_3630363835303531343031@resource.calendar.google.com", startDate:"Jul 10 2018",
3+
allEventsByRoom(calendarId:"andela.com_3630363835303531343031@resource.calendar.google.com",
4+
startDate:"Jul 10 2018",
45
endDate:"Jul 13 2018" ){
56
events{
67
eventTitle
@@ -10,22 +11,22 @@
1011
}
1112
}
1213
}
13-
14+
1415
'''
1516

1617
query_all_events_by_room_with_dates_response = {
17-
"data": {
18-
"allEventsByRoom": {
19-
"events": [
20-
{
21-
"eventTitle": "Onboarding",
22-
"roomId": 1,
23-
"startTime":"2018-07-11T09:00:00Z",
24-
"endTime":"2018-07-11T09:45:00Z",
18+
"data": {
19+
"allEventsByRoom": {
20+
"events": [
21+
{
22+
"eventTitle": "Onboarding",
23+
"roomId": 1,
24+
"startTime": "2018-07-11T09:00:00Z",
25+
"endTime": "2018-07-11T09:45:00Z",
26+
}
27+
]
2528
}
26-
]
2729
}
28-
}
2930
}
3031

3132
query_all_events_by_room_without_dates = '''
@@ -39,22 +40,22 @@
3940
}
4041
}
4142
}
42-
43+
4344
'''
4445

4546
query_all_events_by_room_without_dates_response = {
46-
"data": {
47-
"allEventsByRoom": {
48-
"events": [
49-
{
50-
"eventTitle": "Onboarding",
51-
"roomId": 1,
52-
"startTime":"2018-07-11T09:00:00Z",
53-
"endTime":"2018-07-11T09:45:00Z",
47+
"data": {
48+
"allEventsByRoom": {
49+
"events": [
50+
{
51+
"eventTitle": "Onboarding",
52+
"roomId": 1,
53+
"startTime": "2018-07-11T09:00:00Z",
54+
"endTime": "2018-07-11T09:45:00Z",
55+
}
56+
]
5457
}
55-
]
5658
}
57-
}
5859
}
5960

6061
query_all_events_by_room_without_callendar_id = '''
@@ -68,10 +69,10 @@
6869
}
6970
}
7071
}
71-
72+
7273
'''
7374

74-
query_all_events_by_room_with_invalid_calendar_id = '''
75+
query_all_events_by_room_with_invalid_calendar_id = '''
7576
query{
7677
allEventsByRoom(calendarId:"andela.com_36303638353035313430@resource.calendar.google.com"){
7778
events{
@@ -82,5 +83,5 @@
8283
}
8384
}
8485
}
85-
86+
8687
'''
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from helpers.database import database_uri
2+
from sqlalchemy import create_engine, MetaData, and_
3+
from datetime import timedelta, datetime
4+
import celery
5+
6+
7+
@celery.task(name='clean_archived_data.delete_archived_data')
8+
def delete_archived_data():
9+
"""
10+
This method deletes data that has been deleted for
11+
more than 30 days
12+
"""
13+
database_engine = create_engine(database_uri)
14+
metadata = MetaData()
15+
metadata.reflect(bind=database_engine)
16+
17+
for table in reversed(metadata.sorted_tables):
18+
try:
19+
now = datetime.now()
20+
delta = now - timedelta(days=30)
21+
statement = table.delete().where(
22+
and_(table.c.date_updated < delta, table.c.state == 'archived'))
23+
database_engine.execute(statement)
24+
except AttributeError:
25+
continue

0 commit comments

Comments
 (0)