import datetime from celery.task.schedules import crontab from django.apps import apps from orchestra.contrib.tasks import periodic_task from . import settings @periodic_task(run_every=crontab(hour=4, minute=30), name='orders.cleanup_metrics') def cleanup_metrics(): from .models import MetricStorage, Order Service = apps.get_model(settings.ORDERS_SERVICE_MODEL) # General cleaning: order.billed_on-delta general = 0 delta = datetime.timedelta(days=settings.ORDERS_BILLED_METRIC_CLEANUP_DAYS) for order in Order.objects.filter(billed_on__isnull=False): epoch = order.billed_on-delta try: latest = order.metrics.filter(updated_on__lt=epoch).latest('updated_on') except MetricStorage.DoesNotExist: pass else: general += order.metrics.exclude(pk=latest.pk).filter(updated_on__lt=epoch).count() order.metrics.exclude(pk=latest.pk).filter(updated_on__lt=epoch).only('id').delete() # Reduce monthly metrics to latest monthly = 0 monthly_services = Service.objects.exclude(metric='').filter( billing_period=Service.MONTHLY, pricing_period=Service.BILLING_PERIOD ) for service in monthly_services: for order in Order.objects.filter(service=service): dates = order.metrics.values_list('created_on', flat=True) months = set((date.year, date.month) for date in dates) for year, month in months: metrics = order.metrics.filter( created_on__year=year, created_on__month=month, updated_on__year=year, updated_on__month=month) try: latest = metrics.latest('updated_on') except MetricStorage.DoesNotExist: pass else: monthly += metrics.exclude(pk=latest.pk).count() metrics.exclude(pk=latest.pk).only('id').delete() return (general, monthly)