{"id":30493806,"url":"https://github.com/sirstig/yokedcache","last_synced_at":"2026-04-02T11:45:11.925Z","repository":{"id":311231761,"uuid":"1042964454","full_name":"SirStig/yokedcache","owner":"SirStig","description":"High-performance Python cache library with auto-invalidation, FastAPI \u0026 SQLAlchemy integration.","archived":false,"fork":false,"pushed_at":"2026-03-24T04:28:14.000Z","size":2225,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T02:54:36.389Z","etag":null,"topics":["api","async","cache","cache-control","caching","cli","database","fastapi","high-performance","invalidation","library","metrics","pip","python","sqlalchemy","yaml"],"latest_commit_sha":null,"homepage":"https://sirstig.github.io/yokedcache/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SirStig.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-22T22:00:51.000Z","updated_at":"2026-03-24T04:28:17.000Z","dependencies_parsed_at":"2026-03-24T05:04:33.470Z","dependency_job_id":null,"html_url":"https://github.com/SirStig/yokedcache","commit_stats":null,"previous_names":["sirstig/yokedcache"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/SirStig/yokedcache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SirStig%2Fyokedcache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SirStig%2Fyokedcache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SirStig%2Fyokedcache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SirStig%2Fyokedcache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SirStig","download_url":"https://codeload.github.com/SirStig/yokedcache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SirStig%2Fyokedcache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31305793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T09:48:21.550Z","status":"ssl_error","status_checked_at":"2026-04-02T09:48:19.196Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","async","cache","cache-control","caching","cli","database","fastapi","high-performance","invalidation","library","metrics","pip","python","sqlalchemy","yaml"],"created_at":"2025-08-24T22:25:25.592Z","updated_at":"2026-04-02T11:45:11.920Z","avatar_url":"https://github.com/SirStig.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# yokedcache\n\n[![PyPI version](https://img.shields.io/pypi/v/yokedcache.svg)](https://pypi.org/project/yokedcache/)\n[![Python](https://img.shields.io/pypi/pyversions/yokedcache.svg)](https://pypi.org/project/yokedcache/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Tests](https://github.com/sirstig/yokedcache/actions/workflows/test.yml/badge.svg)](https://github.com/sirstig/yokedcache/actions/workflows/test.yml)\n[![Coverage](https://codecov.io/gh/sirstig/yokedcache/branch/main/graph/badge.svg)](https://codecov.io/gh/sirstig/yokedcache)\n\nAsync-first caching with the same API across backends: in-process memory (works out of the box), Redis, Memcached, disk, and SQLite. Tag and pattern invalidation, optional HTTP middleware, and production metrics built in.\n\nUse `await` in FastAPI, Django async views, workers, or plain asyncio. Sync code is welcome too—`get_sync` / `set_sync` / `@cached` on a normal `def` run the same async implementation, no separate client needed.\n\n**[Documentation](https://sirstig.github.io/yokedcache/)** · **[Changelog](https://sirstig.github.io/yokedcache/changelog.html)** · **[PyPI](https://pypi.org/project/yokedcache/)** · **[Issues](https://github.com/sirstig/yokedcache/issues)**\n\n---\n\n## What's included\n\n- **Multiple backends** — Memory (zero deps), Redis, Memcached, disk, SQLite; per-prefix routing to mix them\n- **Invalidation** — Tag-based, pattern-based, and auto-invalidation on DB writes\n- **Sync + async** — Full async API; sync helpers for scripts and blocking code\n- **HTTP middleware** — ETag / `Cache-Control` via Starlette (`yokedcache[web]`)\n- **Resilience** — Circuit breaker, retries, stale-if-error\n- **Observability** — Prometheus, StatsD, OpenTelemetry (optional extras)\n- **CLI** — Inspect keys, stats, and run health checks from the shell\n\n## Installation\n\n```bash\npip install yokedcache\n```\n\nThe base install ships with an in-process memory backend—no Redis required to get started. Add extras when you need them:\n\n| Extra | What it adds |\n|-------|-------------|\n| `redis` | Redis backend via `redis-py` |\n| `web` | Starlette HTTP cache middleware |\n| `backends` | Disk, SQLite, and Memcached deps together |\n| `observability` | Prometheus, StatsD, OpenTelemetry |\n| `full` | Everything above plus fuzzy search, vector search, SQLAlchemy helpers |\n\nIndividual extras: `memcached`, `disk`, `sqlite`, `monitoring`, `tracing`, `vector`, `fuzzy`, `sqlalchemy`.\n\n## Quick start\n\n**Async (memory backend, no Redis needed):**\n\n```python\nimport asyncio\nfrom yokedcache import YokedCache\nfrom yokedcache.config import CacheConfig\n\nasync def main():\n    cache = YokedCache(CacheConfig())\n    await cache.connect()\n    await cache.set(\"user:1\", {\"name\": \"Ada\"}, ttl=60)\n    print(await cache.get(\"user:1\"))\n    await cache.disconnect()\n\nasyncio.run(main())\n```\n\n**Sync (scripts and blocking code):**\n\n```python\nimport asyncio\nfrom yokedcache import YokedCache\nfrom yokedcache.config import CacheConfig\n\ncache = YokedCache(CacheConfig())\nasyncio.run(cache.connect())\ncache.set_sync(\"user:1\", {\"name\": \"Ada\"}, ttl=60)\nprint(cache.get_sync(\"user:1\"))\nasyncio.run(cache.disconnect())\n```\n\nFor Redis: `pip install \"yokedcache[redis]\"`, then set `redis_url=\"redis://...\"` on `CacheConfig` (or the env var `YOKEDCACHE_REDIS_URL`).\n\n## FastAPI example\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom yokedcache import cached_dependency\n\napp = FastAPI()\n\ncached_get_db = cached_dependency(get_db, ttl=300)\n\n@app.get(\"/users/{user_id}\")\nasync def get_user(user_id: int, db=Depends(cached_get_db)):\n    return db.query(User).filter(User.id == user_id).first()\n```\n\n## Requirements\n\n- **Python 3.10+** (tested on 3.10–3.14)\n- **Redis** is optional; install `yokedcache[redis]` and point to a Redis 6+ server when you want a shared remote cache\n\nPython 3.9 is not supported on 1.x. Pin `yokedcache==0.3.0` only as a temporary bridge—it does not receive security fixes. Upgrade when you can.\n\n## Security\n\nTreat Redis and Memcached as trusted stores—anyone who can write arbitrary keys can affect what your app deserializes. Set `allow_legacy_insecure_deserialization=False` on `CacheConfig` once you've migrated away from legacy entries.\n\nThe optional `disk` extra pulls in `diskcache`, which uses pickle. **[CVE-2025-69872](https://github.com/advisories/GHSA-w8v5-vhqr-4h9v)** covers unsafe deserialization if an attacker can write to the cache directory—no patched PyPI release exists yet. Skip the `disk` extra if you don't need it; keep the cache directory non-world-writable if you do. See [SECURITY.md](SECURITY.md).\n\n## Development\n\n```bash\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e \".[dev]\"\npytest\n```\n\nBuild the docs site locally:\n\n```bash\npip install -e \".[docs]\"\npython scripts/build_docs_site.py\ncp CHANGELOG.md site/changelog.md\npython -m pdoc yokedcache -o site/api --template-directory site-src/pdoc-template\ncd site \u0026\u0026 python -m http.server 8000\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n\nMaintained by **Project Yoked LLC**; technical lead **Joshua Kac**.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsirstig%2Fyokedcache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsirstig%2Fyokedcache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsirstig%2Fyokedcache/lists"}