Route Messages to Handlers with a Python Dict
This code demonstrates a simple message routing pattern using a dictionary to map topic keys to handler functions, with a default handler for unmatched topics.
Python code
35 linesdef route_message(message, routing_table):
"""Route a message to the correct handler based on the topic key."""
topic = message.get("topic", "default")
handler = routing_table.get(topic, routing_table.get("default"))
return handler(message)
def handle_orders(message):
return f"Orders handler processed: {message['payload']}"
def handle_payments(message):
return f"Payments handler processed: {message['payload']}"
def handle_unknown(message):
return f"Default handler processed: {message['payload']}"
if __name__ == "__main__":
routing_table = {
"orders": handle_orders,
"payments": handle_payments,
"default": handle_unknown,
}
messages = [
{"topic": "orders", "payload": {"id": 1, "item": "Widget"}},
{"topic": "payments", "payload": {"id": 1, "amount": 19.99}},
{"topic": "inventory", "payload": {"id": 1, "stock": 10}},
{"payload": {"action": "unknown"}},
]
for msg in messages:
print(route_message(msg, routing_table))
Output
Orders handler processed: {'id': 1, 'item': 'Widget'}
Payments handler processed: {'id': 1, 'amount': 19.99}
Default handler processed: {'id': 1, 'stock': 10}
Default handler processed: {'action': 'unknown'}
How it works
The route_message function uses the topic key from the message to look up the corresponding handler in the routing_table dictionary. If the topic is missing or not found, it falls back to the 'default' handler, ensuring every message is processed. This pattern decouples message sources from their processing logic, making it easy to add new topics by simply extending the dictionary. The handlers are plain functions that receive the full message, allowing them to access any part of the message payload.
Common mistakes
- Forgetting to include a 'default' key causes KeyError for unknown topics.
- Assuming the message always has a 'topic' key without using .get().
- Passing the wrong type of handler (e.g., storing strings instead of callables).
Variations
- Use a class-based approach where handlers are methods and routing_table maps topics to method names.
- Use a dictionary of lambdas for simple inline handling logic.
Real-world use cases
- In a microservices event bus, route incoming events to different processing services based on event type.
- In a message queue consumer, dispatch messages to different worker functions for order processing, payment, and inventory.
- In a plugin architecture, allow dynamic registration of new handlers by updating the routing table at runtime.
Sponsored
More from System design patterns
- Build a BFF (Backend for Frontend) Mock Aggregator in Python medium
- Builder pattern for mocking complex objects in Python easy
- Circuit Breaker Pattern in Python: Closed, Open, and Half-Open States medium
- Create a Data Helper Class in Python easy
- Domain Driven Design Aggregate Root Example in Python medium
- Facade Pattern in Python with Mock Simplification medium
Keep learning
Related tutorials and quizzes for this topic.