Files
2026-05-27 23:29:53 +01:00

3.4 KiB

OpenSpec Change: enterprise-server-cache-memory

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

Summary

Deliver @suaveplan/cache-memory on the genesis branch from scratch at enterprise quality. The package provides a zero-dependency, in-process LRU + TTL cache adapter implementing the same interface contract as @suaveplan/cache-redis. It is the primary testing stand-in and the default cache for single-server deployments. Genesis ships with a doubly-linked-list LRU eviction algorithm, injectable Clock for deterministic time testing, Zod-validated options, OTel counters/histograms, structured logging, and 100% test coverage via property-based tests.


Current-state audit (genesis)

Does not exist on genesis — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) Typed error codes for CACHE_MEMORY.*
@suaveplan/types (workspace:^) StorageLike, LoggerLike, Clock
@suaveplan/logger (workspace:^) Structured logs
zod (catalog:forms) Options validation
@opentelemetry/api (catalog:observability) Counters + histograms
tslib (catalog:build) Runtime helpers

Public API surface

Adapter

class MemoryCacheAdapter {
  constructor(options?: MemoryCacheOptions)
  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>
  size(): number
  stats(): CacheStats
}

function createMemoryCacheAdapter(options?: MemoryCacheOptions): MemoryCacheAdapter

Options + types

interface MemoryCacheOptions {
  maxSize?: number         // max number of entries, default: 1000
  defaultTtlMs?: number    // default TTL when none supplied; undefined = no expiry
  clock?: Clock            // injectable for testing
  logger?: LoggerLike
}

interface CacheStats {
  hits: number
  misses: number
  evictions: number
  size: number
  hitRate: number
}

const MemoryCacheOptionsSchema: z.ZodSchema<MemoryCacheOptions>

Error codes

type MemoryCacheErrorCode =
  | 'CACHE_MEMORY_INVALID_KEY'
  | 'CACHE_MEMORY_CAPACITY_EXCEEDED'

function registerMemoryCacheErrorCodes(): void

File layout

server/data/cache-memory/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/
      index.ts
    types/
      cache-memory.types.ts
      cache-memory.types.md
    adapter/
      memory-cache-adapter/
        memory-cache-adapter.ts
        memory-cache-adapter.md
        memory-cache-adapter.types.ts
        memory-cache-adapter.test.ts
        index.ts
    lru/
      lru-cache/
        lru-cache.ts
        lru-cache.md
        lru-cache.test.ts
        index.ts
  tests/
    property.test.ts

Impact

Downstream consumers: testing utilities, unit-test doubles for packages that depend on cache-redis. Universal helper — no Node.js IO, pure in-process.

Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/logger.