π§ Dynamic Topics¶
Dispytch makes event routing flexible and expressive through dynamic topics. This allows you to define parameterized
topic structures like user.{user_id}.notification
and bind them directly to your handler function arguments. Whether
you're building per-tenant pipelines, user-specific notifications, or fine-grained subscriptions, dynamic topics are a
useful tool in Dispytch.
π What Are Dynamic Topics?¶
Dynamic topics are topic patterns that contain segments identified by curly braces, e.g.:
1 |
|
π οΈ Use Cases¶
Some common use cases include:
- User-specific channels β
user.{user_id}.notification
- Tenant or organization scoping β
tenant.{tenant_id}.events
- Versioned event streams β
service.{version}.log
π§― Broker Compatibility¶
Dynamic topics are supported with all brokers in Dispytch. However, keep in mind:
- Redis (with
psubscribe
) and AMQP (with topic exchange routing) are well-suited due to native support for wildcards. -
Kafka is technically compatible but not ideal for dynamic topic models due to:
- Static topic creation (topics must exist upfront)
- No wildcard subscription
- Poor scalability with high topic cardinality
If you're using Kafka, prefer fewer topics and use event payloads for context and partitions for scalability. But if your use case truly needs dynamic topics (e.g., for multi-tenancy separation), you can use dynamic topics carefully.
π§© Defining Dynamic Segments with TopicSegment()
¶
You can bind dynamic parts of the topic to function parameters using TopicSegment
.
Here are three ways to use it:
1 2 |
|
1 2 |
|
Equivalent to the first form, but useful if you forget the parentheses.
1 2 |
|
You're not allowed to forget the parentheses using this one xD
πͺ Aliases in Dynamic Segments¶
By default, Dispytch binds the segment name in the topic (e.g., user_id
) to the parameter name in your function.
You can override this using aliases.
π·οΈ alias
¶
Sets the name that Dispytch should expect in the topic string.
1 2 |
|
In this case, the topic should be:
1 |
|
Even though your handler uses uid
, Dispytch will map user_id
from the topic to it.
π§ͺ validation_alias
¶
You can also use validation_alias
1 2 |
|
π₯· Both alias
and validation_alias
¶
What if you use both? validation_alias
takes precedence for parsing values from the topic.
1 2 |
|
- Topic segment:
user.{user_id}
- Handler parameter:
user
- Dispytch looks for
user_id
in the topic (notignored
)
βοΈ Example: User-Specific Notifications with Redis¶
1 2 3 4 5 6 7 |
|
Given Topic: "user.42.notification"
Dispytch will extract user_id=42
and pass it to the handler.
βοΈ Example: Using Aliases¶
1 2 3 |
|
Here, Dispytch maps {uid}
in the topic to the user_id
parameter.
π Event Definition¶
On the producer side, this looks like:
1 2 3 4 5 6 7 8 9 |
|
This allows you to emit events with dynamic topics.
π€ Emitting Dynamic Events¶
1 2 |
|
Dispytch will automatically interpolate the topic:
1 |
|
π§ͺ Validating Topic Parameters¶
Dynamic topic segments in Dispytch aren't just dumb markers. Under the hood, TopicSegment()
has the properties of
a Pydantic Field
, which means you can apply validation constraints directly to values extracted from the
topic.
This is useful when:
- You want to restrict allowed values (e.g., whitelisting with
Literal
) - You want to apply numeric bounds or type checks (e.g.,
le=100
,gt=0
) - You want to fail early if a topic segment is invalid
βοΈ Example: Whitelisting with Literal
¶
You can define a handler that only accepts certain literal values:
1 2 3 4 5 6 |
|
If the incoming topic contains anything else β like weirdvalue
β validation fails.
βοΈ Example: Range Constraints¶
You can also enforce constraints like le
(less than or equal):
1 2 |
|
If the topic resolves to value=130
, validation fails and Dispytch raises an error before calling the handler.
π Topic Delimiters in EventListener
¶
When using dynamic topics, Dispytch needs a way to split topic strings into segments β this is done using the
topic_delimiter
argument in the EventListener
.
1 |
|
This tells Dispytch to treat topic segments as dot-separated:
1 |
|
The topic_delimiter
is used both for matching incoming topics and for extracting values from dynamic segments.
β οΈ Important Caveat: Avoid Using the Delimiter in Substituted Values¶
When you emit or receive an event with a dynamic topic, substituted values must not contain the delimiter. For example:
1 |
|
With topic_delimiter='.'
, using value=7.45
would result in:
1 |
|
This will break matching β because Dispytch will incorrectly split it into:
1 |
|
β DO:¶
Use values like 745
, user_45
, or strings that donβt include the delimiter.
β DON'T:¶
Use values that contain the delimiter, like 7.45
with '.'
or "foo/bar"
with '/'
.
π Broker-Specific Delimiter Constraints¶
Some brokers enforce a specific topic delimiter that cannot be changed:
- RabbitMQ: Uses
.
(dot) as the hard-coded separator for topic exchanges. - Kafka: Does not split topics by delimiter; full topic names are atomic.
- Redis (pubsub): Allows
psubscribe
with glob patterns, so any delimiter works, but be consistent.
Make sure to align your topic_delimiter
choice with your broker's behavior.