Skip to content

Commit f7d27fc

Browse files
Ostap-Zherebetskyicslzchen
authored andcommitted
Implement notifications cleanup task with batch deletion and configurable batch size
1 parent 2972e89 commit f7d27fc

2 files changed

Lines changed: 36 additions & 10 deletions

File tree

notifications/tasks.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -497,18 +497,42 @@ def send_no_addon_email(self, dry_run=False, **kwargs):
497497

498498
@celery_app.task(bind=True, name='notifications.tasks.notifications_cleanup_task')
499499
def notifications_cleanup_task(self, dry_run=False, **kwargs):
500-
"""Remove old notifications and email tasks from the database."""
501-
500+
"""Entry point for notifications and email tasks cleanup task."""
502501
cutoff_date = timezone.now() - settings.NOTIFICATIONS_CLEANUP_AGE
503-
old_notifications = Notification.objects.filter(sent__lt=cutoff_date)
504-
old_email_tasks = EmailTask.objects.filter(created_at__lt=cutoff_date)
505-
506502
if dry_run:
507-
notifications_count = old_notifications.count()
508-
email_tasks_count = old_email_tasks.count()
503+
notifications_count = Notification.objects.filter(sent__lt=cutoff_date).count()
504+
email_tasks_count = EmailTask.objects.filter(created_at__lt=cutoff_date).count()
509505
logger.info(f'[Dry Run] Notifications Cleanup Task: {notifications_count} notifications and {email_tasks_count} email tasks would be deleted.')
510506
return
511507

512-
deleted_notifications_count, _ = old_notifications.delete()
513-
deleted_email_tasks_count, _ = old_email_tasks.delete()
514-
logger.info(f'Notifications Cleanup Task: Deleted {deleted_notifications_count} notifications and {deleted_email_tasks_count} email tasks older than {cutoff_date}.')
508+
delete_batch.delay('osf', 'Notification', {'sent__lt': cutoff_date}, batch_size=settings.NOTIFICATIONS_CLEANUP_BATCH_SIZE)
509+
delete_batch.delay('osf', 'EmailTask', {'created_at__lt': cutoff_date}, batch_size=settings.NOTIFICATIONS_CLEANUP_BATCH_SIZE)
510+
511+
512+
@celery_app.task(bind=True, name='notifications.tasks.delete_batch')
513+
def delete_batch(
514+
self,
515+
app_label,
516+
model_name,
517+
filters,
518+
order_field='id',
519+
batch_size=10000
520+
):
521+
Model = apps.get_model(app_label, model_name)
522+
523+
ids = list(
524+
Model.objects
525+
.filter(**filters)
526+
.order_by(order_field)
527+
.values_list('id', flat=True)[:batch_size]
528+
)
529+
530+
if not ids:
531+
logger.info(f'{model_name} cleanup finished')
532+
return
533+
534+
deleted, _ = Model.objects.filter(id__in=ids).delete()
535+
536+
logger.info(f'Deleted {deleted} rows from {model_name}')
537+
538+
delete_batch.delay(app_label, model_name, filters, order_field, batch_size)

website/settings/defaults.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,10 @@ def parent_dir(path):
186186
NO_ADDON_WAIT_TIME = timedelta(weeks=8) # 2 months for "Link an add-on to your OSF project" email
187187
NO_LOGIN_WAIT_TIME = timedelta(weeks=52) # 1 year for "We miss you at OSF" email
188188
NO_LOGIN_OSF4M_WAIT_TIME = timedelta(weeks=52) # 1 year for "We miss you at OSF" email to users created from OSF4M
189+
189190
# TODO: this will be changed to 12 weeks (3 month) with ENG-9856
190191
NOTIFICATIONS_CLEANUP_AGE = timedelta(weeks=52) # 1 year to clean up old notifications and email tasks
192+
NOTIFICATIONS_CLEANUP_BATCH_SIZE = 10000 # Batch size for notifications and email tasks cleanup
191193

192194
# Configuration for "We miss you at OSF" email (`NotificationTypeEnum.USER_NO_LOGIN`)
193195
# Note: 1) we can gradually increase `MAX_DAILY_NO_LOGIN_EMAILS` to 10000, 100000, etc. or set it to `None` after we

0 commit comments

Comments
 (0)