Skip to content

Commit 305a0cd

Browse files
flossypurseclaude
andcommitted
Enhance countdown-py README with comprehensive documentation
Added comprehensive documentation for the Python countdown example: **Content Added:** - Problem statement (resource waste, crash recovery) - Solution explanation (durable sleep benefits) - Real-world use cases (reminders, SLA monitors, rate limiting) - Step-by-step code walkthrough - Crash recovery explanation - Running instructions with example commands - Configuration options (ntfy.sh, Slack, Discord) - Failure scenario testing procedures - Key concepts (durable sleep, idempotency, resource efficiency) - Production considerations - Related examples **Structure:** - Clear sections with progressive detail - Code examples with explanations - Testing procedures for crash recovery - Multiple notification backend examples Updated repo description and topics: resonate, python, durable-execution, countdown, notifications Note: Removed serverless/cloud function sections as Python SDK does not yet have shims for those platforms. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent 5938cfe commit 305a0cd

File tree

1 file changed

+211
-1
lines changed

1 file changed

+211
-1
lines changed

README.md

Lines changed: 211 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,211 @@
1-
# example-countdown-py
1+
# Example: Countdown with Durable Sleep (Python)
2+
3+
A countdown timer that demonstrates **durable sleep** - long pauses without consuming resources, surviving crashes and resuming exactly where it left off.
4+
5+
## What This Demonstrates
6+
7+
### Problem: Long-Running Timers
8+
Traditional countdown timers keep a process running continuously, wasting resources during sleep periods. If the process crashes, you lose the countdown state.
9+
10+
### Solution: Durable Sleep
11+
Resonate's durable sleep allows workflows to:
12+
- Pause for extended periods (hours, days, weeks)
13+
- Consume zero resources while sleeping
14+
- Survive crashes and resume at the right time
15+
- Send periodic notifications reliably
16+
17+
## Use Cases
18+
19+
This pattern applies to:
20+
- **Scheduled reminders** - Meeting notifications, task deadlines
21+
- **SLA monitors** - Alert if response not received in time
22+
- **Rate limiting** - Enforce delays between operations
23+
- **Periodic reports** - Daily/weekly/monthly automation
24+
- **Countdown timers** - Track time until events
25+
26+
## How It Works
27+
28+
```python
29+
def countdown(ctx: Context, count: int, interval, url: str):
30+
for i in range(count, 0, -1):
31+
# Send notification (durable)
32+
yield ctx.run(notify, message=f"Countdown: {i}", url=url)
33+
34+
# Sleep for interval (process can exit here)
35+
yield ctx.sleep(interval)
36+
37+
# Final notification
38+
yield ctx.run(notify, message="Countdown complete", url=url)
39+
```
40+
41+
### What Happens on Each Iteration
42+
43+
1. **Send notification** - `ctx.run()` executes and checkpoints the result
44+
2. **Sleep** - `ctx.sleep()` suspends the workflow, process can exit
45+
3. **Resume** - Resonate wakes the workflow after the interval
46+
4. **Repeat** - Continue from checkpoint without re-sending notifications
47+
48+
### Crash Recovery
49+
50+
If the process crashes during sleep:
51+
- Workflow state is preserved in Resonate
52+
- Resonate automatically resumes at the scheduled wake time
53+
- No notifications are duplicated
54+
- Countdown continues as if nothing happened
55+
56+
## Running the Example
57+
58+
### Prerequisites
59+
60+
- Python 3.13+
61+
- uv (Python package manager)
62+
- ntfy.sh account or webhook URL
63+
64+
### Installation
65+
66+
```bash
67+
# Install dependencies
68+
uv sync
69+
```
70+
71+
### Usage
72+
73+
```bash
74+
# Start the countdown worker
75+
uv run python countdown.py
76+
```
77+
78+
Then trigger a countdown via the Resonate API or another process:
79+
80+
```bash
81+
# Start 10-minute countdown with 1-minute intervals
82+
curl -X POST http://localhost:8001/promises \
83+
-H "Content-Type: application/json" \
84+
-d '{
85+
"id": "countdown/demo",
86+
"timeout": 36000000,
87+
"data": {
88+
"func": "countdown",
89+
"args": [10, 60000, "https://ntfy.sh/your-topic"]
90+
}
91+
}'
92+
```
93+
94+
**Parameters:**
95+
- `count`: Number of countdown steps (10 = 10 notifications)
96+
- `interval`: Milliseconds between steps (60000 = 1 minute)
97+
- `url`: Webhook URL for notifications (ntfy.sh, Slack, etc.)
98+
99+
### Notification Format
100+
101+
Each notification sends JSON:
102+
```json
103+
{
104+
"message": "Countdown: 7"
105+
}
106+
```
107+
108+
## Configuration
109+
110+
### Environment Variables
111+
112+
Create a `.env` file:
113+
```bash
114+
RESONATE_URL=http://localhost:8001
115+
RESONATE_TOKEN=your-token-here
116+
NTFY_URL=https://ntfy.sh/your-topic
117+
```
118+
119+
### Notification Backends
120+
121+
The example uses ntfy.sh by default, but works with any webhook:
122+
123+
**Slack:**
124+
```python
125+
url = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
126+
```
127+
128+
**Discord:**
129+
```python
130+
url = "https://discord.com/api/webhooks/YOUR/WEBHOOK"
131+
```
132+
133+
**Custom API:**
134+
```python
135+
url = "https://api.example.com/notifications"
136+
```
137+
138+
## Testing Failure Scenarios
139+
140+
### Test 1: Crash During Sleep
141+
142+
1. Start countdown with long interval:
143+
```bash
144+
# 5 steps, 30 seconds each
145+
resonate.run("test/crash", countdown, 5, 30000, url)
146+
```
147+
148+
2. Wait for first notification
149+
150+
3. Kill the process (Ctrl+C)
151+
152+
4. Restart the process:
153+
```bash
154+
uv run python countdown.py
155+
```
156+
157+
5. Observe: Countdown resumes at the correct step, no duplicates
158+
159+
### Test 2: Long-Running Countdown
160+
161+
```bash
162+
# 24-hour countdown with hourly notifications
163+
resonate.run("test/longrun", countdown, 24, 3600000, url)
164+
```
165+
166+
Process can stop/start freely. Notifications arrive on schedule.
167+
168+
## Code Structure
169+
170+
```
171+
countdown.py # Countdown workflow definition
172+
pyproject.toml # Dependencies
173+
```
174+
175+
## Key Concepts
176+
177+
### Durable Sleep
178+
- `ctx.sleep(milliseconds)` suspends workflow
179+
- Process can exit, workflow state persists
180+
- Resonate resumes at the right time
181+
- No polling, no cron jobs needed
182+
183+
### Idempotency
184+
- Each notification uses a deterministic ID
185+
- Replays don't duplicate notifications
186+
- `ctx.run()` checkpoints prevent re-execution
187+
188+
### Resource Efficiency
189+
- Zero CPU/memory during sleep
190+
- Scale to zero between notifications
191+
- Pay only for active execution time
192+
193+
## Production Considerations
194+
195+
1. **Monitoring**: Track notification delivery success
196+
2. **Error handling**: Add retry logic for webhook failures
197+
3. **Timeouts**: Set workflow timeout longer than total countdown
198+
4. **Backpressure**: Limit concurrent countdown workflows
199+
5. **Observability**: Log each notification for audit trail
200+
201+
## Learn More
202+
203+
- [Python SDK Docs](https://docs.resonatehq.io/sdk/python)
204+
- [Durable Sleep Explained](https://docs.resonatehq.io/concepts/sleep)
205+
- [Serverless Patterns](https://docs.resonatehq.io/patterns/serverless)
206+
207+
## Related Examples
208+
209+
- [example-countdown-ts](../example-countdown-ts) - TypeScript version
210+
- [example-durable-sleep-py](../example-durable-sleep-py) - Basic sleep patterns
211+
- [example-durable-sleep-ts](../example-durable-sleep-ts) - Basic sleep patterns (TypeScript)

0 commit comments

Comments
 (0)