caching — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited caching (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Covers Redis as cache, pub/sub bus, and job queue — plus lightweight in-process caching for Node/Python services.
import redis.asyncio as aioredis
redis = aioredis.from_url(
"redis://localhost:6379",
encoding="utf-8",
decode_responses=True,
max_connections=20,
)
# Simple get/set with TTL
await redis.set("key", "value", ex=300) # expires in 5 min
value = await redis.get("key") # None if expired/missing
# Delete
await redis.delete("key")import json
async def get_article(slug: str) -> dict:
cache_key = f"article:{slug}"
cached = await redis.get(cache_key)
if cached:
return json.loads(cached)
article = await db.fetch_article(slug) # expensive DB read
await redis.set(cache_key, json.dumps(article), ex=3600)
return article
# Invalidate on write
async def update_article(slug: str, data: dict):
await db.update_article(slug, data)
await redis.delete(f"article:{slug}") # bust cache# Publisher
async def publish(channel: str, payload: dict):
await redis.publish(channel, json.dumps(payload))
await publish("article.ready", {"slug": slug, "domain": domain})
# Subscriber (runs in background task)
async def subscribe(channel: str):
pubsub = redis.pubsub()
await pubsub.subscribe(channel)
async for message in pubsub.listen():
if message["type"] == "message":
data = json.loads(message["data"])
await handle_event(data)QUEUE = "jobs:scrape"
# Enqueue
await redis.lpush(QUEUE, json.dumps({"url": url, "domain": domain}))
# Worker — blocking pop, 30s timeout
async def worker():
while True:
item = await redis.brpop(QUEUE, timeout=30)
if item:
_, raw = item
job = json.loads(raw)
await process(job)// Simple TTL map — good for server-side rendered pages
const cache = new Map();
function setCache(key, value, ttlMs = 12_000) {
cache.set(key, { value, exp: Date.now() + ttlMs });
}
function getCache(key) {
const entry = cache.get(key);
if (!entry) return null;
if (Date.now() > entry.exp) { cache.delete(key); return null; }
return entry.value;
}
// Usage (agent-dashboard pattern)
let _cache = null;
async function refreshCache() { _cache = await gatherData(); }
setInterval(refreshCache, 12_000);
refreshCache();
// API handler responds instantly from _cache
app.get('/api/status', (req, res) => res.json(_cache));async def check_rate_limit(key: str, limit: int, window_s: int) -> bool:
pipe = redis.pipeline()
pipe.incr(key)
pipe.expire(key, window_s)
count, _ = await pipe.execute()
return count <= limit
# Usage
allowed = await check_rate_limit(f"rl:{ip}", limit=60, window_s=60)
if not allowed:
raise HTTPException(429, "Rate limit exceeded")# Pattern: service:resource_type:identifier[:variant]
article:slug:keto-diet-guide
domain:stats:ketoandhealthy.com
session:token:abc123
rl:ip:1.2.3.4
jobs:scrape
jobs:publishredis-cli info memory # used_memory_human, maxmemory
redis-cli info stats # keyspace_hits, keyspace_misses (hit rate)
redis-cli info keyspace # db0: keys=N,expires=N
redis-cli dbsize # total key count
redis-cli --latency # round-trip latency
redis-cli keys "article:*" # list keys by pattern (don't use on prod with millions of keys — use SCAN)
redis-cli scan 0 match "article:*" count 100# In redis.conf or at runtime
redis-cli config set maxmemory 512mb
redis-cli config set maxmemory-policy allkeys-lru # evict least-recently-used when full
# For job queues (never evict jobs): use a separate Redis DB or instance
redis-cli -n 1 lpush jobs:scrape ... # DB 1 = queues, DB 0 = cacheservice:type:id conventionSET call — never store without expiry on cache keysmaxmemory + allkeys-lru set for pure-cache Redis instancesnoeviction policy (never lose a job)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.