Skip to content

Commit a7e48f5

Browse files
committed
docs
1 parent 9b93f7d commit a7e48f5

4 files changed

Lines changed: 777 additions & 714 deletions

File tree

README.md

Lines changed: 94 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -102,29 +102,70 @@ The SDK requires Python 3.9+. To install the SDK, use the following command:
102102
python3 -m pip install conductor-python
103103
```
104104

105-
## ⚡ Performance Features (v1.2.5+)
105+
## 🚀 Quick Start
106106

107-
The Python SDK includes ultra-low latency optimizations for high-performance production workloads:
107+
For a complete end-to-end example, see [examples/workers_e2e.py](examples/workers_e2e.py):
108108

109-
- **2-5ms average polling delay** (down from 15-90ms) - 10-18x improvement!
110-
- **HTTP/2 enabled by default** - 40-60% higher throughput, request multiplexing
111-
- **Batch polling** - 60-70% fewer API calls
112-
- **Adaptive backoff** - Prevents API hammering when queue is empty
113-
- **Concurrent execution** - ThreadPoolExecutor with configurable `thread_count`
114-
- **Connection pooling** - 100 connections with 50 keep-alive
115-
- **250+ tasks/sec throughput** with 80-85% efficiency (thread_count=10)
116-
117-
See [POLLING_LOOP_OPTIMIZATIONS.md](POLLING_LOOP_OPTIMIZATIONS.md) and [HTTP2_MIGRATION.md](HTTP2_MIGRATION.md) for details.
118-
119-
## 📚 Key Documentation
109+
```bash
110+
export CONDUCTOR_SERVER_URL="http://localhost:8080/api"
111+
python3 examples/workers_e2e.py
112+
```
120113

121-
- **[Worker Architecture](WORKER_ARCHITECTURE.md)** - Overview of worker architecture and design
122-
- **[Worker Concurrency Design](WORKER_CONCURRENCY_DESIGN.md)** - Multiprocessing vs AsyncIO comparison
123-
- **[Polling Loop Optimizations](POLLING_LOOP_OPTIMIZATIONS.md)** - Ultra-low latency polling details
124-
- **[HTTP/2 Migration](HTTP2_MIGRATION.md)** - HTTP/2 benefits and connection pooling
125-
- **[Lease Extension](LEASE_EXTENSION.md)** - How to handle long-running tasks
126-
- **[Worker Configuration](WORKER_CONFIGURATION.md)** - Environment-based configuration
127-
- **[Worker Documentation](docs/worker/README.md)** - Complete worker usage guide
114+
This example demonstrates:
115+
- Registering a workflow definition
116+
- Starting workflow execution
117+
- Running workers (sync + async)
118+
- Monitoring with Prometheus metrics
119+
- Long-running tasks with lease extension
120+
121+
**What you'll see:**
122+
- Workflow URL to monitor execution in UI
123+
- Workers processing tasks (AsyncTaskRunner vs TaskRunner)
124+
- Metrics endpoint at http://localhost:8000/metrics
125+
- Long-running task with TaskInProgress (5 polls)
126+
127+
## ⚡ Performance Features (SDK 1.3.0+)
128+
129+
The Python SDK provides high-performance worker execution with automatic optimization:
130+
131+
**Worker Architecture:**
132+
- **AsyncTaskRunner** for async workers (`async def`) - Pure async/await, zero thread overhead
133+
- **TaskRunner** for sync workers (`def`) - ThreadPoolExecutor for concurrent execution
134+
- **Automatic selection** - Based on function signature, no configuration needed
135+
- **One process per worker** - Process isolation and fault tolerance
136+
137+
**Performance Optimizations:**
138+
- **Dynamic batch polling** - Batch size adapts to available capacity (thread_count - running tasks)
139+
- **Adaptive backoff** - Exponential backoff when queue empty (1ms → 2ms → 4ms → poll_interval)
140+
- **High concurrency** - Async workers: 100-1000+ tasks/sec, Sync workers: 10-50 tasks/sec
141+
142+
**AsyncTaskRunner Benefits (async def workers):**
143+
- 67% fewer threads per worker
144+
- 40-50% less memory per worker
145+
- 10-100x better I/O throughput
146+
- Direct `await worker_fn()` execution
147+
148+
See [docs/design/WORKER_DESIGN.md](docs/design/WORKER_DESIGN.md) for complete architecture details.
149+
150+
## 📚 Documentation
151+
152+
**Getting Started:**
153+
- **[End-to-End Example](examples/workers_e2e.py)** - Complete workflow execution with workers
154+
- **[Examples Guide](examples/EXAMPLES_README.md)** - All examples with quick reference
155+
156+
**Worker Documentation:**
157+
- **[Worker Design & Architecture](docs/design/WORKER_DESIGN.md)** - Complete worker architecture guide
158+
- AsyncTaskRunner vs TaskRunner
159+
- Automatic runner selection
160+
- Worker discovery, configuration, best practices
161+
- Long-running tasks and lease extension
162+
- Performance metrics and monitoring
163+
- **[Worker Configuration](WORKER_CONFIGURATION.md)** - Hierarchical environment-based configuration
164+
- **[Complete Worker Guide](docs/worker/README.md)** - Comprehensive worker documentation
165+
166+
**Monitoring & Advanced:**
167+
- **[Metrics](METRICS.md)** - Prometheus metrics collection
168+
- **[Event-Driven Architecture](docs/design/event_driven_interceptor_system.md)** - Observability design
128169

129170
## Hello World Application Using Conductor
130171

@@ -334,16 +375,34 @@ def greetings(name: str) -> str:
334375
return f'Hello, {name}'
335376
```
336377

337-
**Async Workers:** Workers can be defined as `async def` functions for I/O-bound tasks, which are automatically executed using a background event loop for high concurrency:
378+
**Async Workers:** Workers can be defined as `async def` functions for I/O-bound tasks. The SDK automatically uses **AsyncTaskRunner** for pure async/await execution with high concurrency:
338379

339380
```python
340-
@worker_task(task_definition_name='fetch_data')
381+
@worker_task(task_definition_name='fetch_data', thread_count=50)
341382
async def fetch_data(url: str) -> dict:
383+
# Automatically uses AsyncTaskRunner (not TaskRunner)
384+
# - Pure async/await execution (no thread overhead)
385+
# - Single event loop per process
386+
# - Up to 50 concurrent tasks
342387
async with httpx.AsyncClient() as client:
343388
response = await client.get(url)
344389
return response.json()
345390
```
346391

392+
**Sync Workers:** Use regular `def` functions for CPU-bound or blocking I/O tasks:
393+
394+
```python
395+
@worker_task(task_definition_name='process_data', thread_count=5)
396+
def process_data(data: dict) -> dict:
397+
# Automatically uses TaskRunner (ThreadPoolExecutor)
398+
# - 5 concurrent threads
399+
# - Best for CPU-bound tasks or blocking I/O
400+
result = expensive_computation(data)
401+
return {'result': result}
402+
```
403+
404+
**The SDK automatically selects the right execution model** based on your function signature (`def` vs `async def`).
405+
347406
A worker can take inputs which are primitives - `str`, `int`, `float`, `bool` etc. or can be complex data classes.
348407

349408
Here is an example worker that uses `dataclass` as part of the worker input.
@@ -402,28 +461,34 @@ if __name__ == '__main__':
402461
```bash
403462
# Global configuration (applies to all workers)
404463
export conductor.worker.all.domain=production
405-
export conductor.worker.all.poll_interval=250
464+
export conductor.worker.all.poll_interval_millis=250
465+
export conductor.worker.all.thread_count=20
406466

407467
# Worker-specific configuration (overrides global)
408-
export conductor.worker.greetings.thread_count=20
468+
export conductor.worker.greetings.thread_count=50
409469

410-
# Runtime control (pause/resume workers)
470+
# Runtime control (pause/resume workers without code changes)
411471
export conductor.worker.all.paused=true # Maintenance mode
412472
```
413473

414-
Workers log their configuration on startup:
474+
Workers log their resolved configuration on startup:
415475
```
416-
INFO - Conductor Worker[name=greetings, status=active, poll_interval=250ms, domain=production, thread_count=20]
476+
INFO - Conductor Worker[name=greetings, pid=12345, status=active, poll_interval=250ms, domain=production, thread_count=50]
417477
```
418478

479+
**Configuration Priority:** Worker-specific > Global > Code defaults
480+
419481
For detailed configuration options, see [WORKER_CONFIGURATION.md](WORKER_CONFIGURATION.md).
420482

421483
**Monitoring:** Enable Prometheus metrics with built-in HTTP server:
422484

423485
```python
424486
from conductor.client.configuration.settings.metrics_settings import MetricsSettings
425487

426-
metrics_settings = MetricsSettings(http_port=8000)
488+
metrics_settings = MetricsSettings(
489+
directory='/tmp/conductor-metrics', # Multiprocess coordination
490+
http_port=8000 # HTTP metrics endpoint
491+
)
427492

428493
task_handler = TaskHandler(
429494
configuration=api_config,
@@ -433,7 +498,7 @@ task_handler = TaskHandler(
433498
# Metrics available at: http://localhost:8000/metrics
434499
```
435500

436-
For more details, see [METRICS.md](METRICS.md) and [WORKER_DESIGN.md](WORKER_DESIGN.md).
501+
For more details, see [METRICS.md](METRICS.md) and [docs/design/WORKER_DESIGN.md](docs/design/WORKER_DESIGN.md).
437502

438503
### Design Principles for Workers
439504

0 commit comments

Comments
 (0)