AntFlow 0.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- antflow-0.7.3/AntFlow.egg-info/PKG-INFO +544 -0
- antflow-0.7.3/AntFlow.egg-info/SOURCES.txt +44 -0
- antflow-0.7.3/AntFlow.egg-info/dependency_links.txt +1 -0
- antflow-0.7.3/AntFlow.egg-info/requires.txt +17 -0
- antflow-0.7.3/AntFlow.egg-info/top_level.txt +1 -0
- antflow-0.7.3/LICENSE +21 -0
- antflow-0.7.3/PKG-INFO +544 -0
- antflow-0.7.3/README.md +504 -0
- antflow-0.7.3/antflow/__init__.py +62 -0
- antflow-0.7.3/antflow/_version.py +1 -0
- antflow-0.7.3/antflow/context.py +67 -0
- antflow-0.7.3/antflow/display/__init__.py +19 -0
- antflow-0.7.3/antflow/display/base.py +80 -0
- antflow-0.7.3/antflow/display/compact.py +190 -0
- antflow-0.7.3/antflow/display/detailed.py +232 -0
- antflow-0.7.3/antflow/display/full.py +324 -0
- antflow-0.7.3/antflow/display/progress.py +116 -0
- antflow-0.7.3/antflow/exceptions.py +27 -0
- antflow-0.7.3/antflow/executor.py +495 -0
- antflow-0.7.3/antflow/pipeline.py +1510 -0
- antflow-0.7.3/antflow/tracker.py +205 -0
- antflow-0.7.3/antflow/types.py +325 -0
- antflow-0.7.3/antflow/utils.py +42 -0
- antflow-0.7.3/pyproject.toml +75 -0
- antflow-0.7.3/setup.cfg +4 -0
- antflow-0.7.3/tests/test_backpressure.py +85 -0
- antflow-0.7.3/tests/test_display.py +192 -0
- antflow-0.7.3/tests/test_error_summary.py +173 -0
- antflow-0.7.3/tests/test_executor.py +233 -0
- antflow-0.7.3/tests/test_executor_concurrency.py +56 -0
- antflow-0.7.3/tests/test_executor_retry.py +100 -0
- antflow-0.7.3/tests/test_injection.py +84 -0
- antflow-0.7.3/tests/test_integration.py +166 -0
- antflow-0.7.3/tests/test_pipeline.py +265 -0
- antflow-0.7.3/tests/test_pipeline_concurrency.py +73 -0
- antflow-0.7.3/tests/test_priority.py +76 -0
- antflow-0.7.3/tests/test_quick_api.py +132 -0
- antflow-0.7.3/tests/test_retry_status.py +45 -0
- antflow-0.7.3/tests/test_skip_if.py +65 -0
- antflow-0.7.3/tests/test_stage_callbacks.py +80 -0
- antflow-0.7.3/tests/test_stream.py +86 -0
- antflow-0.7.3/tests/test_stream_memory.py +86 -0
- antflow-0.7.3/tests/test_task_events.py +250 -0
- antflow-0.7.3/tests/test_tracker.py +427 -0
- antflow-0.7.3/tests/test_unpacking.py +114 -0
- antflow-0.7.3/tests/test_wait.py +249 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: AntFlow
|
|
3
|
+
Version: 0.7.3
|
|
4
|
+
Summary: AntFlow: Async execution library with concurrent.futures-style API and advanced pipelines
|
|
5
|
+
Author-email: Rodolfo Nobrega <rodolfo@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rodolfonobrega/AntFlow
|
|
8
|
+
Project-URL: Documentation, https://rodolfonobrega.github.io/AntFlow
|
|
9
|
+
Project-URL: Repository, https://github.com/rodolfonobrega/AntFlow
|
|
10
|
+
Project-URL: Issues, https://github.com/rodolfonobrega/AntFlow/issues
|
|
11
|
+
Keywords: AntFlow,async,asyncio,pipeline,concurrent,futures,executor,worker-pool
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Framework :: AsyncIO
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: tenacity>=8.0.0
|
|
27
|
+
Requires-Dist: rich>=13.0.0
|
|
28
|
+
Requires-Dist: taskgroup>=0.0.0a4; python_version < "3.11"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
34
|
+
Provides-Extra: docs
|
|
35
|
+
Requires-Dist: mkdocs>=1.5.0; extra == "docs"
|
|
36
|
+
Requires-Dist: mkdocs-material>=9.0.0; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "docs"
|
|
38
|
+
Requires-Dist: mkdocs-autorefs>=0.6.0; extra == "docs"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<img src="docs/images/antflow-logo.png" alt="AntFlow Logo" width="800">
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
# AntFlow
|
|
46
|
+
|
|
47
|
+
## Why AntFlow?
|
|
48
|
+
|
|
49
|
+
The name 'AntFlow' is inspired by the efficiency of an ant colony, where each ant (worker) performs its specialized function, and together they contribute to the colony's collective goal. Similarly, AntFlow orchestrates independent workers to achieve complex asynchronous tasks seamlessly.
|
|
50
|
+
|
|
51
|
+
### The Problem I Had to Solve
|
|
52
|
+
|
|
53
|
+
I was processing massive amounts of data using OpenAI's Batch API. The workflow was complex:
|
|
54
|
+
|
|
55
|
+
1. Upload batches of data to OpenAI
|
|
56
|
+
2. Wait for processing to complete
|
|
57
|
+
3. Download the results
|
|
58
|
+
4. Save to database
|
|
59
|
+
5. Repeat for the next batch
|
|
60
|
+
|
|
61
|
+
Initially, I processed 10 batches at a time using basic async. But here's the problem: **I had to wait for ALL 10 batches to complete before starting the next group.**
|
|
62
|
+
|
|
63
|
+
### The Bottleneck
|
|
64
|
+
|
|
65
|
+
Imagine this scenario:
|
|
66
|
+
|
|
67
|
+
- 9 batches complete in 5 minutes
|
|
68
|
+
- 1 batch gets stuck and takes 30 minutes
|
|
69
|
+
- **I waste 25 minutes waiting for that one slow batch while my system sits idle**
|
|
70
|
+
|
|
71
|
+
With hundreds of batches to process, these delays accumulated into **hours of wasted time**. Even worse, one failed batch would block the entire pipeline.
|
|
72
|
+
|
|
73
|
+
### The Solution: AntFlow
|
|
74
|
+
|
|
75
|
+
I built AntFlow to solve this exact problem. Instead of batch-by-batch processing, AntFlow uses worker pools where:
|
|
76
|
+
|
|
77
|
+
- ✅ Each worker handles tasks independently
|
|
78
|
+
- ✅ When a worker finishes, it immediately grabs the next task
|
|
79
|
+
- ✅ Slow tasks don't block fast ones
|
|
80
|
+
- ✅ Always maintain optimal concurrency (e.g., 10 tasks running simultaneously)
|
|
81
|
+
- ✅ Built-in retry logic for failed tasks
|
|
82
|
+
- ✅ Multi-stage pipelines for complex workflows
|
|
83
|
+
|
|
84
|
+
**Result:** My OpenAI batch processing went from taking hours to completing in a fraction of the time, with automatic retry handling and zero idle time.
|
|
85
|
+
|
|
86
|
+
<p align="center">
|
|
87
|
+
<img src="docs/images/antflow-workers.png" alt="AntFlow Workers" width="600">
|
|
88
|
+
</p>
|
|
89
|
+
|
|
90
|
+
<p align="center">
|
|
91
|
+
<em>AntFlow: Modern async execution library with concurrent.futures-style API and advanced pipelines</em>
|
|
92
|
+
</p>
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Key Features
|
|
97
|
+
|
|
98
|
+
### 🚀 **Worker Pool Architecture**
|
|
99
|
+
- Independent workers that never block each other
|
|
100
|
+
- Automatic task distribution
|
|
101
|
+
- Optimal resource utilization
|
|
102
|
+
|
|
103
|
+
### 🔄 **Multi-Stage Pipelines**
|
|
104
|
+
- Chain operations with configurable worker pools per stage
|
|
105
|
+
- Each stage runs independently
|
|
106
|
+
- Data flows automatically between stages
|
|
107
|
+
- **Priority Queues**: Assign priority to items to bypass sequential processing (NEW)
|
|
108
|
+
- **Interactive Control**: Resume pipelines and inject items into any stage (NEW)
|
|
109
|
+
|
|
110
|
+
### 💪 **Built-in Resilience**
|
|
111
|
+
- Per-task retry with exponential backoff
|
|
112
|
+
- Per-stage retry for transactional operations
|
|
113
|
+
- Failed tasks don't stop the pipeline
|
|
114
|
+
|
|
115
|
+
### 📊 **Real-time Monitoring & Dashboards**
|
|
116
|
+
- **Built-in Progress Bar** - Simple `progress=True` flag for terminal progress
|
|
117
|
+
- **Three Dashboard Levels** - Compact, Detailed, and Full dashboards
|
|
118
|
+
- **Custom Dashboards** - Implement `DashboardProtocol` for your own UI
|
|
119
|
+
- **Worker State Tracking** - Know what each worker is doing in real-time
|
|
120
|
+
- **Performance Metrics** - Track items processed, failures, avg time per worker
|
|
121
|
+
- **Error Summary** - Aggregated error statistics with `get_error_summary()`
|
|
122
|
+
- **StatusTracker** - Real-time item tracking with full history
|
|
123
|
+
|
|
124
|
+
### 🎯 **Familiar API**
|
|
125
|
+
- Drop-in async replacement for `concurrent.futures`
|
|
126
|
+
- `submit()`, `map()`, `as_completed()` methods
|
|
127
|
+
- Clean, intuitive interface
|
|
128
|
+
|
|
129
|
+
### ✨ **Fluent APIs** (NEW)
|
|
130
|
+
- **`Pipeline.quick()`** - One-liner for simple pipelines
|
|
131
|
+
- **`Pipeline.create()`** - Fluent builder pattern
|
|
132
|
+
- **Result Streaming** - `pipeline.stream()` for processing results as they complete
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Use Cases
|
|
137
|
+
|
|
138
|
+
### ✅ **Perfect for:**
|
|
139
|
+
- **Batch API Processing** - OpenAI, Anthropic, any batch API
|
|
140
|
+
- **ETL Pipelines** - Extract, transform, load at scale
|
|
141
|
+
- **Web Scraping** - Fetch, parse, store web data efficiently
|
|
142
|
+
- **Data Processing** - Process large datasets with retry logic
|
|
143
|
+
- **Microservices** - Chain async service calls with error handling
|
|
144
|
+
|
|
145
|
+
### ⚡ **Real-world Impact:**
|
|
146
|
+
- Process large batches without bottlenecks
|
|
147
|
+
- Automatic retry for transient failures
|
|
148
|
+
- Zero idle time = maximum throughput
|
|
149
|
+
- Clear observability with metrics and callbacks
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Quick Install
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install AntFlow
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Quick Start
|
|
162
|
+
|
|
163
|
+
AntFlow offers **three equivalent ways** to create pipelines. Choose based on your needs:
|
|
164
|
+
|
|
165
|
+
### Method 1: Fluent Builder API (Concise & Recommended)
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
import asyncio
|
|
169
|
+
from antflow import Pipeline
|
|
170
|
+
|
|
171
|
+
async def fetch(x):
|
|
172
|
+
await asyncio.sleep(0.1)
|
|
173
|
+
return f"data_{x}"
|
|
174
|
+
|
|
175
|
+
async def main():
|
|
176
|
+
items = range(10)
|
|
177
|
+
results = await (
|
|
178
|
+
Pipeline.create()
|
|
179
|
+
.add("Fetch", fetch, workers=5, retries=3)
|
|
180
|
+
.run(items, progress=True)
|
|
181
|
+
)
|
|
182
|
+
print(f"Processed {len(results)} items")
|
|
183
|
+
|
|
184
|
+
if __name__ == "__main__":
|
|
185
|
+
asyncio.run(main())
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Method 2: Stage Objects (Full Control)
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import asyncio
|
|
192
|
+
from antflow import Pipeline, Stage
|
|
193
|
+
|
|
194
|
+
async def process(x):
|
|
195
|
+
await asyncio.sleep(0.1)
|
|
196
|
+
return x * 2
|
|
197
|
+
|
|
198
|
+
async def main():
|
|
199
|
+
items = range(10)
|
|
200
|
+
stage = Stage(name="Process", workers=5, tasks=[process])
|
|
201
|
+
pipeline = Pipeline(stages=[stage])
|
|
202
|
+
results = await pipeline.run(items, progress=True)
|
|
203
|
+
print(f"Processed {len(results)} items")
|
|
204
|
+
|
|
205
|
+
if __name__ == "__main__":
|
|
206
|
+
asyncio.run(main())
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Method 3: Quick One-Liner
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
import asyncio
|
|
213
|
+
from antflow import Pipeline
|
|
214
|
+
|
|
215
|
+
async def simple_task(x):
|
|
216
|
+
return x + 1
|
|
217
|
+
|
|
218
|
+
async def main():
|
|
219
|
+
results = await Pipeline.quick(range(10), simple_task, workers=5, progress=True)
|
|
220
|
+
print(f"Processed {len(results)} items")
|
|
221
|
+
|
|
222
|
+
if __name__ == "__main__":
|
|
223
|
+
asyncio.run(main())
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Which Method to Choose?
|
|
227
|
+
|
|
228
|
+
| Method | When to Use |
|
|
229
|
+
|--------|-------------|
|
|
230
|
+
| **Stage objects** | Fine-grained control, custom callbacks, task concurrency limits |
|
|
231
|
+
| **Fluent API** | Clean multi-stage pipelines, quick prototyping |
|
|
232
|
+
| **Pipeline.quick()** | Simple scripts, single-task processing |
|
|
233
|
+
|
|
234
|
+
All three methods produce the same result - they're just different ways to express the same thing.
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
### Built-in Progress & Dashboards
|
|
238
|
+
|
|
239
|
+
All display options are **optional**. By default, pipelines run silently.
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
import asyncio
|
|
243
|
+
from antflow import Pipeline
|
|
244
|
+
|
|
245
|
+
async def task(x):
|
|
246
|
+
await asyncio.sleep(0.01)
|
|
247
|
+
return x * 2
|
|
248
|
+
|
|
249
|
+
async def main():
|
|
250
|
+
items = range(50)
|
|
251
|
+
# Dashboard options: "compact", "detailed", "full"
|
|
252
|
+
results = await Pipeline.quick(items, task, workers=5, dashboard="detailed")
|
|
253
|
+
|
|
254
|
+
if __name__ == "__main__":
|
|
255
|
+
asyncio.run(main())
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
> **Tip:** For multi-stage pipelines, use `dashboard="detailed"` to see progress per stage and identify bottlenecks.
|
|
259
|
+
|
|
260
|
+
### Stream Results
|
|
261
|
+
|
|
262
|
+
Process results as they complete:
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
import asyncio
|
|
266
|
+
from antflow import Pipeline
|
|
267
|
+
|
|
268
|
+
async def process(x):
|
|
269
|
+
await asyncio.sleep(0.1)
|
|
270
|
+
return f"result_{x}"
|
|
271
|
+
|
|
272
|
+
async def main():
|
|
273
|
+
pipeline = Pipeline.create().add("Process", process, workers=5).build()
|
|
274
|
+
|
|
275
|
+
async for result in pipeline.stream(range(10)):
|
|
276
|
+
print(f"Got: {result.value}")
|
|
277
|
+
|
|
278
|
+
if __name__ == "__main__":
|
|
279
|
+
asyncio.run(main())
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Traditional API
|
|
285
|
+
|
|
286
|
+
For full control, use the traditional Stage and Pipeline API:
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
import asyncio
|
|
290
|
+
from antflow import Pipeline, Stage
|
|
291
|
+
|
|
292
|
+
async def upload_batch(batch_data):
|
|
293
|
+
await asyncio.sleep(0.1)
|
|
294
|
+
return "batch_id"
|
|
295
|
+
|
|
296
|
+
async def check_status(batch_id):
|
|
297
|
+
await asyncio.sleep(0.1)
|
|
298
|
+
return "result_url"
|
|
299
|
+
|
|
300
|
+
async def download_results(result_url):
|
|
301
|
+
await asyncio.sleep(0.1)
|
|
302
|
+
return "processed_data"
|
|
303
|
+
|
|
304
|
+
async def save_to_db(processed_data):
|
|
305
|
+
await asyncio.sleep(0.1)
|
|
306
|
+
return "saved"
|
|
307
|
+
|
|
308
|
+
async def main():
|
|
309
|
+
# Build the pipeline with explicit stages
|
|
310
|
+
upload_stage = Stage(name="Upload", workers=10, tasks=[upload_batch])
|
|
311
|
+
check_stage = Stage(name="Check", workers=10, tasks=[check_status])
|
|
312
|
+
download_stage = Stage(name="Download", workers=10, tasks=[download_results])
|
|
313
|
+
save_stage = Stage(name="Save", workers=5, tasks=[save_to_db])
|
|
314
|
+
|
|
315
|
+
pipeline = Pipeline(stages=[upload_stage, check_stage, download_stage, save_stage])
|
|
316
|
+
|
|
317
|
+
# Process with progress bar
|
|
318
|
+
batches = ["batch1", "batch2", "batch3"]
|
|
319
|
+
results = await pipeline.run(batches, progress=True)
|
|
320
|
+
print(f"Results: {len(results)} items")
|
|
321
|
+
|
|
322
|
+
if __name__ == "__main__":
|
|
323
|
+
asyncio.run(main())
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**What happens**: Each stage has its own worker pool. Workers process tasks independently. As soon as a worker finishes, it picks the next task. No waiting. No idle time. Maximum throughput.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Core Concepts
|
|
331
|
+
|
|
332
|
+
### AsyncExecutor: Simple Concurrent Execution
|
|
333
|
+
|
|
334
|
+
For straightforward parallel processing, AsyncExecutor provides a `concurrent.futures`-style API:
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
import asyncio
|
|
338
|
+
from antflow import AsyncExecutor
|
|
339
|
+
|
|
340
|
+
async def process_item(x):
|
|
341
|
+
await asyncio.sleep(0.1)
|
|
342
|
+
return x * 2
|
|
343
|
+
|
|
344
|
+
async def main():
|
|
345
|
+
async with AsyncExecutor(max_workers=10) as executor:
|
|
346
|
+
# Using map() - returns list directly (like list(executor.map(...)) in concurrent.futures)
|
|
347
|
+
# retries=3 means it will try up to 4 times total with exponential backoff
|
|
348
|
+
results = await executor.map(process_item, range(100), retries=3)
|
|
349
|
+
print(f"Processed {len(results)} items")
|
|
350
|
+
|
|
351
|
+
asyncio.run(main())
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Pipeline: Multi-Stage Processing
|
|
355
|
+
|
|
356
|
+
For complex workflows with multiple steps, you can build a `Pipeline`:
|
|
357
|
+
|
|
358
|
+
```python
|
|
359
|
+
import asyncio
|
|
360
|
+
from antflow import Pipeline, Stage
|
|
361
|
+
|
|
362
|
+
async def fetch(x):
|
|
363
|
+
await asyncio.sleep(0.1)
|
|
364
|
+
return f"data_{x}"
|
|
365
|
+
|
|
366
|
+
async def process(x):
|
|
367
|
+
await asyncio.sleep(0.1)
|
|
368
|
+
return x.upper()
|
|
369
|
+
|
|
370
|
+
async def save(x):
|
|
371
|
+
await asyncio.sleep(0.1)
|
|
372
|
+
return f"saved_{x}"
|
|
373
|
+
|
|
374
|
+
async def main():
|
|
375
|
+
# Define stages with different worker counts
|
|
376
|
+
fetch_stage = Stage(
|
|
377
|
+
name="Fetch",
|
|
378
|
+
workers=10,
|
|
379
|
+
tasks=[fetch],
|
|
380
|
+
# Limit specific tasks to avoid rate limits
|
|
381
|
+
task_concurrency_limits={"fetch": 2}
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
process_stage = Stage(name="Process", workers=5, tasks=[process])
|
|
385
|
+
save_stage = Stage(name="Save", workers=3, tasks=[save])
|
|
386
|
+
|
|
387
|
+
# Build and run pipeline
|
|
388
|
+
pipeline = Pipeline(stages=[fetch_stage, process_stage, save_stage])
|
|
389
|
+
results = await pipeline.run(range(50), progress=True)
|
|
390
|
+
|
|
391
|
+
print(f"Completed: {len(results)} items")
|
|
392
|
+
print(f"Stats: {pipeline.get_stats()}")
|
|
393
|
+
|
|
394
|
+
if __name__ == "__main__":
|
|
395
|
+
asyncio.run(main())
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Why different worker counts?**
|
|
399
|
+
- **Fetch**: I/O bound, use more workers (10)
|
|
400
|
+
- **Process**: CPU bound, moderate workers (5)
|
|
401
|
+
- **Save**: Rate-limited API, fewer workers (3)
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Real-Time Monitoring with StatusTracker
|
|
406
|
+
|
|
407
|
+
Track every item as it flows through your pipeline with **StatusTracker**. Get real-time status updates, query current states, and access complete event history.
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
from antflow import Pipeline, Stage, StatusTracker
|
|
411
|
+
import asyncio
|
|
412
|
+
|
|
413
|
+
# Mock tasks
|
|
414
|
+
async def fetch(x): return x
|
|
415
|
+
async def process(x): return x * 2
|
|
416
|
+
async def save(x): return x
|
|
417
|
+
|
|
418
|
+
# 1. Define a callback for real-time updates
|
|
419
|
+
async def log_event(event):
|
|
420
|
+
print(f"Item {event.item_id}: {event.status} @ {event.stage}")
|
|
421
|
+
|
|
422
|
+
tracker = StatusTracker(on_status_change=log_event)
|
|
423
|
+
|
|
424
|
+
# Define stages
|
|
425
|
+
stage1 = Stage(name="Fetch", workers=5, tasks=[fetch])
|
|
426
|
+
stage2 = Stage(name="Process", workers=3, tasks=[process])
|
|
427
|
+
stage3 = Stage(name="Save", workers=5, tasks=[save])
|
|
428
|
+
|
|
429
|
+
pipeline = Pipeline(
|
|
430
|
+
stages=[stage1, stage2, stage3],
|
|
431
|
+
status_tracker=tracker
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# 2. Run pipeline (logs will print in real-time)
|
|
435
|
+
async def main():
|
|
436
|
+
items = range(50)
|
|
437
|
+
results = await pipeline.run(items)
|
|
438
|
+
|
|
439
|
+
# 3. Get final statistics
|
|
440
|
+
stats = tracker.get_stats()
|
|
441
|
+
print(f"Completed: {stats['completed']}")
|
|
442
|
+
print(f"Failed: {stats['failed']}")
|
|
443
|
+
|
|
444
|
+
# Get full history for an item
|
|
445
|
+
history = tracker.get_history(item_id=0)
|
|
446
|
+
|
|
447
|
+
asyncio.run(main())
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
See the [examples/](examples/) directory for more advanced usage, including **built-in dashboards** (`dashboard="compact"`, `"detailed"`, `"full"`) and a **Web Dashboard** example (`examples/web_dashboard/`).
|
|
451
|
+
|
|
452
|
+
### Monitoring: Dashboard vs StatusTracker
|
|
453
|
+
|
|
454
|
+
AntFlow provides two complementary monitoring mechanisms:
|
|
455
|
+
|
|
456
|
+
- **Dashboard (Polling)**: Built-in visual monitoring with periodic updates. Perfect for interactive debugging and real-time progress visualization. See [Dashboard Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/dashboard/).
|
|
457
|
+
|
|
458
|
+
- **StatusTracker (Event-driven)**: Async callbacks invoked immediately on events. Ideal for logging to external systems, integrating with monitoring tools, and complete event history. See [StatusTracker Guide](https://rodolfonobrega.github.io/AntFlow/api/tracker/).
|
|
459
|
+
|
|
460
|
+
See [Monitoring Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/monitoring/) for a detailed comparison and examples of both mechanisms.
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Documentation
|
|
465
|
+
|
|
466
|
+
AntFlow has comprehensive documentation to help you get started and master advanced features:
|
|
467
|
+
|
|
468
|
+
### 🚀 Getting Started
|
|
469
|
+
- [Quick Start Guide](https://rodolfonobrega.github.io/AntFlow/getting-started/quickstart/) - Get up and running in minutes
|
|
470
|
+
- [Installation Guide](https://rodolfonobrega.github.io/AntFlow/getting-started/installation/) - Installation instructions
|
|
471
|
+
|
|
472
|
+
### 📚 User Guides
|
|
473
|
+
- [AsyncExecutor Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/executor/) - Using the concurrent.futures-style API
|
|
474
|
+
- [Concurrency Control](https://rodolfonobrega.github.io/AntFlow/user-guide/concurrency/) - Managing concurrency limits and semaphores
|
|
475
|
+
- [Pipeline Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/pipeline/) - Building multi-stage workflows
|
|
476
|
+
- [Monitoring Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/monitoring/) - Dashboard vs StatusTracker comparison
|
|
477
|
+
- [Dashboard Guide](https://rodolfonobrega.github.io/AntFlow/user-guide/dashboard/) - Real-time monitoring and dashboards
|
|
478
|
+
- [Error Handling](https://rodolfonobrega.github.io/AntFlow/user-guide/error-handling/) - Managing failures and retries
|
|
479
|
+
- [Worker Tracking](https://rodolfonobrega.github.io/AntFlow/user-guide/worker-tracking/) - Monitoring individual workers
|
|
480
|
+
|
|
481
|
+
### 💡 Examples
|
|
482
|
+
- [Examples Index](https://rodolfonobrega.github.io/AntFlow/examples/) - **Start Here**: List of all 11+ example scripts
|
|
483
|
+
- [Basic Examples](https://rodolfonobrega.github.io/AntFlow/examples/basic/) - Simple use cases to get started
|
|
484
|
+
- [Advanced Examples](https://rodolfonobrega.github.io/AntFlow/examples/advanced/) - Complex workflows and patterns
|
|
485
|
+
|
|
486
|
+
### 📖 API Reference
|
|
487
|
+
- [API Index](https://rodolfonobrega.github.io/AntFlow/api/) - Complete API documentation
|
|
488
|
+
- [AsyncExecutor](https://rodolfonobrega.github.io/AntFlow/api/executor/) - Executor API reference
|
|
489
|
+
- [Pipeline](https://rodolfonobrega.github.io/AntFlow/api/pipeline/) - Pipeline API reference
|
|
490
|
+
- [StatusTracker](https://rodolfonobrega.github.io/AntFlow/api/tracker/) - Status tracking and monitoring
|
|
491
|
+
- [Exceptions](https://rodolfonobrega.github.io/AntFlow/api/exceptions/) - Exception types
|
|
492
|
+
- [Types](https://rodolfonobrega.github.io/AntFlow/api/types/) - Type definitions
|
|
493
|
+
- [Utils](https://rodolfonobrega.github.io/AntFlow/api/utils/) - Utility functions
|
|
494
|
+
|
|
495
|
+
You can also build and serve the documentation locally using `mkdocs`:
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
pip install mkdocs-material
|
|
499
|
+
mkdocs serve
|
|
500
|
+
```
|
|
501
|
+
Then open your browser to `http://127.0.0.1:8000`.
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## Requirements
|
|
506
|
+
|
|
507
|
+
- Python 3.9+
|
|
508
|
+
- tenacity >= 8.0.0
|
|
509
|
+
|
|
510
|
+
**Note**: For Python 3.9-3.10, the `taskgroup` backport is automatically installed.
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Running Tests
|
|
515
|
+
|
|
516
|
+
To run the test suite, first install the development dependencies from the project root:
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
pip install -e ".[dev]"
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Then, you can run the tests using `pytest`:
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
pytest
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## Contributing
|
|
531
|
+
|
|
532
|
+
Contributions are welcome! Please see our [Contributing Guidelines](CONTRIBUTING.md).
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## License
|
|
537
|
+
|
|
538
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
<p align="center">
|
|
543
|
+
Made with ❤️ to solve real problems in production
|
|
544
|
+
</p>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
AntFlow.egg-info/PKG-INFO
|
|
5
|
+
AntFlow.egg-info/SOURCES.txt
|
|
6
|
+
AntFlow.egg-info/dependency_links.txt
|
|
7
|
+
AntFlow.egg-info/requires.txt
|
|
8
|
+
AntFlow.egg-info/top_level.txt
|
|
9
|
+
antflow/__init__.py
|
|
10
|
+
antflow/_version.py
|
|
11
|
+
antflow/context.py
|
|
12
|
+
antflow/exceptions.py
|
|
13
|
+
antflow/executor.py
|
|
14
|
+
antflow/pipeline.py
|
|
15
|
+
antflow/tracker.py
|
|
16
|
+
antflow/types.py
|
|
17
|
+
antflow/utils.py
|
|
18
|
+
antflow/display/__init__.py
|
|
19
|
+
antflow/display/base.py
|
|
20
|
+
antflow/display/compact.py
|
|
21
|
+
antflow/display/detailed.py
|
|
22
|
+
antflow/display/full.py
|
|
23
|
+
antflow/display/progress.py
|
|
24
|
+
tests/test_backpressure.py
|
|
25
|
+
tests/test_display.py
|
|
26
|
+
tests/test_error_summary.py
|
|
27
|
+
tests/test_executor.py
|
|
28
|
+
tests/test_executor_concurrency.py
|
|
29
|
+
tests/test_executor_retry.py
|
|
30
|
+
tests/test_injection.py
|
|
31
|
+
tests/test_integration.py
|
|
32
|
+
tests/test_pipeline.py
|
|
33
|
+
tests/test_pipeline_concurrency.py
|
|
34
|
+
tests/test_priority.py
|
|
35
|
+
tests/test_quick_api.py
|
|
36
|
+
tests/test_retry_status.py
|
|
37
|
+
tests/test_skip_if.py
|
|
38
|
+
tests/test_stage_callbacks.py
|
|
39
|
+
tests/test_stream.py
|
|
40
|
+
tests/test_stream_memory.py
|
|
41
|
+
tests/test_task_events.py
|
|
42
|
+
tests/test_tracker.py
|
|
43
|
+
tests/test_unpacking.py
|
|
44
|
+
tests/test_wait.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
tenacity>=8.0.0
|
|
2
|
+
rich>=13.0.0
|
|
3
|
+
|
|
4
|
+
[:python_version < "3.11"]
|
|
5
|
+
taskgroup>=0.0.0a4
|
|
6
|
+
|
|
7
|
+
[dev]
|
|
8
|
+
pytest>=7.0
|
|
9
|
+
pytest-asyncio>=0.21.0
|
|
10
|
+
mypy>=1.0
|
|
11
|
+
ruff>=0.1.0
|
|
12
|
+
|
|
13
|
+
[docs]
|
|
14
|
+
mkdocs>=1.5.0
|
|
15
|
+
mkdocs-material>=9.0.0
|
|
16
|
+
mkdocstrings[python]>=0.24.0
|
|
17
|
+
mkdocs-autorefs>=0.6.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
antflow
|
antflow-0.7.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AntFlow Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|