Search code examples
pythoncelerydjango-celeryworker

Is it possible to deadlock a worker by accumulating scheduled tasks?


By code:

@celery.task()
def some_recursive_task():
    # Do some stuff and schedule it to run again later
    # Note that the next run is not scheduled in a fixed basis, like crontabs
    # but based on history of some object
    # Actual task is found here: 
    # https://github.com/rafaelsierra/cheddar/blob/master/src/feeds/tasks.py#L39
    # Then it call himself again
    countdown = bla.get_countdown()
    some_recursive_task.apply_async(countdown=countdown)

This task will run withing the next 10 minutes and 12 hours, but this task also calls another tasks that should run now, one for downloading stuff and other to parse it.

The problem is that the main function is called for every single record on database, let's assume a few hundred tasks running, but, considering that those task runs in average every few hours the amount of tasks is not a big deal.

The problem starts when I try to run this with a single worker, when I start the worker, I put it to run all queues and set 8 concurrent workers, then it starts an begin to acknowledge the tasks, but it seems that, no matter how far in future a task is set to, a worker will get it and wait for the its scheduled run, meaning that this worker is locked until then.

I know that I can just split the two other functions into different queues, which I already did, but my concern is that workers will acknowledge tasks to run 12 hours ahead and will not run the ones it should in 30 minutes.

Shouldn't workers ignore scheduled tasks until its time and run the ones that are just delayed without a time?

I don't think, or don't know how, periodic tasks is a solution.


Solution

  • See the points 5 & 6 there. Please, keep in mind that countdown is no different from eta argument of the task.

    In short you're right. Single worker (or any amount of workers) should not block on scheduled (eta or countdown) tasks.

    How can you tell that workers are locked? The scheduled tasks are prefetched from the queue, but not acknowledged until they are executed.

    Also, please keep in mind all scheduled tasks are kept in RAM until they're executed. You would like them to be as light as possible. From what I understand the scheduled task doesn't pass around big chunks of data, probably only some URI, so this shouldn't be a problem.

    The links you've pasted return 404. Are you sure cheddar isn't a private repository?