Skip to content

feat: unified middleware store interface (driver-agnostic) #217

@FumingPower3925

Description

@FumingPower3925

Summary

Define a unified, driver-agnostic store interface that all middleware store adapters build on. This prevents each middleware (session, ratelimit, csrf, cache, idempotency) from defining its own Redis/Postgres adapter with duplicated connection management.

Problem

Currently each middleware defines its own store interface:

  • session.Store — Get/Save/Delete/Reset with context
  • csrf.Storage — Get/Set/Delete (no context)
  • ratelimit.Store — Allow (domain-specific)
  • Future: cache.Store, idempotency.Store

Each will need Redis and PostgreSQL adapters, leading to 5×2 = 10+ adapter packages with duplicated connection pooling, error handling, and serialization code.

Proposal

Create a middleware/store package with:

// KV is a minimal key-value interface that driver adapters implement.
type KV interface {
    Get(ctx context.Context, key string) ([]byte, error)
    Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
    Delete(ctx context.Context, key string) error
}

Then each middleware adapter is a thin wrapper:

  • session.NewRedisStore(kv store.KV) — serializes map[string]any to JSON, delegates to KV
  • csrf.NewRedisStorage(kv store.KV) — wraps Get/Set/Delete
  • ratelimit.NewRedisStore(kv store.KV) — uses Lua scripts via an extended KV interface
  • cache.NewRedisStore(kv store.KV) — delegates with prefix

Driver packages implement store.KV:

  • driver/redisredis.NewKV(client) implementing store.KV
  • driver/postgrespostgres.NewKV(pool) implementing store.KV

Benefits

  • Add a new driver (Memcached, DynamoDB) once → all middleware get it
  • Middleware authors don't need to know about Redis/Postgres internals
  • Connection management stays in the driver, not in each middleware adapter
  • Testable via store.MemoryKV (in-memory implementation for tests)

Metadata

Metadata

Labels

middlewareMiddleware implementation

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions