grampy
A small workflow graph for work queues that already live in a storage — a database, a key-value store, or plain memory: the storage is a driver.
pip install grampy-q # from quazardous import grampy
pip install "grampy-q[postgres]" # + the PostgreSQL driver (SQLAlchemy)
Try the brick sorter → — a sorting line where bricks are sorted by colour, TNT bricks get quarantined, defused with retries or thrown away, and a sorted brick sent back waits in a lane before it runs again. It runs the real library in your browser.
You declare a DAG of nodes. Each subject (a job, a request, an offer…) goes
through the nodes; a node journal records, per subject and per node,
whether the node is running, done, skipped, failed or omitted.
Workers claim a node for eligible subjects, conclude it, and the graph
decides what becomes claimable next — forks run in parallel, joins wait for
their parents.
from quazardous.grampy import Node, NodeJournal, check_dag
from quazardous.grampy.drivers.memory import MemoryDriver
from quazardous.grampy.items import Adapter, Items
DAG = (
Node("fetch", working="fetching", state="fetched"),
Node("crop", parents=("fetch",), optional=True),
Node("read", parents=("fetch",), optional=True),
Node("judge", parents=("crop", "read"), state="judged"),
)
check_dag(DAG)
class DocsAdapter(Adapter): # how grampy reads YOUR object
def id_of(self, doc): return doc.id
def inflate(self, ids): return [LIBRARY[i] for i in ids]
def applies(self, doc, node): # one graph, subjects that differ
return node != "crop" or doc.scanned
items = Items(NodeJournal(MemoryDriver(), DAG), DocsAdapter())
lease = items.claim("fetch", 10, candidates=my_loader()) # objects in…
for doc in lease: # …and objects out
...
items.conclude("fetch", lease)
Handing grampy your objects is the canonical way to use it — see
items. The
core underneath works on ids alone and stays available: journal.claim("fetch", 10, candidates=[…]) returns subjects, and never reads your data.
The package lives in the quazardous namespace; the distribution is grampy-q
(grampy was already taken on PyPI; the q is for queue).
What it does
Each line links to the rules, where it is spelled out.
| joins as data | which parent statuses a node accepts, k of n, a step that runs on a failure |
| exclusive choices | a node names its branch; what only the others lead to is omitted at once |
| loops and history | bounded ways back, every row taken away kept with when and why |
| retries | declared backoff — constant, linear or exponential, capped, with jitter |
| leases | per node, given back by journal.expire() when a worker dies |
| waits and grace | settled by a durable signal, recorded even before the wait, or failed at its timeout |
| lanes | a subject that comes back waits, merges with the version waiting, runs again after a cooldown |
| policies | one workflow, subjects treated differently: their own retries, leases and budgets |
| rate and concurrency | several bands at once (GCRA, with bursts), a cap per node, per policy |
| versions | subjects pinned to the graph they started on, migrated all or nothing |
| items | speak your objects: handlers name a branch, or give up a step one kind skips |
| drawings | Mermaid flowchart, Mermaid state diagram, Graphviz, with live counts |
Storage
The journal never commits and never reads your tables. Eligibility is your
query, passed to claim and read inside its transaction; a claim gives back
ids, and you load your own objects. See drivers.
| driver | needs |
|---|---|
drivers.memory |
nothing — the reference the others are confronted with |
drivers.sqlite |
the standard library |
drivers.postgres |
SQLAlchemy Core |
Any other storage: implement the driver protocol and pass the shared contract
(quazardous.grampy.testing.JournalContract), concurrency tests included.
Documentation
- The rules — every mechanism, spelled out.
- Items — objects instead of ids, the canonical way.
- Drivers and candidates — tables, queries, your own data.
- Drawings — diagrams from a graph.
- The same notions in other tools — Graphile Worker, BullMQ, Hatchet, Inngest, Temporal, Oban.
- CONTRIBUTING — tests, lint, how to release.
Tests
pip install -e ".[test]" # or: uvx --with pytest pytest
pytest # graph, states, memory and SQLite drivers
GRAMPY_TEST_PG_DSN=postgresql+psycopg://user:pass@localhost/test \
pytest # + the postgres driver (needs sqlalchemy and a driver)
License
MIT
Release files for grampy-q 0.2.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 | |
|---|---|---|---|
| grampy_q-0.2.0.tar.gz | 104.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| grampy_q-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 196.3 kB
Release files / grampy_q-0.2.0.tar.gz
| Download URL | grampy_q-0.2.0.tar.gz |
|---|---|
| Size | 104.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c3a030d8400d3359b185279b0ccc5860e030be6e3806ff7fa2955fc9c0a773e9
|
|
BLAKE2b-256 checksum How to use checksums |
966e1761d502d1493c9cf1a5fb136adf94918c1fe0ffa429bc55ccd5976d3876
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / grampy_q-0.2.0-py3-none-any.whl
| Download URL | grampy_q-0.2.0-py3-none-any.whl |
|---|---|
| Size | 92.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
02dec3f9486374b4c0244780589d6738d95683646dc3c5782cdf03b27f19c0e5
|
|
BLAKE2b-256 checksum How to use checksums |
ceaddfd7de4e68afed407018b4a3a7acaa101270860b5d86363a43cfd3d43b4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log