Skip to content

Commit 80cdb02

Browse files
author
Вадим Козыревский
committed
Update documentation
1 parent 6716a42 commit 80cdb02

7 files changed

Lines changed: 331 additions & 32 deletions

File tree

docs/index.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
<p class="hero-subtitle">Event-Driven Architecture Framework for Distributed Systems</p>
55

66
<div class="project-links">
7-
<a href="https://github.com/vadikko2/python-cqrs" class="project-link github-link" target="_blank" rel="noopener">
8-
<span class="icon">🐙</span>
9-
<span class="text">GitHub</span>
10-
</a>
11-
<a href="https://pypi.org/project/python-cqrs/" class="project-link pypi-link" target="_blank" rel="noopener">
12-
<span class="icon">📦</span>
13-
<span class="text">PyPI</span>
14-
</a>
15-
<a href="https://clickpy.clickhouse.com/dashboard/python-cqrs" class="project-link stats-link" target="_blank" rel="noopener">
16-
<span class="icon">📊</span>
17-
<span class="text">Downloads</span>
7+
<a href="https://github.com/vadikko2/python-cqrs" class="project-link star-link" target="_blank" rel="noopener">
8+
<span class="star-link-icon star-link-icon-github">🐙</span>
9+
<span class="star-link-text">Star if cool</span>
10+
<span class="star-link-icon star-link-icon-star">⭐</span>
11+
<span class="star-link-icon star-link-icon-sparkle">✨</span>
12+
<span class="star-link-icon star-link-icon-sparkle">✨</span>
1813
</a>
14+
<div class="project-links-row">
15+
<a href="https://pypi.org/project/python-cqrs/" class="project-link pypi-link" target="_blank" rel="noopener">
16+
<span class="icon">📦</span>
17+
<span class="text">PyPI</span>
18+
</a>
19+
<a href="https://clickpy.clickhouse.com/dashboard/python-cqrs" class="project-link stats-link" target="_blank" rel="noopener">
20+
<span class="icon">📊</span>
21+
<span class="text">Downloads</span>
22+
</a>
23+
</div>
1924
</div>
2025

2126
</div>

docs/javascripts/star-link.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
(function() {
2+
'use strict';
3+
4+
const STAR_EMOJIS = ['⭐', '✨'];
5+
6+
function shuffle(arr) {
7+
const a = arr.slice();
8+
for (let i = a.length - 1; i > 0; i--) {
9+
const j = Math.floor(Math.random() * (i + 1));
10+
[a[i], a[j]] = [a[j], a[i]];
11+
}
12+
return a;
13+
}
14+
15+
function randomChoice(arr) {
16+
return arr[Math.floor(Math.random() * arr.length)];
17+
}
18+
19+
function randomizeStars(starLink) {
20+
const delays = shuffle([0, 0.08, 0.16, 0.24, 0.32]);
21+
starLink.style.setProperty('--delay-star', delays[0] + 's');
22+
starLink.style.setProperty('--delay-sparkle-1', delays[1] + 's');
23+
starLink.style.setProperty('--delay-sparkle-2', delays[2] + 's');
24+
starLink.style.setProperty('--delay-before', delays[3] + 's');
25+
starLink.style.setProperty('--delay-after', delays[4] + 's');
26+
27+
starLink.style.setProperty('--star-before', '"' + randomChoice(STAR_EMOJIS) + '"');
28+
starLink.style.setProperty('--star-after', '"' + randomChoice(STAR_EMOJIS) + '"');
29+
30+
const flying = starLink.querySelectorAll('.star-link-icon-star, .star-link-icon-sparkle');
31+
flying.forEach(function(el) {
32+
el.textContent = randomChoice(STAR_EMOJIS);
33+
});
34+
}
35+
36+
function initStarLink() {
37+
const starLink = document.querySelector('.star-link');
38+
if (!starLink) return;
39+
40+
starLink.addEventListener('mouseenter', function() {
41+
randomizeStars(starLink);
42+
});
43+
44+
const cycleTrigger = starLink.querySelector('.star-link-icon-star');
45+
if (cycleTrigger) {
46+
cycleTrigger.addEventListener('animationiteration', function() {
47+
randomizeStars(starLink);
48+
});
49+
}
50+
}
51+
52+
if (document.readyState === 'loading') {
53+
document.addEventListener('DOMContentLoaded', initStarLink);
54+
} else {
55+
initStarLink();
56+
}
57+
})();

docs/saga/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ async for step_result in mediator.stream(context, saga_id=saga_id):
164164
print(f"Step completed: {step_result.step_type.__name__}")
165165
```
166166

167+
!!! tip "Stream API"
168+
`mediator.stream(context, saga_id=...)` is called **without** `await` and returns an `AsyncIterator[SagaStepResult]`. Consume it with `async for` as shown above.
169+
167170
## Key Features
168171

169172
- **Automatic Compensation** — Failed steps trigger compensation of completed steps in reverse order

docs/stream_handling/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,6 @@ class ProcessFilesCommandHandler(
9090
# Yield result - events will be processed after this yield
9191
yield result
9292
```
93+
94+
!!! tip "Typing"
95+
The base `StreamingRequestHandler` declares `def handle(...) -> AsyncIterator[ResT]`. Your subclass implements it as an async generator (`async def handle(...): yield ...`). This is type-safe; no `# type: ignore` is needed. Call `mediator.stream(request)` **without** `await` and consume the result with `async for`.

docs/stream_handling/reference.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,20 @@ Streaming handlers are ideal for:
5353
| Progress Updates | Not available | Real-time |
5454
| Event Processing | After completion | After each yield |
5555
| Use Case | Simple operations | Batch/long-running operations |
56+
57+
### API Contract and Typing
58+
59+
**StreamingRequestHandler**
60+
61+
The base class declares `handle` as a **sync** method returning an iterator: `def handle(self, request: ReqT) -> AsyncIterator[ResT]`. Subclasses implement it as an **async generator** (`async def handle(...): ... yield ...`). This keeps types compatible with Pyright and mypy — **no type ignores** are needed on your handler's `handle` method.
62+
63+
**Stream and consumption**
64+
65+
- `mediator.stream(request)` is called **without** `await`.
66+
- It returns an `AsyncIterator`; consume it with `async for`:
67+
68+
```python
69+
# Correct: no await, iterate with async for
70+
async for result in mediator.stream(command):
71+
print(result)
72+
```

0 commit comments

Comments
 (0)