AntFlow: Async execution library with concurrent.futures-style API and advanced pipelines
Project description
AntFlow
Why AntFlow?
I was processing massive amounts of data using OpenAI's Batch API. The workflow had four steps:
- Upload batches to OpenAI
- Wait for processing
- Download results
- Save to database
I was running 10 batches at a time with basic async. The problem: I had to wait for all 10 to finish before starting the next group.
In practice, 9 batches would finish in 5 minutes and one would take 30. That one slow batch blocked everything — 25 minutes of idle time, repeated across hundreds of batches.
AntFlow fixes this with a worker pool model: each worker picks up the next task as soon as it finishes, so slow tasks never block fast ones. Worker count, retry logic, and stage configuration stay in your hands.
My batch processing went from hours to a fraction of the time.
Install
pip install AntFlow
OpenTelemetry support (optional):
pip install AntFlow[opentelemetry]
Quick Start
Three ways to create a pipeline — pick what fits:
Fluent builder
import asyncio
from antflow import Pipeline
async def fetch(x):
await asyncio.sleep(0.1)
return f"data_{x}"
async def main():
results = await (
Pipeline.create()
.add("Fetch", fetch, workers=5, retries=3)
.run(range(10), progress=True)
)
print(f"Processed {len(results)} items")
asyncio.run(main())
Stage objects
import asyncio
from antflow import Pipeline, Stage
async def process(x):
await asyncio.sleep(0.1)
return x * 2
async def main():
stage = Stage(name="Process", workers=5, tasks=[process])
pipeline = Pipeline(stages=[stage])
results = await pipeline.run(range(10), progress=True)
print(f"Processed {len(results)} items")
asyncio.run(main())
One-liner
import asyncio
from antflow import Pipeline
async def simple_task(x):
return x + 1
async def main():
results = await Pipeline.quick(range(10), simple_task, workers=5, progress=True)
print(f"Processed {len(results)} items")
asyncio.run(main())
| Method | When to use |
|---|---|
| Stage objects | Fine-grained control, custom callbacks, per-task concurrency limits |
| Fluent builder | Multi-stage pipelines, quick prototyping |
Pipeline.quick() |
Single-task scripts |
Dashboards
Pipelines run silently by default. Pass progress=True for a progress bar, or dashboard= for more detail:
results = await Pipeline.quick(items, task, workers=5, dashboard="detailed")
Options: "compact", "detailed", "full". Use "detailed" on multi-stage pipelines to spot bottlenecks per stage.
Streaming results
import asyncio
from antflow import Pipeline
async def process(x):
await asyncio.sleep(0.1)
return f"result_{x}"
async def main():
pipeline = Pipeline.create().add("Process", process, workers=5).build()
async for result in pipeline.stream(range(10)):
print(f"Got: {result.value}")
asyncio.run(main())
AsyncExecutor
For simple parallel execution without pipelines:
import asyncio
from antflow import AsyncExecutor
async def process_item(x):
await asyncio.sleep(0.1)
return x * 2
async def main():
async with AsyncExecutor(max_workers=10) as executor:
results = await executor.map(process_item, range(100), retries=3)
print(f"Processed {len(results)} items")
asyncio.run(main())
retries=3 means up to 4 total attempts with exponential backoff.
Multi-stage pipeline
import asyncio
from antflow import Pipeline, Stage
async def fetch(x):
await asyncio.sleep(0.1)
return f"data_{x}"
async def process(x):
await asyncio.sleep(0.1)
return x.upper()
async def save(x):
await asyncio.sleep(0.1)
return f"saved_{x}"
async def main():
fetch_stage = Stage(
name="Fetch",
workers=10,
tasks=[fetch],
task_concurrency_limits={"fetch": 2} # avoid rate limits
)
process_stage = Stage(name="Process", workers=5, tasks=[process])
save_stage = Stage(name="Save", workers=3, tasks=[save])
pipeline = Pipeline(stages=[fetch_stage, process_stage, save_stage])
results = await pipeline.run(range(50), progress=True)
print(f"Completed: {len(results)} items")
print(f"Stats: {pipeline.get_stats()}")
asyncio.run(main())
Worker counts follow the workload: more for I/O-bound stages, fewer where you're rate-limited.
StatusTracker
Track every item as it moves through stages:
from antflow import Pipeline, Stage, StatusTracker
import asyncio
async def fetch(x): return x
async def process(x): return x * 2
async def save(x): return x
async def log_event(event):
print(f"Item {event.item_id}: {event.status} @ {event.stage}")
tracker = StatusTracker(on_status_change=log_event)
pipeline = Pipeline(
stages=[
Stage(name="Fetch", workers=5, tasks=[fetch]),
Stage(name="Process", workers=3, tasks=[process]),
Stage(name="Save", workers=5, tasks=[save]),
],
status_tracker=tracker
)
async def main():
await pipeline.run(range(50))
stats = tracker.get_stats()
print(f"Completed: {stats['completed']}, Failed: {stats['failed']}")
history = tracker.get_history(item_id=0)
asyncio.run(main())
Dashboard vs StatusTracker: dashboards poll on an interval for visual output; StatusTracker fires async callbacks on each event. Use dashboards for interactive debugging, StatusTracker for logging to external systems.
Features
- Worker pool per stage — workers never block each other
- Per-task retry with exponential backoff
- Per-stage retry for transactional operations
- Priority queues — bypass sequential order when needed
- Interactive control — resume pipelines, inject items mid-run
- OpenTelemetry auto-instrumentation (optional)
concurrent.futures-style API (submit,map,as_completed)
Documentation
Full docs at rodolfonobrega.github.io/AntFlow:
Local docs:
pip install mkdocs-material
mkdocs serve
Requirements
- Python 3.9+
- tenacity >= 8.0.0
Python 3.9–3.10 installs the taskgroup backport automatically.
Tests
pip install -e ".[dev]"
pytest
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file antflow-0.10.0.tar.gz.
File metadata
- Download URL: antflow-0.10.0.tar.gz
- Upload date:
- Size: 72.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
425dd6574c7ffdb35a6dce21cbac4be157b9ce37fbdee9ece3927aef66c4343d
|
|
| MD5 |
18f355567971d7946a1d16dbd6c90e66
|
|
| BLAKE2b-256 |
b6f30958a701ee2c4caa4847b2a9ce0b161cd9538324a42429f5092a5c5680f1
|
Provenance
The following attestation bundles were made for antflow-0.10.0.tar.gz:
Publisher:
pypi.yml on rodolfonobrega/AntFlow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
antflow-0.10.0.tar.gz -
Subject digest:
425dd6574c7ffdb35a6dce21cbac4be157b9ce37fbdee9ece3927aef66c4343d - Sigstore transparency entry: 2047962984
- Sigstore integration time:
-
Permalink:
rodolfonobrega/AntFlow@99bb322b903e2498a07019aed85f6b7a05edb749 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/rodolfonobrega
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@99bb322b903e2498a07019aed85f6b7a05edb749 -
Trigger Event:
release
-
Statement type:
File details
Details for the file antflow-0.10.0-py3-none-any.whl.
File metadata
- Download URL: antflow-0.10.0-py3-none-any.whl
- Upload date:
- Size: 47.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75a90e202fb9247114b112d19e513168a30e260356d3b2e2ee7c5c516c5c8f1d
|
|
| MD5 |
6eb591da6ac0757c001091fc2599aa6d
|
|
| BLAKE2b-256 |
bd1fa9bb48043efc85fffea67497028728a0f387c4df4f74f16394aa78e07b2f
|
Provenance
The following attestation bundles were made for antflow-0.10.0-py3-none-any.whl:
Publisher:
pypi.yml on rodolfonobrega/AntFlow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
antflow-0.10.0-py3-none-any.whl -
Subject digest:
75a90e202fb9247114b112d19e513168a30e260356d3b2e2ee7c5c516c5c8f1d - Sigstore transparency entry: 2047963041
- Sigstore integration time:
-
Permalink:
rodolfonobrega/AntFlow@99bb322b903e2498a07019aed85f6b7a05edb749 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/rodolfonobrega
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@99bb322b903e2498a07019aed85f6b7a05edb749 -
Trigger Event:
release
-
Statement type: