π§ Dynamic Routes¶
Dispytch makes event routing flexible and expressive through dynamic routes. This allows you to define parameterized
route structures like user.{user_id}.notification and bind them directly to your handler function arguments.
π What Are Dynamic Routes?¶
Dynamic routes are route 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 routing is 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 routing 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 routing.
Dynamic routing is an application-level feature of Dispytch, independent of your brokerβs internal routing. Dispytch can only process the events your broker is configured to deliver
π§© Defining Dynamic Segments with SubscriptionParam()¶
You can bind dynamic parts of the event route to function parameters using SubscriptionParam.
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 subscription (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 EventSubscription.
1 2 3 | |
Even though your handler uses uid, Dispytch will map user_id from the subscription pattern to it.
π§ͺ validation_alias¶
You can also use validation_alias. If you use both alias and validation_alias then validation_alias takes
precedence.
1 2 3 | |
βοΈ Example: User-Specific Notifications with Redis¶
1 2 3 4 5 6 7 8 9 10 | |
Given Topic: "user.42.notification"
Dispytch will extract user_id=42 and pass it to the handler.
βοΈ Example: Using Aliases¶
1 2 3 4 5 6 7 8 9 10 | |
Here, Dispytch maps {uid} in the channel to the user_id parameter.
π Event Definition¶
On the producer side, this looks like:
1 2 3 4 5 6 7 8 9 10 | |
π€ Emitting Dynamically Routed Events¶
1 2 3 | |
Dispytch will automatically interpolate the route:
1 | |
π§ͺ Validating Subscription Parameters¶
Under the hood, SubscriptionParam has the properties of a Pydantic Field,
which means you can apply validation constraints directly to values extracted from the route.
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 route 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 route 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 route resolves to value=130, validation fails and Dispytch raises an error before calling the handler.
π Route Delimiter in EventDispatcher¶
When using dynamic routes, Dispytch needs a way to split subscription patterns into segments β
this is done using the route_delimiter argument in the EventDispatcher.
1 | |
This tells Dispytch to treat route segments as dot-separated:
1 | |
β οΈ Important Caveat: Avoid Using the Delimiter in Substituted Values¶
When you emit or receive an event with a dynamic route, substituted values must not contain the delimiter. For example:
1 | |
With route_delimiter='.', using value=7.45 would result in:
1 | |
This will break matching β because Dispytch will incorrectly split it into:
1 | |
Avoid using values that contain your delimiter, like 7.45 with '.' or "user_id" with '_'.
π Broker-Specific Delimiter Constraints¶
Some brokers enforce a specific delimiter for their internal routing that cannot be changed:
- RabbitMQ: Uses
.(dot) as the hard-coded separator for wildcards. - Kafka: Does not split topics by delimiter; full topic names are atomic.
- Redis (PubSub): Allows
psubscribewith glob patterns, so any delimiter works, but be consistent.
Make sure to align your route_delimiter choice with your broker's routing behavior.