Skip to content

Commit 72725de

Browse files
committed
feat: Add hard timeout demo with comprehensive Container API integration
- Demonstrates hard timeout feature alongside soft timeout - Interactive web interface showing timeout countdown timers - Multiple demo scenarios: basic timeout, long tasks, timeout comparison - Container status monitoring and real-time updates - Complete configuration with Dockerfile, wrangler.jsonc, package.json
1 parent e68dd9c commit 72725de

File tree

6 files changed

+589
-0
lines changed

6 files changed

+589
-0
lines changed

hard-timeout/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# syntax=docker/dockerfile:1
2+
3+
FROM node:18-slim
4+
5+
WORKDIR /app
6+
7+
# Create a simple HTTP server for demonstration
8+
RUN echo 'const http = require("http"); \
9+
const server = http.createServer((req, res) => { \
10+
res.writeHead(200, {"Content-Type": "text/plain"}); \
11+
res.end("Hard Timeout Demo Container\\n"); \
12+
}); \
13+
server.listen(8080, () => { \
14+
console.log("Server running on port 8080"); \
15+
});' > server.js
16+
17+
EXPOSE 8080
18+
19+
CMD ["node", "server.js"]

hard-timeout/README.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Container Timeout Demo
2+
3+
This example demonstrates the timeout feature for Cloudflare Containers. The timeout automatically kills containers after a specified absolute time from container start, regardless of activity.
4+
5+
## Key Features
6+
7+
- **Timeout**: Absolute timeout from container start time (vs soft timeout based on inactivity)
8+
- **Automatic termination**: Container is forcefully killed with SIGKILL when timeout expires
9+
- **Lifecycle hook**: `onHardTimeoutExpired()` method called when timeout occurs
10+
- **Complementary to soft timeout**: Works alongside existing activity-based timeout
11+
12+
## Timeout vs Soft Timeout
13+
14+
| Feature | Soft Timeout (sleepAfter) | Timeout |
15+
|---------|---------------------------|---------|
16+
| **Trigger** | Time since last activity | Time since container start |
17+
| **Signal** | SIGTERM (graceful) | SIGKILL (forceful) |
18+
| **Reset** | Reset on activity | Never resets |
19+
| **Use Case** | Save resources during inactivity | Prevent runaway containers |
20+
21+
## Configuration
22+
23+
```typescript
24+
export class TimeoutContainer extends Container {
25+
constructor(ctx: DurableObject['ctx'], env: Env) {
26+
super(ctx, env, {
27+
defaultPort: 8080,
28+
timeout: '30s', // Kill container after 30 seconds regardless of activity
29+
sleepAfter: '10s' // Soft timeout for inactivity (still works)
30+
});
31+
}
32+
}
33+
```
34+
35+
## Demo Scenarios
36+
37+
### 1. Basic Timeout (`/basic`)
38+
- Container configured with 15-second timeout
39+
- Shows automatic container termination after timeout
40+
- Demonstrates `onHardTimeoutExpired()` lifecycle hook
41+
42+
### 2. Long-Running Task (`/long-task`)
43+
- Simulates a long-running computation that would exceed timeout
44+
- Shows how timeout takes precedence over activity
45+
46+
### 3. Timeout Comparison (`/compare`)
47+
- Side-by-side comparison of soft vs timeout behavior
48+
- Shows how activity resets soft timeout but not timeout
49+
50+
## Running the Demo
51+
52+
1. **Deploy the container:**
53+
```bash
54+
npm run deploy
55+
```
56+
57+
2. **Test different scenarios:**
58+
```bash
59+
# Basic timeout demo
60+
curl https://timeout-demo.your-subdomain.workers.dev/basic
61+
62+
# Long running task demo
63+
curl https://timeout-demo.your-subdomain.workers.dev/long-task
64+
65+
# Timeout comparison demo
66+
curl https://timeout-demo.your-subdomain.workers.dev/compare
67+
```
68+
69+
3. **Monitor container lifecycle:**
70+
- Check Worker logs to see timeout events
71+
- Watch for "Timeout expired" messages
72+
- Observe container restart behavior
73+
74+
## Time Expression Formats
75+
76+
The `timeout` option supports various time expressions:
77+
78+
```typescript
79+
timeout: '30s' // 30 seconds
80+
timeout: '5m' // 5 minutes
81+
timeout: '1h' // 1 hour
82+
timeout: 120 // 120 seconds (number)
83+
```
84+
85+
## Best Practices
86+
87+
1. **Set reasonable limits**: Choose timeouts based on your workload
88+
2. **Override lifecycle hooks**: Implement `onHardTimeoutExpired()` for cleanup
89+
3. **Monitor and alert**: Track timeout events for operational visibility
90+
4. **Balance with soft timeout**: Use both timeouts for comprehensive resource management
91+
92+
## Implementation Notes
93+
94+
- Timeout starts when container first starts, not on each request
95+
- Uses `destroy()` by default for immediate termination
96+
- Integrates with existing alarm system for efficient timeout checking
97+
- Takes priority over soft timeout when both would trigger simultaneously

hard-timeout/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "timeout-container",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "wrangler deploy",
7+
"dev": "wrangler dev",
8+
"start": "wrangler dev",
9+
"cf-typegen": "wrangler types"
10+
},
11+
"devDependencies": {
12+
"@cloudflare/workers-types": "^4.20250403.0",
13+
"typescript": "^5.5.2",
14+
"wrangler": "^4.25.0"
15+
}
16+
}

0 commit comments

Comments
 (0)