Skip to main content

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:
    ...  # e.task_id keeps running

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,
    retry_backoff_ms=1_000,   # doubles per attempt, capped by retry_backoff_max_ms (30s); 0 disables
    on_error=lambda exc, info: log.warning("worker survived %s: %s", info, exc),
)

# Nothing else deletes rows. Sweep terminal tasks on a schedule.
await tasks.purge(older_than_ms=7 * 24 * 3600_000)

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

cairnq-0.2.0.tar.gz (73.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cairnq-0.2.0-py3-none-any.whl (62.1 kB view details)

Uploaded Python 3

File details

Details for the file cairnq-0.2.0.tar.gz.

File metadata

  • Download URL: cairnq-0.2.0.tar.gz
  • Upload date:
  • Size: 73.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cairnq-0.2.0.tar.gz
Algorithm Hash digest
SHA256 546e537b3ddd8b5c9c4dd37c2a4b37cd938bc79cc76f438f28a1a9073eca8bf7
MD5 a66f661d470192cd3096ef28ecb9f4a8
BLAKE2b-256 50c18bd497a480d8e0dd94fbd411a485e558c8f90d5ce1f723a4ca1f535699e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for cairnq-0.2.0.tar.gz:

Publisher: publish.yml on Jannchie/cairnq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cairnq-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cairnq-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 62.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cairnq-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e24204e2c1ac6b9a125a152e96a8083d970fcfc9771d337337e114954a62107d
MD5 4527695db8721604c6c2cdaa744ad167
BLAKE2b-256 05a66d5532c4729a2f26e97b2b04bc34273c0dba0ae5d100af6b0f462e3ef68e

See more details on using hashes here.

Provenance

The following attestation bundles were made for cairnq-0.2.0-py3-none-any.whl:

Publisher: publish.yml on Jannchie/cairnq

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.14.0

2 files

0.13.0

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

This release

0.2.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page