Files
suaveplan/openspec/changes/enterprise-server-cache-redis/proposal.md
2026-05-27 23:29:53 +01:00

3.9 KiB

OpenSpec Change: enterprise-server-cache-redis

  • Change ID: enterprise-server-cache-redis
  • Package: @suaveplan/cache-redis
  • Category: server/data
  • Target path: server/data/cache-redis
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/cache-redis.md

Summary

Deliver @suaveplan/cache-redis on the genesis branch from scratch at enterprise quality. The package provides a Redis-backed cache adapter implementing the StorageLike / CacheLike interface. It wraps ioredis with typed get/set/delete/has/list/clear/ttl operations, namespace prefixing, Zod-validated connection options, circuit-breaker via @suaveplan/retry, OTel instrumentation, and structured logging. Supports both single-node and cluster modes via a single createRedisCacheAdapter factory.


Current-state audit (genesis)

The package does not exist on genesis yet — fresh build. No prior source, no test results, no coverage data.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) Typed error codes for CACHE_REDIS.*
@suaveplan/types (workspace:^) StorageLike, LoggerLike
@suaveplan/retry (workspace:^) Circuit breaker + backoff on connection loss
@suaveplan/logger (workspace:^) Structured logs
zod (catalog:forms) Options validation
@opentelemetry/api (catalog:observability) Spans + counters
ioredis (catalog:data) Redis client
tslib (catalog:build) Runtime helpers

Public API surface

Adapter

class RedisCacheAdapter {
  constructor(options: RedisCacheOptions)
  get(key: string): Promise<Uint8Array | undefined>
  set(key: string, value: Uint8Array, ttlMs?: number): Promise<void>
  delete(key: string): Promise<boolean>
  has(key: string): Promise<boolean>
  list(prefix?: string): Promise<string[]>
  clear(): Promise<void>
  ttl(key: string): Promise<number | undefined>   // remaining TTL in ms
  connect(): Promise<void>
  disconnect(): Promise<void>
  ping(): Promise<boolean>
}

function createRedisCacheAdapter(options: RedisCacheOptions): RedisCacheAdapter

Options

interface RedisCacheOptions {
  host?: string          // default: 'localhost'
  port?: number          // default: 6379
  password?: string
  db?: number
  namespace?: string     // key prefix, default: ''
  tls?: boolean
  clusterNodes?: Array<{ host: string; port: number }>
  maxRetries?: number    // default: 3
  connectTimeout?: number // default: 5000 ms
  commandTimeout?: number // default: 2000 ms
  logger?: LoggerLike
}

const RedisCacheOptionsSchema: z.ZodSchema<RedisCacheOptions>

Error codes

type RedisCacheErrorCode =
  | 'CACHE_REDIS_CONNECT_FAILED'
  | 'CACHE_REDIS_COMMAND_FAILED'
  | 'CACHE_REDIS_TIMEOUT'
  | 'CACHE_REDIS_CLUSTER_ERROR'
  | 'CACHE_REDIS_INVALID_KEY'

function registerRedisCacheErrorCodes(): void

File layout

server/data/cache-redis/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/
      index.ts
    types/
      cache-redis.types.ts
      cache-redis.types.md
    adapter/
      redis-cache-adapter/
        redis-cache-adapter.ts
        redis-cache-adapter.md
        redis-cache-adapter.types.ts
        redis-cache-adapter.test.ts
        index.ts
    utils/
      key-builder.ts
      key-builder.md
      key-builder.test.ts
  tests/
    integration.test.ts   # real Redis via docker

Impact

Downstream consumers: any server package needing distributed caching (api-gateway, rate-limiter, idempotency, sessions). No genesis package currently depends on it.

Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/retry, @suaveplan/logger. Integration tests require a live Redis instance — use docker run redis:7-alpine in CI.