Skip to main content

kuu

PyPI Python License Downloads

kuu


a native distributed task queue for python

uv add kuu
# extras: dashboard, nats, postgres, prometheus, redis

quick start

# myapp/app.py
from kuu import Kuu
from kuu.brokers.redis import RedisBroker
from kuu.results.redis import RedisResults

app = Kuu(broker=RedisBroker(url=...), results=RedisResults(url=...))


# myapp/tasks.py
from typing import TypedDict
from datetime import timedelta
from .app import app


class ChargeResult(TypedDict):
    ok: bool
    charged: int


@app.task
async def charge(user_id: int, amount_cents: int) -> ChargeResult:
    return {"ok": True, "charged": amount_cents}


@app.sched(every(hours=4, starting=time(hours=1, minutes=30))) # 1:30, 5:30, 9:30...
async def refresh_balance() -> None: ...


# myapp/main.py
from .tasks import charge


async def run() -> None:
    # type checker infers TaskHandle[ChargeResult]
    # args/kwargs of the task remain typed
    handle = await charge.q(user_id=1, amount_cents=500)

    # type checker infers ChargeResult
    result = await handle.result(timeout=30)
# reads ./kuunfig.toml or [tool.kuu] in ./pyproject.toml
# starts control plane with all presets spawned
uv run kuu start

# singular preset with dashboard / remote uplink
uv run kuu start --preset ...

what's inside

  • brokers: Redis Streams, NATS JetStream, in-memory (for tests)
  • scheduler: interval jobs (@app.every) and composable cron-like schedules (@app.sched)
  • middleware: logging, retry with exponential backoff + jitter, timeout, plus custom hooks
  • events: pub/sub signals for task lifecycle (task_enqueued .. task_dead)
  • serialization: JSON (msgspec), Msgpack, Pickle, with extensible type coercion via marshal
  • persistence: SQLite (zero-config) and PostgreSQL backends for run/log history
  • dashboard: Starlette+HTMX web UI with live worker/queue stats and task management
  • prometheus: multiprocess metrics with worker-side emitter and client-side middleware
  • hot reload: watch filesystem changes, restart worker pool on settled batches

config

put the block below into kuunfig.toml, or under [tool.kuu] in your pyproject.toml

[default] holds base values; each [presets.<name>] overrides only the fields you set. unset fields fall back to [default]. a flat config (no [default] wrapper) still works

[default]
queues = []              # consume from; empty = auto-discover from registry
processes = 1            # worker subprocesses to spawn
concurrency = 64         # max concurrent tasks per worker
prefetch = 16            # batch size; defaults to max(1, concurrency // 4)
shutdown_timeout = 30.0  # seconds to wait for in-flight tasks on stop

[default.metrics]
enable = false
host = "0.0.0.0"
port = 9191

[default.dashboard]
enable = false
host = "0.0.0.0"
port = 8181
path = "/dashboard"

scheduler.enable = false    # run scheduler loop in-process; jobs declared via app.every / app.sched

[default.watch]
enable = false              # reload workers on filesystem changes
root = "."                  # path to watch
respect_gitignore = true    # skip files matched by .gitignore
exclude = [".git/**"]       # extra globs to exclude
reload_delay = 0.25
reload_debounce = 0.5

[default.persistence]
enable = true               # store run/log history
dsn = "sqlite:///./kuu.db"  # sqlite (default) or postgres://...;
# also can be provided via KUU_PERSISTENCE_DSN env var
schema = ""                 # postgres schema; empty = default
runs_table = "kuu_runs"              # Attempt rows
logical_runs_table = "kuu_logical_runs" # parent Runs
logs_table = "kuu_run_logs"
keep_days = 7               # auto-purge runs older than this
max_runs = 100_000          # hard cap on stored runs
log_level = "INFO"
capture_args = false        # sensitive inputs are opt-in
capture_headers = false
capture_result = false
attempt_observation_bytes = 10_485_760 # per-Attempt budget; overflow becomes a gap

[presets.prod]
processes = 8
concurrency = 256

[presets.dev]
processes = 1
concurrency = 16

any setting can be overridden from the CLI with -o dotted.path=value values are parsed as JSON when possible (true, 42, ["a","b"]), otherwise kept as strings

contribution

well if you insist... (issues / PRs welcome)

#clankersgoaway

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kuu-0.4.0.tar.gz (120.3 kB view details)

Uploaded Source

Built Distribution

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

kuu-0.4.0-py3-none-any.whl (168.3 kB view details)

Uploaded Python 3

File details

Details for the file kuu-0.4.0.tar.gz.

File metadata

  • Download URL: kuu-0.4.0.tar.gz
  • Upload date:
  • Size: 120.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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}

File hashes

Hashes for kuu-0.4.0.tar.gz
Algorithm Hash digest
SHA256 10b207be23f9a4212747cf9d2c880f0923a2a4fd9cea35fa52f667297f610334
MD5 de2714d13cd9a7b8abac247fd11514e3
BLAKE2b-256 d4c2de2dffcf75d0e26d96e337f1fd0ae244e1de0a2223e71dbf31f732e9f40f

See more details on using hashes here.

File details

Details for the file kuu-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: kuu-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 168.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","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}

File hashes

Hashes for kuu-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2cac8e494ca0372c7af8034f3a4594c52ca5e5c57f7412b1faeb5ff7ea676646
MD5 e6b632b6de0390028b246cd2d84e11df
BLAKE2b-256 7302acca9ffeaf124748323d0231ea8ef9a7924c5f9d7cfd9c4d5d37c53627b0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.2

2 files

0.4.1

2 files

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5.post1

2 files

0.2.5

2 files

0.2.4.post4

2 files

0.2.4.post3

2 files

0.2.4.post2

2 files

0.2.4.post1

2 files

0.2.4

2 files

0.2.3.post2

2 files

0.2.3.post1

2 files

0.2.3

2 files

0.2.2.post1

2 files

0.2.2

2 files

0.2.1.post4

2 files

0.2.1.post3

2 files

0.2.1.post2

2 files

0.2.1.post1

2 files

0.2.1

2 files

0.2.0.post1

2 files

0.2.0

2 files

0.1.7.post2

2 files

0.1.7.post1

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5.post2

2 files

0.1.5.post1

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.0.post1

2 files

0.1.0

2 files

0.0.2

2 files

0.0.1.post1

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page