Skip to content

Commit 9d2090e

Browse files
author
Вадим Козыревский
committed
Add Saga and Cor Mermaid generating
1 parent a449a2c commit 9d2090e

6 files changed

Lines changed: 785 additions & 0 deletions

File tree

docs/chain_of_responsibility/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [Basic Example](#basic-example)
88
- [Examples](examples.md)
99
- [Advanced Topics](advanced.md)
10+
- [Mermaid Diagrams](../mermaid/chain_of_responsibility.md)
1011

1112
The Chain of Responsibility pattern allows multiple handlers to process a request in sequence until one successfully handles it. This pattern is particularly useful when you have multiple processing strategies or need to implement fallback mechanisms.
1213

@@ -31,6 +32,7 @@ The Chain of Responsibility pattern allows multiple handlers to process a reques
3132

3233
- **[Examples](examples.md)** — Registering handlers and complete examples
3334
- **[Advanced Topics](advanced.md)** — Manual chain building, handler methods, and integration
35+
- **[Mermaid Diagrams](../mermaid/chain_of_responsibility.md)** — Generate Sequence and Class diagrams for documentation
3436

3537
## Pattern Description
3638

docs/index.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ applications. It helps separate read and write operations, improving scalability
4040
| 🔗 **Flexibility** | Chain of Responsibility pattern support |
4141
| 📦 **Protobuf** | Protocol Buffers events serialization support |
4242
| 🔄 **Saga Pattern** | Choreographic Saga for distributed transactions with automatic compensation |
43+
| 📊 **Mermaid Diagrams** | Built-in generation of Sequence and Class diagrams for Chain of Responsibility and Saga patterns |
4344

4445
---
4546

@@ -207,6 +208,17 @@ The `python-cqrs` framework follows a clear architectural pattern:
207208
| **Parallel Processing** | Parallel processing of domain events |
208209
| **Performance** | Improved performance for independent event handlers |
209210

211+
### 📊 Mermaid Diagram Generation
212+
213+
| Feature | Description |
214+
|---------|-------------|
215+
| **Chain of Responsibility** | Generate Sequence and Class diagrams for handler chains |
216+
| **Saga Pattern** | Generate Sequence and Class diagrams for saga execution flows |
217+
| **Documentation** | Perfect for documentation, visualization, and understanding component structure |
218+
| **Multiple Formats** | Sequence diagrams for execution flow, Class diagrams for type structure |
219+
220+
See [Mermaid Diagrams](mermaid/index.md) for detailed documentation.
221+
210222
## Documentation
211223

212224
### Core Concepts
Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
# Mermaid Diagram Generation for Chain of Responsibility
2+
3+
The package includes built-in support for generating Mermaid diagrams from Chain of Responsibility handler chains. This feature is perfect for documentation, visualization, and understanding handler chain structure and execution flow.
4+
5+
## Overview
6+
7+
The `CoRMermaid` class can generate two types of diagrams:
8+
9+
1. **Sequence Diagram** - Shows the execution flow through the chain, successful handling, and pass-through scenarios
10+
2. **Class Diagram** - Shows the type structure, relationships between handlers, request types, response types, and chain links
11+
12+
## Example
13+
14+
You can find a complete working example in the repository:
15+
16+
[**View Example: `cor_mermaid.py`**](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_mermaid.py)
17+
18+
### Basic Usage
19+
20+
```python
21+
from cqrs.requests.mermaid import CoRMermaid
22+
from cqrs.requests.cor_request_handler import CORRequestHandler
23+
24+
# Create your handler chain (see Chain of Responsibility documentation for details)
25+
handlers = [
26+
CreditCardHandler,
27+
PayPalHandler,
28+
BankTransferHandler,
29+
DefaultPaymentHandler,
30+
]
31+
32+
# Create Mermaid generator
33+
generator = CoRMermaid(handlers)
34+
35+
# Generate Sequence diagram showing execution flow
36+
sequence_diagram = generator.sequence()
37+
print(sequence_diagram)
38+
39+
# Generate Class diagram showing type structure
40+
class_diagram = generator.class_diagram()
41+
print(class_diagram)
42+
```
43+
44+
## Sequence Diagram
45+
46+
The Sequence diagram visualizes the complete execution flow of a handler chain using nested `alt/else` blocks:
47+
48+
- Each handler can either **process the request** (return result and stop the chain) or **pass to the next handler**
49+
- The diagram shows all possible paths through the chain using nested conditional blocks
50+
- **Any handler can process the request and stop the chain**, not just the last one
51+
- Handler names (not aliases) are used in `alt` conditions for better readability
52+
53+
### Example Handler Chain Code
54+
55+
```python
56+
from cqrs.requests.cor_request_handler import CORRequestHandler
57+
from cqrs.response import Response
58+
59+
class ProcessPaymentCommand(cqrs.Request):
60+
amount: float
61+
payment_method: str
62+
user_id: str
63+
64+
class PaymentResult(Response):
65+
success: bool
66+
transaction_id: str | None = None
67+
message: str = ""
68+
69+
class CreditCardHandler(CORRequestHandler[ProcessPaymentCommand, PaymentResult]):
70+
async def handle(self, request: ProcessPaymentCommand) -> PaymentResult | None:
71+
if request.payment_method == "credit_card":
72+
return PaymentResult(success=True, transaction_id="cc_123")
73+
return await self.next(request)
74+
75+
class PayPalHandler(CORRequestHandler[ProcessPaymentCommand, PaymentResult]):
76+
async def handle(self, request: ProcessPaymentCommand) -> PaymentResult | None:
77+
if request.payment_method == "paypal":
78+
return PaymentResult(success=True, transaction_id="pp_123")
79+
return await self.next(request)
80+
81+
class DefaultPaymentHandler(CORRequestHandler[ProcessPaymentCommand, PaymentResult]):
82+
async def handle(self, request: ProcessPaymentCommand) -> PaymentResult | None:
83+
return PaymentResult(success=False, message="Unsupported method")
84+
85+
handlers = [CreditCardHandler, PayPalHandler, DefaultPaymentHandler]
86+
```
87+
88+
### Generated Sequence Diagram
89+
90+
#### Text Format
91+
92+
```text
93+
sequenceDiagram
94+
participant C as Chain
95+
participant H1 as CreditCardHandler
96+
participant H2 as PayPalHandler
97+
participant H3 as DefaultPaymentHandler
98+
99+
Note over C: Chain Execution Flow
100+
C->>H1: handle(request)
101+
102+
alt CreditCardHandler can handle
103+
H1-->>C: result
104+
Note over H1: Handler processed, chain stops
105+
else
106+
H1->>H2: next(request)
107+
Note over H1: Cannot handle, passing to next
108+
alt PayPalHandler can handle
109+
H2-->>C: result
110+
Note over H2: Handler processed, chain stops
111+
else
112+
H2->>H3: next(request)
113+
Note over H2: Cannot handle, passing to next
114+
alt DefaultPaymentHandler can handle
115+
H3-->>C: result
116+
Note over H3: Handler processed (default)
117+
end
118+
end
119+
end
120+
```
121+
122+
#### Rendered Diagram
123+
124+
```mermaid
125+
sequenceDiagram
126+
participant C as Chain
127+
participant H1 as CreditCardHandler
128+
participant H2 as PayPalHandler
129+
participant H3 as DefaultPaymentHandler
130+
131+
Note over C: Chain Execution Flow
132+
C->>H1: handle(request)
133+
134+
alt CreditCardHandler can handle
135+
H1-->>C: result
136+
Note over H1: Handler processed, chain stops
137+
else
138+
H1->>H2: next(request)
139+
Note over H1: Cannot handle, passing to next
140+
alt PayPalHandler can handle
141+
H2-->>C: result
142+
Note over H2: Handler processed, chain stops
143+
else
144+
H2->>H3: next(request)
145+
Note over H2: Cannot handle, passing to next
146+
alt DefaultPaymentHandler can handle
147+
H3-->>C: result
148+
Note over H3: Handler processed (default)
149+
end
150+
end
151+
end
152+
```
153+
154+
## Class Diagram
155+
156+
The Class diagram shows the complete type structure and relationships:
157+
158+
- CORRequestHandler base class with its methods
159+
- Handler classes with their methods (`handle`, `next`, `events`)
160+
- Request classes with their fields
161+
- Response classes with their fields
162+
- Relationships between classes (inheritance, chain links, usage, return types)
163+
164+
### Generated Class Diagram
165+
166+
#### Text Format
167+
168+
```text
169+
classDiagram
170+
class CORRequestHandler {
171+
<<abstract>>
172+
+handle(request) Response | None
173+
+next(request) Response | None
174+
+set_next(handler) CORRequestHandler
175+
+events: List[Event]
176+
}
177+
178+
class CreditCardHandler {
179+
+handle(request) Response | None
180+
+next(request) Response | None
181+
+events: List[Event]
182+
}
183+
184+
class PayPalHandler {
185+
+handle(request) Response | None
186+
+next(request) Response | None
187+
+events: List[Event]
188+
}
189+
190+
class DefaultPaymentHandler {
191+
+handle(request) Response | None
192+
+next(request) Response | None
193+
+events: List[Event]
194+
}
195+
196+
class ProcessPaymentCommand {
197+
+amount: float
198+
+payment_method: str
199+
+user_id: str
200+
}
201+
202+
class PaymentResult {
203+
+success: bool
204+
+transaction_id: str | None
205+
+message: str
206+
}
207+
208+
%% Inheritance relationships
209+
CORRequestHandler <|-- CreditCardHandler
210+
CORRequestHandler <|-- PayPalHandler
211+
CORRequestHandler <|-- DefaultPaymentHandler
212+
213+
%% Chain relationships (set_next)
214+
CreditCardHandler --> PayPalHandler : set_next
215+
PayPalHandler --> DefaultPaymentHandler : set_next
216+
217+
%% Handler to Request relationships
218+
CreditCardHandler ..> ProcessPaymentCommand : uses
219+
PayPalHandler ..> ProcessPaymentCommand : uses
220+
DefaultPaymentHandler ..> ProcessPaymentCommand : uses
221+
222+
%% Handler to Response relationships
223+
CreditCardHandler ..> PaymentResult : returns
224+
PayPalHandler ..> PaymentResult : returns
225+
DefaultPaymentHandler ..> PaymentResult : returns
226+
```
227+
228+
#### Rendered Diagram
229+
230+
```mermaid
231+
classDiagram
232+
class CORRequestHandler {
233+
<<abstract>>
234+
+handle(request) Response | None
235+
+next(request) Response | None
236+
+set_next(handler) CORRequestHandler
237+
+events: List[Event]
238+
}
239+
240+
class CreditCardHandler {
241+
+handle(request) Response | None
242+
+next(request) Response | None
243+
+events: List[Event]
244+
}
245+
246+
class PayPalHandler {
247+
+handle(request) Response | None
248+
+next(request) Response | None
249+
+events: List[Event]
250+
}
251+
252+
class DefaultPaymentHandler {
253+
+handle(request) Response | None
254+
+next(request) Response | None
255+
+events: List[Event]
256+
}
257+
258+
class ProcessPaymentCommand {
259+
+amount: float
260+
+payment_method: str
261+
+user_id: str
262+
}
263+
264+
class PaymentResult {
265+
+success: bool
266+
+transaction_id: str | None
267+
+message: str
268+
}
269+
270+
%% Inheritance relationships
271+
CORRequestHandler <|-- CreditCardHandler
272+
CORRequestHandler <|-- PayPalHandler
273+
CORRequestHandler <|-- DefaultPaymentHandler
274+
275+
%% Chain relationships (set_next)
276+
CreditCardHandler --> PayPalHandler : set_next
277+
PayPalHandler --> DefaultPaymentHandler : set_next
278+
279+
%% Handler to Request relationships
280+
CreditCardHandler ..> ProcessPaymentCommand : uses
281+
PayPalHandler ..> ProcessPaymentCommand : uses
282+
DefaultPaymentHandler ..> ProcessPaymentCommand : uses
283+
284+
%% Handler to Response relationships
285+
CreditCardHandler ..> PaymentResult : returns
286+
PayPalHandler ..> PaymentResult : returns
287+
DefaultPaymentHandler ..> PaymentResult : returns
288+
```
289+
290+
## Usage in Documentation
291+
292+
Generated diagrams can be:
293+
294+
- **Copied and pasted** into [Mermaid Live Editor](https://mermaid.live/) for visualization
295+
- **Embedded directly** in Markdown files (GitHub/GitLab support Mermaid)
296+
- **Used in documentation tools** (Confluence, Notion, etc.)
297+
- **Included in README files** for better understanding
298+
299+
### Running the Example
300+
301+
To see the diagrams generated from a real handler chain, run:
302+
303+
```bash
304+
python examples/cor_mermaid.py
305+
```
306+
307+
This will output both Sequence and Class diagrams in a format ready to copy and paste into any Mermaid-compatible viewer.
308+
309+
## API Reference
310+
311+
### CoRMermaid Class
312+
313+
#### `__init__(handlers: List[type[CORRequestHandler[Any, Any]]])`
314+
315+
Initialize Mermaid diagram generator.
316+
317+
**Parameters:**
318+
- `handlers`: List of handler classes in chain order
319+
320+
#### `sequence() -> str`
321+
322+
Generate a Mermaid Sequence diagram showing chain execution flow.
323+
324+
**Returns:**
325+
- A string containing the Mermaid Sequence diagram code
326+
327+
#### `class_diagram() -> str`
328+
329+
Generate a Mermaid Class diagram showing handler chain structure, types, and relationships.
330+
331+
**Returns:**
332+
- A string containing the Mermaid Class diagram code
333+
334+
## See Also
335+
336+
- [Mermaid Overview](../mermaid/index.md) - Overview of Mermaid diagram generation
337+
- [Chain of Responsibility Overview](../chain_of_responsibility/index.md) - Learn about the Chain of Responsibility pattern implementation
338+
- [Chain of Responsibility Examples](../chain_of_responsibility/examples.md) - Complete examples
339+
- [Chain of Responsibility Advanced Topics](../chain_of_responsibility/advanced.md) - Advanced usage patterns
340+
- [Example: Basic CoR](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_request_handler.py)
341+
- [Example: CoR Mermaid Diagrams](https://github.com/vadikko2/python-cqrs/blob/master/examples/cor_mermaid.py)

0 commit comments

Comments
 (0)