Skip to main content

Celery Dyrygent

Python 3.6 Unit Tests Integration Tests

This project aims to support full DAG workflow processing. It's designed as celery extension and uses celery as an execution backend. Celery-dyrygent is released under modified BSD license. See license

What is it?

The reasons behind this project so as the implementation details were described in the following blogpost https://www.ovh.com/blog/doing-big-automation-with-celery/

What is a DAG workflow?

DAG is a shortcut for Directed Acyclic Graph. While DAG workflow would be any combination of celery primitives:

  • groups
  • chains
  • chords

Celery Dyrygent is able to process any kind of DAG workflows.

Why not to use native celery stuff?

Celery struggles a bit with complex workflows built from combining primitives. The execution might be unreliable, there are a lot of corner cases where workflow might not work as desired. Serialization of complex workflows causes memory issues. Some of the encountered problems which aren't solved (celery 4.2.1):

How does it work?

The whole workflow machinery works simialar to chord_unlock repeating celery task which waits till some tasks are done (header) and then executes further tasks (body). Celery Dyrygent introduces a workflow processor task which orchestrates an execution of a whole workflow. Once the workflow is started the workflow processor task is repeated till the workflow execution is done or till some TTL timestamp is reached (not to repeat indefinitely). The workflow processor schedules the execution of tasks according to their relations, retries itself, then checks if the tasks are done so the new ones can be scheduled, repeat. That's it, the idea is quite simple.

Advantages

  • execution part is done by Celery, so all celery machinery with its features is available (retries, countdowns, etc.)
  • each workflow is executed in the same way
  • Celery operates on simple tasks only - no nested structures which causes troubles
  • link error for whole workflow can be implemented
  • finalizing task for whole workflow can be implemented (e.g. do something always when workflow finishes)
  • workflow execution is SOLID and RELIABLE
  • it's possible to track progress through signals (might need to implement a new signal for each tick)

Drawbacks

  • At the moment workflow processor doesn't pass task results from precedign tasks to following tasks (can be implemented, not implemented at the moment).
  • Workflow processor task is doing repeating ticks (like celery chord unlock) and new tasks are scheduled only within the ticks. This may result in noticeably longer execution time of task chains (e.g. if ticks are done each 2s, next task in chain will only be each 2s)
  • Reliable result backend has to be enabled

How to use it?

Which celery versions are supported?

  • celery 3.1.25
  • celery 4.2.1
  • probably any celery 4.x

Integration

Initialize workflows

You need to register workflow processor task in your celery app

from celery_dyrygent.tasks import register_workflow_processor

app = Celery() #  your celery application instance

workflow_processor = register_workflow_processor(app)

Use workflow on you celery canvas

Workflows can consume celery canvas to properly build internal relations

from celery_dyrygent.workflows import Workflow

canvas = celery.chain() | celery.chord() #  define your canvas using native celery mechanisms

wf = Workflow()
wf.add_celery_canvas(canvas)
wf.apply_async()

Workflow processor task will be scheduled holding all signatures from canvas and their relations. It will execute signatures according to their relations.

Signals support

Celery Dyrygent provides additional signals which can be used e.g. for tracking workflow progress. Following signals are available:

  • after_active_tick
  • on_finish
  • on_state_change

How to use signals?

When a signal is emitted all registered signal handlers are executed. In order to register signal handler you need to use Workflow.connect function. See examples below. The handler is called with two parameters: workflow instance and payload (optional).

Using on_state_change signal

Signal is emitted when workflow state changes. Supported states are:

  • INITIAL
  • RUNNING
  • SUCCESS
  • FAILURE
  • ERROR

Handler is called with two params:

  • workflow instance
  • payload - current state of a workflow
from celery_dyrygent.workflows import Workflow

@Workflow.connect('on_state_change')
def handle_state_change(workflow, payload):
    print(
        "Workflow {} has new state {}"
        .format(workflow.id, payload)
    )

Using on_finish signal

Signal is emitted when workflow is finished (or can't move forward due to failed tasks)

Handler params are:

  • workflow instance
  • paylod - None

Using after_active_tick

Signal is emitted when workflow has scheduled new tasks

Handler params are:

  • workflow instance
  • payload - None

Support for custom data

Both Workflowand WorkflowNode have a custom_payload dictionary member that can be used to store additional data. For example, one can use those dictionnary to store some application specific metadata.

...
wf = Workflow()
for task in task_list:
    sig = create_celery_task(task)
    sig.freeze()
    node = wf.add_signature(sig)
    node.custom_payload['user_id'] = task.user_id
...

Using celery task options

You can define custom options for your tasks, as defined in: https://docs.celeryproject.org/en/stable/reference/celery.app.task.html#celery.app.task.Task.apply_async

These options may be different between the workflow task and user tasks.

wf = Workflow(options={'priority': 10})
wf.add_celery_canvas(canvas)
wf.apply_async(options={'priority': 8})

TODO

  • Proper documentation (e.g. sphinx)
  • Python pip release

Release files for celery-dyrygent 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for celery-dyrygent 0.8.0
File Size Uploaded
celery-dyrygent-0.8.0.tar.gz 17.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for celery-dyrygent 0.8.0
File Interpreter ABI Platform
celery_dyrygent-0.8.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 34.2 kB

Release files / celery-dyrygent-0.8.0.tar.gz

Download URL celery-dyrygent-0.8.0.tar.gz
Size 17.9 kB
Tags Source
SHA-256 checksum
How to use checksums
bb90afd63b3e8aa8afccb4ec6c0ba68278db9c34fb4b32eea210585e66a92906
BLAKE2b-256 checksum
How to use checksums
5c0f6a9dc5f2165178d7bb7ea6f8512794355d7330519dcaf562c4cec5786b07
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

Release files / celery_dyrygent-0.8.0-py2.py3-none-any.whl

Download URL celery_dyrygent-0.8.0-py2.py3-none-any.whl
Size 16.3 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
4664093362973de60a4d1e24f889737c0293d17ad9faf8266fe07aaafaa4507c
BLAKE2b-256 checksum
How to use checksums
18b792d29d4dbceab8eefa2d6ee4a958175f76569e3f2078bb048f52c6290815
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page