Skip to content

Commit 5ddfa30

Browse files
authored
Replace Celery with Dramatiq (#223)
* Fixes the sync/async tracing decorator * Replaces Celery with Dramatiq (smaller, easier to use, supporting asyncio) --------- Signed-off-by: Federico Busetti <[email protected]>
1 parent 28da60c commit 5ddfa30

30 files changed

+945
-623
lines changed

.idea/bootstrap-python-fastapi.iml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Dockerfile

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ RUN make dev-dependencies
5151
# when signals are propagated, we disable it in dev image default CMD
5252
CMD ["uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "--factory", "--reload"]
5353

54-
# Installs requirements to run production celery application
55-
FROM base_builder AS celery_builder
54+
# Installs requirements to run production dramatiq application
55+
FROM base_builder AS dramatiq_builder
5656
RUN poetry install --no-root
5757

5858
# Installs requirements to run production http application
@@ -68,7 +68,7 @@ COPY --chown=nonroot:nonroot poetry.lock .
6868
COPY --chown=nonroot:nonroot src/alembic ./alembic
6969
COPY --chown=nonroot:nonroot src/domains ./domains
7070
COPY --chown=nonroot:nonroot src/gateways ./gateways
71-
COPY --chown=nonroot:nonroot src/common ./bootstrap
71+
COPY --chown=nonroot:nonroot src/common ./common
7272
COPY --chown=nonroot:nonroot src/alembic.ini .
7373
COPY --chown=nonroot:nonroot Makefile .
7474

@@ -79,9 +79,10 @@ COPY --chown=nonroot:nonroot src/http_app ./http_app
7979
# Run CMD using array syntax, so it's uses `exec` and runs as PID1
8080
CMD ["opentelemetry-instrument", "uvicorn", "http_app:create_app", "--host", "0.0.0.0", "--port", "8000", "--factory"]
8181

82-
# Copy the celery python package and requirements from relevant builder
83-
FROM base_app AS celery_app
84-
COPY --from=celery_builder /poetryvenvs /poetryvenvs
85-
COPY --chown=nonroot:nonroot src/celery_worker ./celery_worker
82+
# Copy the dramatiq python package and requirements from relevant builder
83+
FROM base_app AS dramatiq_app
84+
COPY --from=dramatiq_builder /poetryvenvs /poetryvenvs
85+
COPY --chown=nonroot:nonroot src/dramatiq_worker ./dramatiq_worker
8686
# Run CMD using array syntax, so it's uses `exec` and runs as PID1
87-
CMD ["opentelemetry-instrument", "celery", "-A", "celery_worker:app", "worker", "-l", "INFO"]
87+
# TODO: Review processes/threads
88+
CMD ["opentelemetry-instrument", "dramatiq", "-p", "1", "-t", "1", "dramatiq_worker"]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ and [SOLID principles](https://en.wikipedia.org/wiki/SOLID).
2121
This template provides out of the box some commonly used functionalities:
2222

2323
* API Documentation using [FastAPI](https://fastapi.tiangolo.com/)
24-
* Async tasks execution using [Celery](https://docs.celeryq.dev/en/stable/index.html)
24+
* Async tasks execution using [Dramatiq](https://dramatiq.io/index.html)
2525
* Repository pattern for databases using [SQLAlchemy](https://www.sqlalchemy.org/) and [SQLAlchemy bind manager](https://febus982.github.io/sqlalchemy-bind-manager/stable/)
2626
* Database migrations using [Alembic](https://alembic.sqlalchemy.org/en/latest/) (configured supporting both sync and async SQLAlchemy engines)
2727
* [TODO] Producer and consumer to emit and consume events using [CloudEvents](https://cloudevents.io/) format on [Confluent Kafka](https://docs.confluent.io/kafka-clients/python/current/overview.html)
@@ -44,7 +44,7 @@ Using Docker:
4444
* `make containers`: Build containers
4545
* `docker compose run --rm dev make migrate`: Run database migrations
4646
* `docker compose up dev`: Run HTTP application with hot reload
47-
* `docker compose up celery-worker`: Run the celery worker
47+
* `docker compose up dramatiq-worker`: Run the dramatiq worker
4848
* `docker compose run --rm test`: Run test suite
4949

5050
Locally:

docker-compose.yaml

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,16 @@ services:
88
redis:
99
image: redis
1010

11-
celery-worker:
11+
dramatiq-worker:
1212
build:
1313
dockerfile: Dockerfile
1414
context: .
15-
target: celery_app
15+
target: dramatiq_app
1616
environment:
17-
OTEL_SERVICE_NAME: "bootstrap-fastapi-worker"
18-
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4317"
19-
CELERY__broker_url: "redis://redis:6379/0"
20-
CELERY__result_backend: "redis://redis:6379/1"
21-
working_dir: "/app/src"
22-
volumes:
23-
- '.:/app'
24-
depends_on:
25-
- redis
26-
- otel-collector
27-
- celery-beat
28-
29-
celery-beat:
30-
build:
31-
dockerfile: Dockerfile
32-
context: .
33-
target: celery_app
34-
environment:
35-
OTEL_SERVICE_NAME: "bootstrap-fastapi-worker"
17+
WATCHFILES_FORCE_POLLING: true
18+
OTEL_SERVICE_NAME: "bootstrap-fastapi-dramatiq-worker"
3619
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4317"
37-
CELERY__broker_url: "redis://redis:6379/0"
38-
CELERY__result_backend: "redis://redis:6379/1"
20+
DRAMATIQ__REDIS_URL: "redis://redis:6379/0"
3921
working_dir: "/app/src"
4022
volumes:
4123
- '.:/app'
@@ -44,12 +26,14 @@ services:
4426
- otel-collector
4527
command:
4628
- opentelemetry-instrument
47-
- celery
48-
- -A
49-
- celery_worker:app
50-
- beat
51-
- -l
52-
- INFO
29+
- dramatiq
30+
- --watch
31+
- .
32+
- -p
33+
- "1"
34+
- -t
35+
- "1"
36+
- dramatiq_worker
5337

5438
dev:
5539
build:
@@ -60,8 +44,6 @@ services:
6044
WATCHFILES_FORCE_POLLING: true
6145
OTEL_SERVICE_NAME: "bootstrap-fastapi-dev"
6246
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4317"
63-
CELERY__broker_url: "redis://redis:6379/0"
64-
CELERY__result_backend: "redis://redis:6379/1"
6547
ports:
6648
- '8000:8000'
6749
working_dir: "/app/src"
@@ -93,8 +75,6 @@ services:
9375
environment:
9476
OTEL_SERVICE_NAME: "bootstrap-fastapi-http"
9577
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4317"
96-
CELERY__broker_url: "redis://redis:6379/0"
97-
CELERY__result_backend: "redis://redis:6379/1"
9878
ports:
9979
- '8001:8000'
10080
volumes:

docs/architecture.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ and the persistence layer.
1111
This is a high level list of the packages in this application template:
1212

1313
* `alembic` (database migration manager)
14-
* `celery_worker` (async tasks runner)
14+
* `dramatiq_worker` (async tasks runner)
1515
* `common` (some common boilerplate initialisation shared by all applications )
1616
* `http_app` (http presentation layer)
1717
* `gateways` (database connection manager, repository implementation, event emitter, etc.)
@@ -31,7 +31,7 @@ This is a high level representation of the nested layers in the application:
3131
flowchart TD
3232
subgraph "Framework & Drivers + Interface Adapters"
3333
alembic
34-
celery_worker
34+
dramatiq_worker
3535
http_app
3636
gateways
3737
subgraph domains.books["Use Cases"]
@@ -52,7 +52,7 @@ flowchart TD
5252
end
5353
5454
alembic ~~~ domains.books
55-
celery_worker ~~~ domains.books
55+
dramatiq_worker ~~~ domains.books
5656
http_app ~~~ domains.books
5757
gateways ~~~ domains.books
5858
@@ -69,7 +69,7 @@ A more detailed view showing the class dependencies and the absence of cyclical
6969

7070
```mermaid
7171
flowchart TD
72-
celery_worker
72+
dramatiq_worker
7373
http_app
7474
subgraph gateways
7575
SQLAlchemyRepository
@@ -99,8 +99,8 @@ flowchart TD
9999
end
100100
end
101101
102-
celery_worker-->domain_boundary
103-
celery_worker-->dto
102+
dramatiq_worker-->domain_boundary
103+
dramatiq_worker-->dto
104104
http_app-->domain_boundary
105105
http_app-->dto
106106
domain_boundary-->domain_logic

docs/dockerfile.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,22 @@ flowchart TD
6161
http_builder-->http_app
6262
end
6363
64-
subgraph Celery
65-
celery_builder["Celery builder
64+
subgraph Dramatiq
65+
dramatiq_builder["Dramatiq builder
6666
============
6767
Installs requirements for
68-
Celery worker in a virtualenv"]
69-
celery_app["HTTP app
68+
Dramatiq worker in a virtualenv"]
69+
dramatiq_app["HTTP app
7070
========
71-
Copies Celery worker app,
71+
Copies Dramatiq worker app,
7272
shared logic
7373
and requirements
7474
from previous containers"]
75-
celery_builder-->celery_app
75+
dramatiq_builder-->dramatiq_app
7676
end
7777
7878
base_builder-->http_builder
79-
base_builder-->celery_builder
79+
base_builder-->dramatiq_builder
8080
base_app-->http_app
81-
base_app-->celery_app
81+
base_app-->dramatiq_app
8282
```

docs/packages/bootstrap.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Bootstrap
22

33
The `bootstrap` package contains logic that is shared among the external layer
4-
(i.e. `http_app`, `celery_worker`, etc.).
4+
(i.e. `http_app`, `dramatiq_worker`, etc.).
55

66
It contains the following submodules and packages (and related responsibilities):
77

88
* `bootstrap.bootstrap`: The application initialisation logic (database, logging,
9-
celery tasks) necessary to run the domain logic. It uses `bootstrap.config` and
9+
dramatiq tasks) necessary to run the domain logic. It uses `bootstrap.config` and
1010
`bootstrap.di_container` subpackages. It does not contain the specific HTTP
1111
framework initialisation (or other frameworks such as GRPC).
1212
* `bootstrap.config`: The application config models, based on `BaseSettings`

docs/packages/celery_worker.md

Lines changed: 0 additions & 11 deletions
This file was deleted.

docs/packages/domains.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ and can be used to bootstrap the application:
4343
to bootstrap the SQLAlchemy imperative mapping in `bootstrap.storage.SQLAlchemy`
4444
package.
4545
* The `domains.book._service` contains the `BookService` implementation.
46-
* The `domains.book._tasks` contains the implementation of celery tasks
46+
* The `domains.book._tasks` contains the implementation of dramatiq tasks
4747
for operations that can be queued without waiting for a result (e.g.
4848
send an email, invalidate cache).

0 commit comments

Comments
 (0)