Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

329
Views
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 esperada, 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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!