atqo
Async task queue orchestrator with resource-aware scheduling.
Each actor class declares what it consumes (requirements); the scheduler holds the pool (resources) and decides how many actors of each class to run. Optional per-task rate limits gate dispatch against time-windowed budgets.
Install
uv add atqo
Usage
from atqo import ActorBase, Scheduler, SchedulerTask, SingleCPUActor
class Scraper(SingleCPUActor):
def consume(self, url):
return fetch(url)
class HeavyActor(ActorBase):
requirements = {"cpu": 2, "mem": 4}
def consume(self, arg):
return process(arg)
scheduler = Scheduler(
actors=[Scraper, HeavyActor],
resources={"cpu": 8, "mem": 16},
)
scheduler.refill_task_queue(
[SchedulerTask(u, actor=Scraper) for u in urls]
+ [SchedulerTask(j, actor=HeavyActor) for j in jobs]
)
results = scheduler.join()
Rate limits
Per-task budgets recover over time (token bucket), independent of the static resource pool:
from atqo import RateLimit
scheduler = Scheduler(
actors=[Scraper],
resources={"cpu": 4},
rate_limits={"site_a": RateLimit(10, per_seconds=60)},
)
SchedulerTask(url, actor=Scraper, rate_costs={"site_a": 1})
A task whose rate_costs exceeds a bucket's capacity raises ImpossibleRateCost at ingress — it could never run.
Simple parallel API
from atqo import parallel_map, parallel_consume
results = parallel_map(expensive_fn, items, workers=4)
parallel_consume(MyActor, items, workers=4)
Patterns
Stateful actors (logged-in browser, warm cache, etc.)
Register a separate actor class. Its __init__ performs the setup; the scheduler routes tasks needing that state via actor=.
class Browser(ActorBase):
requirements = {"browser_slot": 1}
def __init__(self):
self.driver = open_browser()
def consume(self, url):
return self.driver.fetch(url)
class LoggedInBrowser(Browser):
def __init__(self):
super().__init__()
self.driver.login(USER, PW)
scheduler = Scheduler(
actors=[Browser, LoggedInBrowser],
resources={"browser_slot": 4},
)
SchedulerTask(url, actor=LoggedInBrowser)
Hang protection
Blocking waits in the scheduler re-check their exit conditions on a poll interval rather than blocking indefinitely. Optional knobs on Scheduler(...):
task_timeout: per-task wall-clock cap. Exceeded attempts fail like any exception (count againstallowed_fail_count).stall_timeout: if no progress for this long, raiseSchedulerStalled. This also bounds the task-enqueue wait — without it, enqueuing onto a wedged event loop can block indefinitely (_put_timeoutdefaults toNone).poison_timeout: how long graceful actor drain waits before force-cancel (default 5s).
cleanup() and join() always terminate; they cancel listeners and stop the event loop unconditionally.
Metadata
Release files for atqo 2.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| atqo-2.1.0.tar.gz | 38.1 kB | Without provenance | Details for atqo-2.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| atqo-2.1.0-py3-none-any.whl | Python 3 | none | any | Details for atqo-2.1.0-py3-none-any.whl |
Total release size: 72.7 kB
Release files / atqo-2.1.0.tar.gz
| Download URL | atqo-2.1.0.tar.gz |
|---|---|
| Size | 38.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
19fa5f3ac710e363396bcaed89b1b879c4d08882084fa9236460c722bc28fe9d
|
|
BLAKE2b-256 checksum How to use checksums |
f0ff19e3bdb960cbc93d7fb90094179cf78b04663872e333c18983407f547eba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / atqo-2.1.0-py3-none-any.whl
| Download URL | atqo-2.1.0-py3-none-any.whl |
|---|---|
| Size | 34.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec095120e5757f08471d395e62b2644d636a381d72b2faae3ce4f54d40244cb9
|
|
BLAKE2b-256 checksum How to use checksums |
2c4dfaffc462039f01c569855db50c8147e7bac3a310f794522593f38b040089
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for atqo 2.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.