cairnq (Python)
SQLite-first, cross-language, storage-centered durable task runtime. The Python SDK. API and worker processes coordinate only through a shared SQLite file.
from cairnq import CairnQ, Worker
# Worker side — a handler always receives (ctx, payload).
worker = Worker.sqlite("tasks.db")
@worker.task # registered under the function name, "create_summary"
async def create_summary(ctx, payload):
await ctx.progress(0.2, "reading")
return {"summary": await llm.summarize(payload["text"])}
worker.serve() # blocking entry point; Ctrl-C closes cleanly
# API side (in your server) — submit returns immediately.
tasks = CairnQ.sqlite("tasks.db")
task = await tasks.submit("create_summary", {"text": text}, key=f"summary:{aid}")
@worker.task defaults the task name to the function's name. Pass a string for a
dotted/namespaced name: @worker.task("summary.create").
Synchronous call (submit + wait):
from cairnq import TaskFailed, TaskTimeout
try:
result = await tasks.call("create_summary", {"text": text}, wait_timeout_ms=10_000)
except TaskFailed as e:
log(e.code, e.message, e.retryable) # envelope fields, no e.error["code"] digging
except TaskTimeout as e:
# The task keeps running — resume the wait instead of submitting again.
result = await tasks.wait(e.task_id, timeout_ms=60_000)
# …or tasks.wait_by_key(key), from a process that never held the id.
Inspect a task by id/key without memorizing status strings:
task = await tasks.get_by_key(key)
if task and task.succeeded: # also .failed / .canceled / .running / .queued / .is_terminal
use(task.result)
Optionally define a task once and share the symbol across both ends — the name
lives in one place (no string drift), and call() is typed as the task's result:
from cairnq import TaskDef
summarize = TaskDef[dict, dict]("summarize")
@worker.task(summarize) # registered under summarize.name
async def handle(ctx, payload): ...
result = await tasks.call(summarize, {"text": text})
Opt-in: every API still accepts a plain name string (cross-language callers use it).
Running it in production
worker = Worker.sqlite(
"tasks.db",
concurrency=4, # handler calls at once; use max_in_flight_bytes to bound memory
retry_backoff_ms=1_000, # window doubles per attempt, capped at retry_backoff_max_ms (30s),
# jittered over its upper half; 0 disables
on_error=lambda exc, info: log.warning("worker survived %s: %s", info, exc),
)
# Nothing else deletes rows, so give the client a retention policy — it sweeps
# terminal tasks in bounded batches for as long as the handle is open.
tasks = CairnQ.sqlite("tasks.db", retention=Retention(older_than_ms=7 * 24 * 3600_000))
A sync handler (def, not async def) is dispatched to a thread, so the
usual shape around a blocking GPU or HTTP call keeps the worker's event loop —
and with it every lease this worker holds — alive:
@worker.task("score")
def score(ctx, payload):
return {"score": model.forward(payload["image"])} # blocking, off the loop
A handler that does real side effects should bail out when it loses its lease — the task is already running on another worker and nothing it writes is recorded:
@worker.task("long.job")
async def long_job(ctx, payload):
for chunk in chunks:
if ctx.lost_lease or await ctx.canceled():
return
await process(chunk)
Multi-host
Same code, Postgres instead of the file — CairnQ.postgres(dsn) /
Worker.postgres(dsn). Install with pip install cairnq[postgres].
The protocol (schema + canonical SQL) lives in ../cairnq-protocol and is shared
verbatim with the TypeScript SDK. See ../cairnq-protocol/PROTOCOL.md.
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 cairnq-0.7.0.tar.gz.
File metadata
- Download URL: cairnq-0.7.0.tar.gz
- Upload date:
- Size: 130.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a05130b7a16d208b7c8d445f031ac9eadd7cfa8c7a8150f7ab64b275ce7edd7
|
|
| MD5 |
cb126288e7de896d64ab1f05f54ac9ac
|
|
| BLAKE2b-256 |
4bdf3ce16c5e3648b1d33e4c19c940f024f21c63235a88b5e88f51be5be86b85
|
Provenance
The following attestation bundles were made for cairnq-0.7.0.tar.gz:
Publisher:
publish.yml on Jannchie/cairnq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cairnq-0.7.0.tar.gz -
Subject digest:
0a05130b7a16d208b7c8d445f031ac9eadd7cfa8c7a8150f7ab64b275ce7edd7 - Sigstore transparency entry: 2464079442
- Sigstore integration time:
-
Permalink:
Jannchie/cairnq@72fd662913b8491c35a570ee7fc6e360eba92312 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Jannchie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@72fd662913b8491c35a570ee7fc6e360eba92312 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cairnq-0.7.0-py3-none-any.whl.
File metadata
- Download URL: cairnq-0.7.0-py3-none-any.whl
- Upload date:
- Size: 107.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
991a9e3aeb35b5a7388101ff457e0398de2cbcec53bcb3d723a1f1aba6a3bdcf
|
|
| MD5 |
6463d67979196644d28f544bdf4ff66e
|
|
| BLAKE2b-256 |
ba1caea43308bc72c059818244c405384029f1e2f4825dfc6be685cabdc77cc9
|
Provenance
The following attestation bundles were made for cairnq-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on Jannchie/cairnq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cairnq-0.7.0-py3-none-any.whl -
Subject digest:
991a9e3aeb35b5a7388101ff457e0398de2cbcec53bcb3d723a1f1aba6a3bdcf - Sigstore transparency entry: 2464079475
- Sigstore integration time:
-
Permalink:
Jannchie/cairnq@72fd662913b8491c35a570ee7fc6e360eba92312 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Jannchie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@72fd662913b8491c35a570ee7fc6e360eba92312 -
Trigger Event:
push
-
Statement type: