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.7

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.7
File Size Uploaded
omnixys_cache-3.0.7.tar.gz 62.3 kB Details

Built distribution (wheel)

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

Total release size: 76.4 kB

Release files / omnixys_cache-3.0.7.tar.gz

Download URL omnixys_cache-3.0.7.tar.gz
Size 62.3 kB
Tags Source
SHA-256 checksum
How to use checksums
69ef26b3436028d95e3644859f7b39ad1e303ba76062a5d37fc485c8b14a0cd7
BLAKE2b-256 checksum
How to use checksums
c335498b3cea1febe258ed4aacf63f926acf6dce0eaa789d283ac6feb7531046
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","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.7-py3-none-any.whl

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

This release

3.0.7 This release

2 release files

3.0.6

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