Skip to content

Commit dd0ea35

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 - Serverless deployment guide (GCP Functions) - 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 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent 5938cfe commit dd0ea35

File tree

1 file changed

+246
-1
lines changed

1 file changed

+246
-1
lines changed

README.md

Lines changed: 246 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,246 @@
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+
main.py # Entry point (if using GCP Functions)
173+
pyproject.toml # Dependencies
174+
```
175+
176+
## Serverless Deployment
177+
178+
This example works on serverless platforms with execution time limits:
179+
180+
### Google Cloud Functions
181+
182+
The `main.py` file shows GCP Functions integration:
183+
```python
184+
from resonategcp import Resonate
185+
186+
resonate = Resonate.remote()
187+
resonate.register(countdown)
188+
handler = resonate.handler_http()
189+
```
190+
191+
Deploy with:
192+
```bash
193+
gcloud functions deploy countdown \
194+
--runtime python313 \
195+
--trigger-http \
196+
--entry-point handler \
197+
--set-env-vars RESONATE_URL=your-server
198+
```
199+
200+
The function can timeout after each sleep - Resonate handles resumption.
201+
202+
### Other Platforms
203+
204+
Similar patterns work on:
205+
- AWS Lambda (with custom runtime or layers)
206+
- Azure Functions
207+
- Cloudflare Workers (via WebAssembly)
208+
209+
## Key Concepts
210+
211+
### Durable Sleep
212+
- `ctx.sleep(milliseconds)` suspends workflow
213+
- Process can exit, workflow state persists
214+
- Resonate resumes at the right time
215+
- No polling, no cron jobs needed
216+
217+
### Idempotency
218+
- Each notification uses a deterministic ID
219+
- Replays don't duplicate notifications
220+
- `ctx.run()` checkpoints prevent re-execution
221+
222+
### Resource Efficiency
223+
- Zero CPU/memory during sleep
224+
- Scale to zero between notifications
225+
- Pay only for active execution time
226+
227+
## Production Considerations
228+
229+
1. **Monitoring**: Track notification delivery success
230+
2. **Error handling**: Add retry logic for webhook failures
231+
3. **Timeouts**: Set workflow timeout longer than total countdown
232+
4. **Backpressure**: Limit concurrent countdown workflows
233+
5. **Observability**: Log each notification for audit trail
234+
235+
## Learn More
236+
237+
- [Python SDK Docs](https://docs.resonatehq.io/sdk/python)
238+
- [Durable Sleep Explained](https://docs.resonatehq.io/concepts/sleep)
239+
- [Serverless Patterns](https://docs.resonatehq.io/patterns/serverless)
240+
241+
## Related Examples
242+
243+
- [example-countdown-ts](../example-countdown-ts) - TypeScript version
244+
- [example-countdown-gcp-ts](../example-countdown-gcp-ts) - GCP Functions (TypeScript)
245+
- [example-countdown-supabase-ts](../example-countdown-supabase-ts) - Supabase Edge Functions
246+
- [example-durable-sleep-py](../example-durable-sleep-py) - Basic sleep patterns

0 commit comments

Comments
 (0)