Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ of those changes to CLEARTYPE SRL.
| [@5tefan](https://github.com/5tefan/) | Stefan Codrescu |
| [@kuba-lilz](https://github.com/kuba-lilz/) | Jakub Kolodziejczyk |
| [@dbowring](https://github.com/dbowring/) | Daniel Bowring |
| [@bagowix](https://github.com/bagowix/) | Bogdan Galushko |
| [@olii](https://github.com/olii) | Oliver Nemček |
| [@bartvanandel](https://github.com/bartvanandel) | Bart van Andel |
| [@LincolnPuzey](https://github.com/LincolnPuzey) | Lincoln Puzey |
Expand Down
72 changes: 72 additions & 0 deletions examples/use_actors_from_different_files/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Using Actors from Different Files

## Overview

If you want to use actors from different files in your project, you must ensure that all
actors are properly initialized and visible to Dramatiq. This example demonstrates one
possible way to set up a project with multiple actor files and run them through the
Dramatiq CLI.

## Project Structure

```text
project/
├── actors/
│ ├── __init__.py
│ ├── bar.py
│ ├── foo.py
├── main.py
├── my_broker.py
```

- `actors/`: Contains actor definitions (`foo.py`, `bar.py`).
- `my_broker.py`: Initializes the broker.
- `main.py`: Application that publishes messages.

## Steps to Run

1. **Run the Dramatiq worker**:

In a terminal, start a worker with the following command

```shell
dramatiq my_broker actors
```

It is important to note:
* The first argument must be the module that initializes the Broker.
Because we are using a plain module name, it must call `set_broker()`.
* The subsequent arguments are extra modules to import that contain actor definitions.
In this case, only our `actors` module.

2. **Publish tasks by running the application**:

In another terminal, run the application that publishes some messages.
This could be a webserver, or a cron-like scheduler.
In this example it is a simple script.

```shell
python main.py
```

3. **Check the logs in the Dramatiq worker terminal**:

Back in the first terminal, check the worker logs to see that the actors have run.

```text
Bar task done.
Foo task done.
```

## Conclusion

This example is just one way of organizing actors into multiple files, but not the only way.

The two key rules to remember are:

1. Call `set_broker()` before importing any module that uses `@actor`.
This ensures that `@actor` will use the correct Broker.
This can be enforced by importing your broker-defining module in any actor-defining module,
like in this example.
2. Modules that are passed to the worker command line must import (directly or indirectly)
all actors. This ensures that the dramatiq worker is aware of all actors.
7 changes: 7 additions & 0 deletions examples/use_actors_from_different_files/actors/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Module to define actors"""

# Import actors from submodules to ensure they are registered when this `actors` module is imported.
from .bar import bar_task
from .foo import foo_task

__all__ = ["bar_task", "foo_task"]
9 changes: 9 additions & 0 deletions examples/use_actors_from_different_files/actors/bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import dramatiq

# Import my_broker module to ensure set_broker() is called before @actor is used.
import my_broker


@dramatiq.actor(broker=my_broker.rabbitmq_broker)
def bar_task():
print("Bar task done.")
9 changes: 9 additions & 0 deletions examples/use_actors_from_different_files/actors/foo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import dramatiq

# Import my_broker module to ensure set_broker() is called before @actor is used.
import my_broker


@dramatiq.actor(broker=my_broker.rabbitmq_broker)
def foo_task():
print("Foo task done.")
15 changes: 15 additions & 0 deletions examples/use_actors_from_different_files/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Import Broker first so it is set up.
import my_broker # noqa: F401

# Import actors after broker.
import actors


def my_app():
"""Basic application that publishes some messages."""
actors.bar_task.send()
actors.foo_task.send()


if __name__ == "__main__":
my_app()
12 changes: 12 additions & 0 deletions examples/use_actors_from_different_files/my_broker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import dramatiq
from dramatiq.brokers.rabbitmq import RabbitmqBroker
from dramatiq.middleware import CurrentMessage

# Set up Broker (and any custom Middleware)
rabbitmq_broker = RabbitmqBroker(url="amqp://guest:guest@localhost:5672")
rabbitmq_broker.add_middleware(CurrentMessage())

# Declare your Broker.
# IMPORTANT: This must run before importing any module that uses the @actor decorator.
# This is because @actor will immediately look up the Broker to associate the Actor with it.
dramatiq.set_broker(rabbitmq_broker)