Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

357
Vistas
Python Celery sincronización de cronjob inconsistente para la programación de tareas con la función ahora

La situación

Tengo una tarea de apio que estoy ejecutando en una zona horaria diferente para cada cliente.

Básicamente, para cada cliente en mi base de datos, obtengo la zona horaria y luego configuro la tarea de apio de esta manera.

 'schedule': crontab(minute=30, hour=14, nowfun=self.now_function)

Básicamente, lo que quiero es que la tarea se ejecute a las 14:30, en la zona horaria del cliente. De ahí la función now_.

Mi now_function solo obtiene la hora actual con la zona horaria del cliente.

 def now_function(self): """ return the now function for the task this is used to compute the time a task should be scheduled for a given customer """ return datetime.now(timezone(self.customer.c_timezone))

Qué está pasando

Obtengo inconsistencias en el tiempo de ejecución de la tarea, a veces se ejecutan a la hora prevista, así que digamos a las 14:30 en la zona horaria del cliente, si la zona horaria es America/Chicago , se ejecuta a las 20:30 y ese es mi comportamiento esperado. .

Algunos otros días, funciona a las 14:30, que es la hora en UTC.

Estoy rastreando para ver si hay un patrón en el día en que la tarea se ejecuta en el momento correcto y el día en que las tarjetas se ejecutan en el momento incorrecto.

información adicional

He intentado esto en apio 4.4.2 y 5.xx pero todavía tiene el mismo comportamiento.

Aquí está mi configuración de apio.

 CELERY_REDIS_SCHEDULER_URL = redis_instance_url logger.debug("****** CELERY_REDIS_SCHEDULER_URL: ", CELERY_REDIS_SCHEDULER_URL) logger.debug("****** environment: ", environment) redbeat_redis_url = CELERY_REDIS_SCHEDULER_URL broker_url = CELERY_REDIS_SCHEDULER_URL result_backend = CELERY_REDIS_SCHEDULER_URL task_serializer = 'pickle' result_serializer = 'pickle' accept_content = ['pickle'] enable_utc = False task_track_started = True task_send_sent_event = True

Puede notar que enable_utc está establecido en False .

  • Estoy usando la instancia de Redis de AWS para ejecutar mi tarea.
  • Estoy usando el programador RedBeatScheduler de este paquete para programar mis tareas.

Si alguien ha tenido este problema o me puede ayudar a reproducirlo, le estaré muy agradecido.

Otras ediciones:

  • Tengo otro cron para el mismo trabajo al mismo tiempo pero funcionando semanal y mensualmente pero están funcionando perfectamente.
 weekly_schedule : crontab(minute=30, hour=14, nowfun=self.now_function, day_of_week=1) monthly_schedule : crontab(minute=30, hour=14, nowfun=self.now_function, day_of_month=1)

Proyecto de muestra

Aquí hay un proyecto de muestra en GitHub si desea ejecutar y reproducir el problema.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

El codificador y decodificador de RedBeat no son compatibles nowfun .
Código fuente: https://github.com/sibson/redbeat/blob/e6d72e2/redbeat/decoder.py#L94-L102
El comportamiento que ve se describió anteriormente: sibson/redbeat#192 (comentario 756397651)

Puede subclasificar y reemplazar RedBeatJSONDecoder y RedBeatJSONEncoder .

Dado que nowfun tiene que ser JSON serializable, solo podemos admitir algunos casos especiales,
por ejemplo nowfun=partial(datetime.now, tz=pytz.timezone(self.customer.c_timezone))

 from datetime import datetime from functools import partial from celery.schedules import crontab import pytz from pytz.tzinfo import DstTzInfo from redbeat.decoder import RedBeatJSONDecoder, RedBeatJSONEncoder class CustomJSONDecoder(RedBeatJSONDecoder): def dict_to_object(self, d): if '__type__' not in d: return d objtype = d.pop('__type__') if objtype == 'crontab': if d.get('nowfun', {}).get('keywords', {}).get('zone'): d['nowfun'] = partial(datetime.now, tz=pytz.timezone(d.pop('nowfun')['keywords']['zone'])) return crontab(**d) d['__type__'] = objtype return super().dict_to_object(d) class CustomJSONEncoder(RedBeatJSONEncoder): def default(self, obj): if isinstance(obj, crontab): d = super().default(obj) if 'nowfun' not in d and isinstance(obj.nowfun, partial) and obj.nowfun.func == datetime.now: zone = None if obj.nowfun.args and isinstance(obj.nowfun.args[0], DstTzInfo): zone = obj.nowfun.args[0].zone elif isinstance(obj.nowfun.keywords.get('tz'), DstTzInfo): zone = obj.nowfun.keywords['tz'].zone if zone: d['nowfun'] = {'keywords': {'zone': zone}} return d return super().default(obj)

Reemplace las clases en redbeat.schedulers :

 from redbeat import schedulers schedulers.RedBeatJSONDecoder = CustomJSONDecoder schedulers.RedBeatJSONEncoder = CustomJSONEncoder
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda