Skip to main content

Building blocks for single-consumer async task queue processing

Project description

pykitchen

SDK building blocks for single-consumer async task queue processing in Python.

Provides a local-filesystem queue with deferred retries, a manual priority lane, and pluggable storage/queue backend interfaces. Runtime dependency: pydantic.

examples/kafka_spark_service/ shows how to wire the SDK into a service that ingests from Kafka via Spark Structured Streaming, with one-at-a-time sequential processing.

How it works

The worker drains a queue one task at a time. On failure a task is deferred to data/retry/ with its due time encoded in the filename — so the retry schedule survives restarts without any in-memory timer. The manual inbox and a priority lane let you inject or fast-track tasks without touching Kafka.

Kafka --Spark--> enqueue ----+
manual drop  --> enqueue ----+--> data/pending/ --> in-memory queue --> worker --> data/processed/
                              |                                            |
data/priority/<id> -----------> served ahead of queue                    +-------> data/retry/  (deferred)
                                                                         \-------> data/failed/ (dead letter)

Install

pip install pykitchen

# With Spark support (requires Java 8 or 11)
pip install "pykitchen[spark]"

Or with uv:

uv sync --group dev            # SDK + dev tools (pytest, ruff)
uv sync --extra spark --group dev  # also installs pyspark==3.1.3

SDK building blocks

Building block What it gives you
Task Base task model — subclass it and implement process()
LocalConfig Filesystem path layout (pending/, retry/, failed/, …) + ensure_dirs()
WorkerConfig Retry and timing settings (max_retries, retry_delay_seconds, …)
LocalStorage Full task lifecycle on disk (persist, ack, nack, retry, dead-letter, priority)
LocalQueue Thread-safe in-memory queue backed by LocalStorage
run_worker() Single-consumer loop — calls task.process() for each task
BaseQueue / BaseStorage ABCs for custom backends (SQS, S3, Azure, …)

Quickstart

Define your task by subclassing Task and implementing process():

import threading
from pykitchen import LocalConfig, LocalQueue, LocalStorage, WorkerConfig, Task, run_worker

class PrintTask(Task):
    message: str

    def process(self) -> list:
        print(f"[{self.task_id}] {self.message}")
        return []  # return follow-up Task instances to enqueue them

cfg = LocalConfig()          # uses ./data by default
cfg.ensure_dirs()

storage = LocalStorage(cfg)
q = LocalQueue(cfg, storage)
worker_cfg = WorkerConfig(max_retries=3, retry_delay_seconds=1800)
stop = threading.Event()

q.enqueue(PrintTask(message="hello"))

run_worker(worker_cfg, q, stop)

process() must raise on failure (the worker handles retry/dead-letter) and be idempotent (delivery is at-least-once). Return a list of Task instances from process() to enqueue follow-up work.

Manual inbox

Drop a JSON file into data/manual_inbox/ — it's picked up automatically on the next worker loop iteration. The file must include a __type__ field matching your Task subclass name:

echo '{"__type__": "PrintTask", "message": "hi"}' > data/manual_inbox/a.json

Prioritise a queued task

Pending files are named <task_id>.json. To jump one to the front of the queue:

touch data/priority/<task_id>

Kafka + Spark example

examples/kafka_spark_service/ is a complete runnable service:

# No-Kafka mode — manual inbox only
ENABLE_STREAM=0 uv run python -m examples.kafka_spark_service.main

# With Kafka + Spark
ENABLE_STREAM=1 KAFKA_BOOTSTRAP=localhost:9092 KAFKA_TOPIC=input-topic \
  uv run python -m examples.kafka_spark_service.main

Put your business logic in examples/kafka_spark_service/processor.py.

Configuration (kafka_spark_service example)

Variable Default Meaning
ENABLE_STREAM true 0 = manual-inbox-only, no Kafka/Spark
KAFKA_BOOTSTRAP localhost:9092 Kafka brokers
KAFKA_TOPIC input-topic Source topic
DATA_DIR ./data Root of all on-disk state
MAX_RETRIES 3 Max total attempts (initial + retries)
RETRY_DELAY_SECONDS 1800 Deferred-retry delay (seconds)
RETRY_BACKOFF_EXP false Exponential backoff on retries
QUEUE_GET_TIMEOUT 2.0 Idle poll cadence (seconds)

Project layout

src/pykitchen/                  SDK package
  task.py                       Task base model
  worker.py                     WorkerConfig + run_worker()
  backends/
    local_config.py             LocalConfig (filesystem paths)
    local_queue.py              LocalQueue
    local_storage.py            LocalStorage
    base_queue.py / base_storage.py  ABCs for custom backends
    sqs_queue.py / s3_storage.py / azure_blob_storage.py  stubs

examples/kafka_spark_service/   Example service (Kafka + Spark)
  main.py                       Wiring: queue → stream → worker
  config.py                     KafkaSparkConfig (LocalConfig + WorkerConfig + Kafka/Spark)
  ingestion.py                  Spark Structured Streaming ingestion
  processor.py                  Business logic (replace with your own)

tests/                          pytest suite (35 tests)
pyproject.toml                  Build metadata (hatchling, UV-compatible)

Running tests

uv run pytest

Project details


Download files

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

Source Distribution

pykitchen-0.1.1.tar.gz (69.5 kB view details)

Uploaded Source

Built Distribution

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

pykitchen-0.1.1-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file pykitchen-0.1.1.tar.gz.

File metadata

  • Download URL: pykitchen-0.1.1.tar.gz
  • Upload date:
  • Size: 69.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pykitchen-0.1.1.tar.gz
Algorithm Hash digest
SHA256 e399433171d61d7969154695bf06b4e3c458c6b6aaf422cc8c611c48a58ba12e
MD5 556cbab8a83d5d9f869c7f36c13b293b
BLAKE2b-256 b52f70f9c7488d8d8c958d4722810160f8deac65b328dfac010c724206724179

See more details on using hashes here.

Provenance

The following attestation bundles were made for pykitchen-0.1.1.tar.gz:

Publisher: build.yml on baskervilski/SimpleAsyncProcessor

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

File details

Details for the file pykitchen-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pykitchen-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 15.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pykitchen-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 af1c7642e1be712065c68e2d61076e50e08cdb1eeba612af18a008aefa6e2d8f
MD5 0e2850d734d060a524c91fe6e8a50e47
BLAKE2b-256 30b7d5832b7fcba53675167c09f5603ae312f4af844ace35092fe2b1a4f78a62

See more details on using hashes here.

Provenance

The following attestation bundles were made for pykitchen-0.1.1-py3-none-any.whl:

Publisher: build.yml on baskervilski/SimpleAsyncProcessor

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

Supported by

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