"""
Configuración de Celery.

Dos colas y no una. El trabajo programado de un sitio grande son miles de
inspecciones que tardan horas; si compartieran cola con las acciones que alguien
acaba de disparar desde la pantalla, esas acciones esperarían detrás de todo el
lote nocturno y la interfaz parecería colgada.

Las tareas se reconocen al terminar, no al recibirlas: si un trabajador muere a
mitad de un lote, el trabajo vuelve a la cola en lugar de desaparecer. El precio
es que una tarea puede ejecutarse dos veces, y por eso todo lo que gasta cuota
pasa por el control de idempotencia.
"""

import os

from celery import Celery
from celery.schedules import crontab

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.dev')

app = Celery('index_relay')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()


@app.task(bind=True, ignore_result=True)
def debug_task(self):
    """Tarea de humo: confirma que el trabajador toma trabajo de la cola."""
    return f'ok desde {self.request.id}'


#: Trabajo diario. La hora está en la zona de presentación, no en UTC: «la
#: sincronización de la madrugada» tiene que ocurrir de madrugada para quien
#: mira el tablero, no para el reloj del servidor.
app.conf.beat_schedule = {
    # Antes que todo lo demás: si un dominio perdió el acceso, la sincronización
    # y la inspección de más abajo no tienen nada que hacer sobre él, y
    # enterarse primero evita gastar cupo en llamadas que van a fallar.
    'revalidar-acceso': {
        'task': 'apps.domains.tasks.revalidate_all_access',
        'schedule': crontab(hour='2', minute='0'),
        'options': {'queue': 'scheduled'},
    },
    'sincronizar-sitemaps': {
        'task': 'apps.sitemaps.tasks.sync_all_domains',
        'schedule': crontab(hour='3', minute='0'),
        'options': {'queue': 'scheduled'},
    },
    # El rendimiento en la búsqueda, un día por corrida.
    #
    # Va después de revalidar el acceso, por el mismo motivo que todo lo demás:
    # un sitio que perdió permiso no tiene nada que traer. Y no comparte el
    # presupuesto de cuota con la inspección de URLs —Search Analytics tiene
    # límite de tasa, no cupo diario—, así que su horario no compite con nada:
    # se lo separa media hora de los sitemaps sólo para no apilar dos tandas de
    # llamadas a Google en el mismo minuto.
    'sync-seo': {
        'task': 'apps.seo.tasks.sync_all_domains',
        'schedule': crontab(hour='3', minute='30'),
        'options': {'queue': 'scheduled'},
    },
    # El recorrido automático de las 4:00 queda **apagado**, por decisión del
    # owner. Se comenta y no se borra: la tarea, su cola y el bolsillo de cuota
    # automática siguen enteros, así que volver a encenderlo es descomentar esto
    # y nada más.
    #
    # Lo que cambia mientras esté apagado: **las URLs sólo se consultan a mano**,
    # desde «Query now», contra la reserva manual de 200 por día y por dominio.
    # Las 1.800 del bolsillo automático dejan de usarse —nadie las pide— y una
    # URL nueva no obtiene su primer dato hasta que alguien dispare una tanda.
    # 'inspeccionar-urls': {
    #     'task': 'apps.coverage.tasks.inspect_all_domains',
    #     'schedule': crontab(hour='4', minute='0'),
    #     'options': {'queue': 'scheduled'},
    # },
    # Aplica la retención de las sesiones ya cerradas. Sin esta entrada el plazo
    # declarado en la configuración no lo cumple nadie.
    'purgar-sesiones': {
        'task': 'apps.accounts.tasks.purge_sessions',
        'schedule': crontab(hour='5', minute='0'),
        'options': {'queue': 'scheduled'},
    },
    # Lo mismo para los archivos de exportación: el plazo declarado en la
    # configuración no lo cumple nadie sin una entrada que lo aplique.
    'purgar-exportaciones': {
        'task': 'apps.coverage.tasks.purge_exports',
        'schedule': crontab(hour='5', minute='30'),
        'options': {'queue': 'scheduled'},
    },
}
