Skip to main content

omnixys-cache

Omnixys shared cache package — a typed Redis/Valkey facade with JSON serialization, invalidation, distributed locks, rate limiting, streams with consumer groups, and delayed jobs, all on one client.

Installation

pip install omnixys-cache

Features

  • CacheClient: async Redis/Valkey facade with typed keys, JSON serialization, TTL handling, atomic NX/PX ops and low-level raw access
  • Key definitions: create_key(prefix, ttl_seconds) and key(...) builders validated at construction time
  • CacheLock: distributed mutual-exclusion lock with token-based (WATCH/MULTI) release
  • RateLimiter: fixed-window rate limiting with hit/check and TTL window reset
  • ValkeyStreamService: stream + consumer-group queues (ensureGroup, enqueue, consume, read_pending, ack)
  • Delayed jobs: schedule/claim/retry/cancel delayed jobs with a worker loop and decorator-driven registry
  • Invalidation: CacheInvalidationService with pluggable strategies
  • Serialization: JSON serializers (JsonCacheSerializer, StrictJsonCacheSerializer)
  • DI: CacheProvider container integration (dishka)

Usage

Client and keys

import asyncio
from cache import CacheClient, create_key

session = create_key("session", ttl_seconds=300)
cache = CacheClient(url="redis://localhost:6379", key_prefix="myapp")

async def main() -> None:
    await cache.set_json(session, {"userId": 42}, parts=("u1",))  # myapp:session:u1
    assert await cache.get_json(session, "u1") == {"userId": 42}
    await cache.expire(session, 60, "u1")
    await cache.close()

asyncio.run(main())

Raw keys work too — pass a plain str and optional parts are joined with :.

Distributed lock

from cache import CacheClient, CacheLock

async with CacheLock(cache, "deploy:eu1", ttl_ms=30_000, wait_ms=10_000) as lock:
    ...
# or manually:
lock = CacheLock(cache, "deploy:eu1", ttl_ms=30_000)
if await lock.acquire():
    try:
        ...
    finally:
        await lock.release()

Rate limiting

from cache import CacheClient, RateLimiter

limiter = RateLimiter(cache)
if not await limiter.check("sms:user:42", limit=5, ttl_seconds=60).allowed:
    raise RuntimeError("rate limit exceeded")

Streams with consumer groups

from cache import CacheClient, ValkeyStreamService

streams = ValkeyStreamService(cache)
await streams.ensure_group("jobs", "workers")

await streams.enqueue("jobs", {"type": "resize", "imageId": "abc"})

for message in await streams.consume("jobs", "workers", consumer="w1", block_ms=1_000):
    payload = message.data          # {"type": "resize", "imageId": "abc"}
    await streams.ack("jobs", "workers", message.id)

Delayed jobs

from cache import DelayedJobService, DelayedJobSchedule, DelayedJobWorker, delayed_job

@delayed_job("image.resize")
async def resize(payload: dict) -> None:
    print(payload["imageId"])

service = DelayedJobService(cache)
job_id = await service.schedule(
    DelayedJobSchedule(type="image.resize", payload={"imageId": "abc"}, delay_ms=5_000)
)

worker = DelayedJobWorker(service)          # uses the default (decorated) registry
await worker.start()

Jobs are persisted as records (7-day TTL), scheduled on a sorted set (delayed:jobs), claimed atomically via WATCH/MULTI, retried on failure up to max_retries, and surfaced through status(), cancel(), retry(), and claim_due().

Testing

The package ships behavior-level tests (pytest + fakeredis, no server needed):

uv run pytest -q          # 47 tests
uv run ruff check .       # lint
uv run mypy src/          # strict typing

License

GPL-3.0-or-later

Metadata

Release files for omnixys-cache 3.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for omnixys-cache 3.0.6
File Size Uploaded
omnixys_cache-3.0.6.tar.gz 62.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for omnixys-cache 3.0.6
File Interpreter ABI Platform
omnixys_cache-3.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 76.2 kB

Release files / omnixys_cache-3.0.6.tar.gz

Download URL omnixys_cache-3.0.6.tar.gz
Size 62.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ab7cfe7c4c0d17904196e93d3312b214b2059e53cfd682442cf532c73aee19b6
BLAKE2b-256 checksum
How to use checksums
86d727f4289725a3680313e5574715ed0fae4b49303e260108beb02f92b54bf2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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}

Release files / omnixys_cache-3.0.6-py3-none-any.whl

Download URL omnixys_cache-3.0.6-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1a2d298d1658b833e25399aa648fd56d3be5d0eed27ee1c76ca25c7b8433f6b5
BLAKE2b-256 checksum
How to use checksums
07f34532e267a57fc6817794538ba6d9f89fdb5a8ad93d955b19e3bc5c7f0b6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","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}

Release history Release notifications | RSS feed

5.0.0

2 release files

3.0.7

2 release files

This release

3.0.6 This release

2 release 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