blazers

Cache API

Concepts: Cache

Base: /api/cache — admin-level RBAC.

GET /api/cache — list

All entries:

[
  {
    "key": "theme",
    "value": "dark",
    "ttl": 3600,
    "expires_at": "2025-01-01T01:00:00Z",
    "created_at": "...",
    "updated_at": "..."
  }
]

POST /api/cache — set

Body

{ "key": "theme", "value": "dark", "ttl": 3600 }

key and value required; ttl in seconds (0/absent = never expires).

Response 201 — the CacheEntry. 400 if key/value empty.

GET /api/cache/{key} — get

Returns the CacheEntry or 404.

DELETE /api/cache/{key} — delete one

204; 404 if the key doesn't exist.

DELETE /api/cache — flush

Wipe all entries. 200 → {"status": "flushed"}.

GET /api/cache/keys — key names

{ "keys": ["session:abc", "visits", "user:1"] }

Sorted names of all unexpired entries (strings, lists and hashes alike).

GET /api/cache/exists/{key} — existence check

{ "key": "theme", "exists": true }

POST /api/cache/delete — delete many

Body { "keys": ["a", "b"] } → { "deleted": 2 }. 400 on empty keys.

GET /api/cache/stats — stats

{ "total_entries": 12, "expired_entries": 3, "memory": true }

Typed values — strings, lists, hashes

POST /api/cache always stores a string. Two richer types are available through dedicated endpoints; they share the same key namespace and TTL rules. Using a typed op on a key of the wrong type returns 400 WRONGTYPE.

  • List — stored as a JSON envelope; a plain GET /api/cache/{key} returns the encoded payload, e.g. {"__type":"list","items":[...]}.
  • Hash — {"__type":"hash","fields":{...}}.

Counters & strings

Endpoint Body Response
POST /api/cache/{key}/incr { "by": 1 } (by optional, default 1) { "key", "value" } — new integer value
POST /api/cache/{key}/append { "value": "..." } { "key", "value" } — full string after append
POST /api/cache/{key}/expire { "ttl": 3600 } (0 clears expiry) { "key", "ttl" }; 404 if missing
GET /api/cache/{key}/ttl — { "key", "ttl" } — seconds left, -1 = no expiry; 404 if missing

INCR on a missing key starts at 0; on a non-integer string it errors. All mutations are atomic.

Lists

Endpoint Body / query Response
POST /api/cache/{key}/list { "values": [...], "left": false } { "key", "length" } — push right (RPUSH) or left (LPUSH)
POST /api/cache/{key}/list/pop { "left": false, "count": 1 } { "key", "value" } — single item, or array when count > 1; null when empty
GET /api/cache/{key}/list?start=0&stop=-1 Redis-style inclusive range, negatives from end { "key", "items": [...] }

An emptied list key is deleted, like Redis.

Hashes

Endpoint Body Response
POST /api/cache/{key}/hash { "field": "f", "value": v } or { "fields": {"f": v, ...} } { "key", "fields_set" }
GET /api/cache/{key}/hash — { "key", "fields": {...} }
GET /api/cache/{key}/hash/{field} — { "key", "field", "value" } (value: null if absent)
DELETE /api/cache/{key}/hash/{field} comma-separated fields allowed { "key", "removed" }

An emptied hash key is deleted. Hash field values are arbitrary JSON.

curl -X POST localhost:8090/api/cache/visits/incr \
  -H "Authorization: Bearer $TOKEN" -d '{"by": 1}'
curl -X POST localhost:8090/api/cache/jobs/list \
  -H "Authorization: Bearer $TOKEN" -d '{"values": ["job-1"]}'
curl -X POST localhost:8090/api/cache/user:42/hash \
  -H "Authorization: Bearer $TOKEN" -d '{"fields": {"plan": "pro"}}'

KV TCP protocol {#kv-tcp-protocol}

blazers kv [--port 6379] [--bind 127.0.0.1] serves the same cache over a Redis-style inline protocol: one command per line, one reply per line — compatible with kevin and usable with nc, telnet, or any line client.

$ blazers kv --port 6379 &
$ printf 'PING\nSET k v EX 30\nGET k\nTTL k\n' | nc 127.0.0.1 6379
PONG
OK
v
29
Command Reply
PING PONG
SET key value [EX seconds] OK / ERR invalid expire time
GET key value, (nil), or the typed JSON envelope
DEL key [key ...] count removed
EXISTS key 1 / 0
KEYS [pattern] sorted keys; * and ? glob
TYPE key string / list / hash / none
LEN unexpired key count
FLUSHALL / FLUSHDB OK
EXPIRE key seconds 1 / 0
TTL key seconds left, -1 no expiry, -2 missing
INCR key / DECR key / INCRBY key n new integer
APPEND key value new string length
LPUSH/RPUSH key v [v ...] new list length
LPOP/RPOP key [count] item(s) or (nil)
LRANGE key start stop space-separated slice
HSET key f v [f v ...] fields written
HGET key f / HGETALL key / HDEL key f ... / HLEN key field ops

Errors are ERR … lines; type mismatches are ERR WRONGTYPE ….

Set BLAZERS_KV_PASSWORD to require AUTH password before any other command (NOAUTH until authenticated, WRONGPASS on a bad password).