@agentbadge/cache
v0.2.0
Published
Shared cache layer for AgentBadge — CacheProvider contract, InMemoryCache fallback, Valkey/Upstash backends
Downloads
557
Maintainers
Readme
@agentbadge/cache
Shared cache layer for AgentBadge. Exposes a CacheProvider contract with
pluggable backends:
InMemoryCache— zero-dependency per-process fallback (default whenCACHE_ENABLED=falseon the server).ValkeyCache— local dev backend overioredis(docker-compose Valkey, host port 6336). Acceptsvalkey:///redis://URLs.UpstashCache— production backend over@upstash/redisHTTP REST (no persistent TCP; works from Fly.io).
All Redis-backed providers share RedisCacheBase over a minimal
RedisCommands surface — values are JSON-encoded, tags use
tag:{tag}/keytags:{key} sets, and every op degrades to a safe default
(null/false/0) on backend failure instead of throwing.
Factory
import { createCache } from "@agentbadge/cache";
const cache = createCache({
enabled: true,
backend: "valkey", // "memory" | "valkey" | "upstash"
url: "valkey://localhost:6336", // or UPSTASH_REDIS_REST_URL
// token: "…", // Upstash only
});enabled:false, unknown backend, or missing url/token → InMemoryCache.
createCache never throws.
Contract
interface CacheProvider {
get<T>(key: string): Promise<T | null>;
set<T>(key: string, value: T, opts?: { ttlSec?: number; tags?: string[] }): Promise<void>;
delete(key: string): Promise<boolean>;
invalidateTag(tag: string): Promise<number>;
incr(key: string, ttlSec?: number): Promise<number>;
health(): Promise<boolean>;
close(): Promise<void>;
}Rules (EPIC-144):
- TTL always set by callers as a safety net; tags only where a real
invalidation event exists (e.g. rescan →
domain:{d}). - Never block the request path on cache failure — degrade to passthrough.
Usage
import { InMemoryCache } from "@agentbadge/cache";
const cache = new InMemoryCache({ maxEntries: 10_000 });
await cache.set("badge:example.com", { score: 92 }, { ttlSec: 300, tags: ["domain:example.com"] });
const hit = await cache.get("badge:example.com");
await cache.invalidateTag("domain:example.com");
await cache.close();Dev backend
Valkey runs in packages/database/docker-compose.yml (host port 6336):
cd ../database && bun run db:up # starts Postgres + Valkey
valkey-cli -p 6336 ping # → PONGGotchas
- Never throw into the request path — providers degrade to safe defaults (null/false/0) on backend failure.
- TTL is mandatory by convention — callers always pass
ttlSec. - Tag scheme:
domain:{d}per-entry (rescan invalidation) + shared tags likebadgefor bulk clear.
See RUNBOOK.md for dev/prod setup, key map, and troubleshooting.
Scripts
bun run build—tsc→dist/bun run test/bunx vitest run— unit tests
Questions & Contact
- Site: https://agentbadge.xyz/
- Contact page: https://agentbadge.xyz/contact
- Discord / Telegram / e-mail: see https://agentbadge.xyz/contact
