Single-machine DAG ready-queue with state machine and thread-safe API
Project description
TopoQueue
A dependency-aware ready queue for DAG tasks.
TopoQueue behaves similarly to queue.Queue, but tasks are released only
when their dependencies are satisfied. It provides:
- DAG validation
- ready-queue scheduling
- task state machine
- thread-safe dispatch
TopoQueue is designed as a lightweight scheduling primitive for local DAG task orchestration.
Non-goals:
- distributed scheduling
- task execution frameworks
- workflow UI or monitoring systems
Installation
Requires Python 3.12+.
TopoQueue includes Cython-compiled extensions for performance.
Install dependencies before building:
- Cython
- a C compiler
- Windows: Visual Studio Build Tools
- Linux/macOS: system default compiler (gcc/clang)
Install for development:
pip install -e .
Install development dependencies:
pip install -e ".[dev]"
Run tests (install the package first, then run pytest):
pip install -e ".[dev]"
pytest tests/ -v
Alternatively, if you do not install the package, build Cython extensions in place first,
then run tests with PYTHONPATH:
pip install -e ".[dev]" # still need dev deps for pytest
python setup.py build_ext --inplace
# Linux/macOS:
PYTHONPATH=src pytest tests/ -v
# Windows PowerShell:
$env:PYTHONPATH="src"; pytest tests/ -v
Quick Start
import queue
from topoqueue import DAGData, DAGQueue, Node, State
data = DAGData(nodes={
"a": Node("a", deps=[]),
"b": Node("b", deps=["a"]),
"c": Node("c", deps=["b"]),
}, metadata={})
q = DAGQueue(data=data)
q.validate()
while not q.is_finished():
try:
node = q.get_ready(block=False)
except queue.Empty:
break
q.mark_done(node.node_id, result="ok")
q.join(timeout=5.0)
If a node fails:
q.mark_failed(node.node_id, cascade=True)
Downstream nodes will transition to CANCELED when cascade=True.
When to Use TopoQueue
TopoQueue is designed as a lightweight scheduling primitive for dependency-based task execution.
Typical use cases include:
- Local DAG task runners
- Workflow engine foundations
- Build systems or CI dependency scheduling
- Task orchestration inside a single service
- Research or experimentation with DAG schedulers
TopoQueue is most useful when you need:
- deterministic dependency resolution
- a ready queue for DAG nodes
- thread-safe worker dispatch
- a minimal core without heavy framework constraints
When Not to Use TopoQueue
TopoQueue is not intended to replace full workflow orchestration systems.
You should consider other tools if you need:
- distributed workers across multiple machines
- persistent task storage or recovery
- scheduling based on time (cron / intervals)
- built-in task execution environments
- monitoring dashboards or workflow UI
- complex retry, backoff, or SLA management
In those cases, a workflow engine such as Airflow, Prefect, or Ray may be more appropriate.
State Machine
stateDiagram-v2
[*] --> PENDING
PENDING --> READY: dependencies satisfied
DIRTY --> READY: dependencies satisfied
READY --> RUNNING: get_ready()
RUNNING --> DONE: mark_done()
RUNNING --> FAILED: mark_failed()
RUNNING --> CANCELED: cancel()
DONE --> DIRTY: invalidate()
READY --> PENDING: invalidate()
FAILED --> READY: retry (attempts < max_retries)
FAILED --> CANCELED: cascade downstream
State meanings:
PENDING
Dependencies are not yet satisfied.
READY
Dependencies completed; node is waiting in the ready queue.
RUNNING
Node has been dispatched to a worker.
DONE
Node finished successfully.
DIRTY
Node was DONE (or READY) but invalidated; must be recomputed. When all dependencies are DONE again, it becomes READY.
FAILED
Node execution failed.
CANCELED
Node was canceled (e.g. by cancel() or upstream failed with cascade).
Retry and Monitoring
Nodes support retry control using max_retries.
If mark_failed() is called and attempts < max_retries,
the node will automatically transition back to READY and be re-queued.
Each failure increments attempts automatically.
Queue statistics:
q.stats()
returns counts for each state and the value:
blocked
PENDING nodes whose dependency chain contains a FAILED node.
Queue Policy
Task dispatch order is determined by QueuePolicy.
If no policy is provided, DefaultQueuePolicy is used (priority first, then nodes with larger fan-out).
Example custom policy:
from topoqueue import DAGQueue, QueuePolicy, QueueContext, DefaultQueuePolicy
class MyPolicy(QueuePolicy):
def score(self, node, context):
return (-node.priority, 0)
q = DAGQueue(data=data, policy=MyPolicy())
Bulk Graph Construction and Persistence
Large DAGs can be built incrementally and validated once:
q = DAGQueue() q.add_nodes([...]) q.validate()
DAG structures can be serialized:
data.to_json() DAGData.from_json(s)
Node identity
Core treats node_id equality as the same node. Two common strategies:
- Stable node_id — Same id across runs;
merge_dag()identifies nodes by id and invalidates whendepsorprioritychange. - Hash-based node_id — e.g.
hash(payload + deps)so semantic change implies a new id; merge then naturally adds/removes nodes. Caller can invalidate downstream as needed.
Snapshot and restore use the same node shape (no payload/results); persistence is up to the caller.
API Overview
| Component | Description |
|---|---|
| State | PENDING, READY, RUNNING, DONE, DIRTY, FAILED, CANCELED |
| Node | node_id, deps(tuple), priority, max_retries, payload, attempts, state;to_dict();支持 **kwargs |
| DAGData | nodes, metadata;to_json() / from_json() |
| DAGQueue | validate(), add_node(), add_nodes(), merge_dag(), snapshot(), restore(), get_ready(), mark_done(), mark_failed(), invalidate(), cancel(), stats(), is_finished(), join(), rebuild_set(changed), visualization_snapshot();可选 policy;可选 result_store、event_sink;graph_version 属性 |
| VisualizationSnapshot | 调试用只读快照:node_ids, edges, node_states, ready_ids, running_ids, dirty_or_pending_ids, graph_version;to_dict() 可序列化;不可 restore |
| ResultStore | 协议:load(node_id), save(node_id, result), invalidate(node_id);由调用方实现,core 仅调用 |
| Events | node_started, node_done, node_failed, node_invalidated, dag_merged;传入 event_sink 可接收执行日志事件 |
| SnapshotData | metadata, nodes;to_dict() / from_dict();快照不含 payload |
| QueuePolicy | QueuePolicy, QueueContext, DefaultQueuePolicy |
Performance
Critical operations are implemented in Cython and compiled to C extensions.
Optimized paths include:
- DAG validation
- dependency resolution
- state transitions
- scheduling statistics
Targets (see docs/plans/2025-03-07-phase3-performance-constraints.md): 100k+ nodes DAG; O(nodes+edges) invalidation propagation.
Benchmark:
python -m benchmarks.bench_scheduler
Examples
The directory examples/wish_engine demonstrates a simple DAG executor.
The example loads a DAG from CSV and runs multiple workers that consume tasks from the ready queue.
Run the example:
python -m examples.wish_engine.run_scheduler examples/wish_engine/sample_dag.csv -n 2
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 Distributions
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 topoqueue-0.1.0.tar.gz.
File metadata
- Download URL: topoqueue-0.1.0.tar.gz
- Upload date:
- Size: 36.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
671516a3bf53ac6bca507d4a3c45835dd8440cbd8a4be37e31f0264cb1cae2a2
|
|
| MD5 |
346718f44284d74e0b21acc767f54a56
|
|
| BLAKE2b-256 |
e33f9f6a36edd72c002016182016b800e03ce67f3be6d0fa1c467597bffca57b
|
Provenance
The following attestation bundles were made for topoqueue-0.1.0.tar.gz:
Publisher:
python-publish.yml on zijian-optics/TopoQueue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topoqueue-0.1.0.tar.gz -
Subject digest:
671516a3bf53ac6bca507d4a3c45835dd8440cbd8a4be37e31f0264cb1cae2a2 - Sigstore transparency entry: 1056859245
- Sigstore integration time:
-
Permalink:
zijian-optics/TopoQueue@c341150076a92944925ddff24bb8b49951d49284 -
Branch / Tag:
refs/tags/v0.1.0-alpha - Owner: https://github.com/zijian-optics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@c341150076a92944925ddff24bb8b49951d49284 -
Trigger Event:
release
-
Statement type:
File details
Details for the file topoqueue-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: topoqueue-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d86f281999332e52a63e0cd03d951682eddf927067a027d1201a4d02612c7093
|
|
| MD5 |
701fb929f99bfa83412498f2f1179fa0
|
|
| BLAKE2b-256 |
a6f81d7f363ddf47098ffc7f7913fdabe6f5524c41306c5e3316de219ea46572
|
Provenance
The following attestation bundles were made for topoqueue-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-publish.yml on zijian-optics/TopoQueue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topoqueue-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
d86f281999332e52a63e0cd03d951682eddf927067a027d1201a4d02612c7093 - Sigstore transparency entry: 1056859247
- Sigstore integration time:
-
Permalink:
zijian-optics/TopoQueue@c341150076a92944925ddff24bb8b49951d49284 -
Branch / Tag:
refs/tags/v0.1.0-alpha - Owner: https://github.com/zijian-optics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@c341150076a92944925ddff24bb8b49951d49284 -
Trigger Event:
release
-
Statement type:
File details
Details for the file topoqueue-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: topoqueue-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78c758c2949509521fcc027080447dac97f02bd7eb910198ccb06f4587bc78b4
|
|
| MD5 |
2d91a6cc331e14510e5bc6ac7c164785
|
|
| BLAKE2b-256 |
9f65cceef0c2d2371114a821b32d5aebeafebbf4008f1ac733cc6d3d50f04b0b
|
Provenance
The following attestation bundles were made for topoqueue-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-publish.yml on zijian-optics/TopoQueue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topoqueue-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
78c758c2949509521fcc027080447dac97f02bd7eb910198ccb06f4587bc78b4 - Sigstore transparency entry: 1056859248
- Sigstore integration time:
-
Permalink:
zijian-optics/TopoQueue@c341150076a92944925ddff24bb8b49951d49284 -
Branch / Tag:
refs/tags/v0.1.0-alpha - Owner: https://github.com/zijian-optics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@c341150076a92944925ddff24bb8b49951d49284 -
Trigger Event:
release
-
Statement type:
File details
Details for the file topoqueue-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: topoqueue-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f45c6c7a898002b8d25d11985b1024abc4ae7a8c9ba20ef33114d74c63eb1556
|
|
| MD5 |
e9b8094bf1849a1263430459336339aa
|
|
| BLAKE2b-256 |
24aa5f7f32503dd987304eb1a54a2459eeb7fd653f41d643e558b870aff6dac0
|
Provenance
The following attestation bundles were made for topoqueue-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-publish.yml on zijian-optics/TopoQueue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topoqueue-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
f45c6c7a898002b8d25d11985b1024abc4ae7a8c9ba20ef33114d74c63eb1556 - Sigstore transparency entry: 1056859249
- Sigstore integration time:
-
Permalink:
zijian-optics/TopoQueue@c341150076a92944925ddff24bb8b49951d49284 -
Branch / Tag:
refs/tags/v0.1.0-alpha - Owner: https://github.com/zijian-optics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@c341150076a92944925ddff24bb8b49951d49284 -
Trigger Event:
release
-
Statement type:
File details
Details for the file topoqueue-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: topoqueue-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0ac5f4594f4ed7883a5b02ddfb7e84616c9219ff652b6f7a6f97b69179c625f
|
|
| MD5 |
6c6a1ed9d46dbc8da94479b6c1affabd
|
|
| BLAKE2b-256 |
318de0ec1397108d7a903cb339a5bdfa47301d56f3a48de6d5d5e45cc9802791
|
Provenance
The following attestation bundles were made for topoqueue-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-publish.yml on zijian-optics/TopoQueue
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
topoqueue-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
b0ac5f4594f4ed7883a5b02ddfb7e84616c9219ff652b6f7a6f97b69179c625f - Sigstore transparency entry: 1056859246
- Sigstore integration time:
-
Permalink:
zijian-optics/TopoQueue@c341150076a92944925ddff24bb8b49951d49284 -
Branch / Tag:
refs/tags/v0.1.0-alpha - Owner: https://github.com/zijian-optics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@c341150076a92944925ddff24bb8b49951d49284 -
Trigger Event:
release
-
Statement type: