feat(cache): add in-memory cache service (ADR-0022 Phase 1 part 2) #23

Merged
arcodange merged 1 commits from feat/cache-service-inmemory into main 2026-05-03 13:24:18 +02:00
Owner

Summary

Implements Phase 1 part 2 of ADR-0022: in-memory cache service via github.com/patrickmn/go-cache. Companion to PR #22 (rate limit middleware). Together they complete Phase 1 of the rate-limit + cache strategy.

Spec

  • Service interface (cache.Service): Set / Get / Delete / Flush / ItemCount
  • Implementation: InMemoryService backed by go-cache (TTL + automatic cleanup)
  • Config: 3 fields under cache.* (Enabled, DefaultTTLSeconds=300, CleanupIntervalSeconds=600)
  • Wired into Server struct
  • Demonstration: handleVersion now memoizes the response for 60 seconds (cache key per format)

Out of scope

  • Phase 2 (Redis-compatible shared cache via Dragonfly/KeyDB) — separate PR
  • Caching of other endpoints — separate PR(s)
  • BDD scenario — same architectural limitation as PR #22 ratelimit (testserver pre-started, env vars don't propagate). Unit tests cover the behavior. To enable BDD, testserver needs per-scenario config support.

Changes

  • pkg/cache/cache.go (NEW, 58 lines): Service interface + InMemoryService
  • pkg/cache/cache_test.go (NEW, 125 lines, 6/6 unit tests PASS)
  • pkg/config/config.go: CacheConfig + defaults + env binds + getters (mirrors RateLimitConfig pattern)
  • pkg/server/server.go: cacheService field on Server, init in NewServer, use in handleVersion
  • config.yaml: cache section with defaults
  • go.mod / go.sum: github.com/patrickmn/go-cache v2.1.0+incompatible

Test plan

  • go build ./pkg/cache/... PASS
  • go build ./pkg/config/... PASS
  • go build ./pkg/server/... PASS
  • go test ./pkg/cache/... 6/6 PASS
  • go test ./pkg/config/... PASS
  • go test ./pkg/server/... PASS
  • go test ./features/health/... PASS (no regression)
  • CI passes on the branch

Migration context

ARCODANGE Phase 1 — autonomous run via Mistral Vibe with ICM workspace at ~/Work/Vibe/workspaces/cache-service-inmemory/.

Optimization win: T6 stages 01-02 cost €2.50 (vs €5+ for similar T5 rate-limit) thanks to pre-extracted snippets in shared/. Documented in ~/.vibe/skills/prompt-builder/examples/add-feature.md.

🤖 Co-Authored-By: Mistral Vibe (devstral-2 / mistral-medium-3.5) + Claude Opus 4.7

## Summary Implements Phase 1 part 2 of [ADR-0022](adr/0022-rate-limiting-cache-strategy.md): in-memory cache service via `github.com/patrickmn/go-cache`. Companion to PR #22 (rate limit middleware). Together they complete Phase 1 of the rate-limit + cache strategy. ## Spec - Service interface (`cache.Service`): `Set / Get / Delete / Flush / ItemCount` - Implementation: `InMemoryService` backed by go-cache (TTL + automatic cleanup) - Config: 3 fields under `cache.*` (Enabled, DefaultTTLSeconds=300, CleanupIntervalSeconds=600) - Wired into Server struct - **Demonstration**: `handleVersion` now memoizes the response for 60 seconds (cache key per format) ## Out of scope - Phase 2 (Redis-compatible shared cache via Dragonfly/KeyDB) — separate PR - Caching of other endpoints — separate PR(s) - BDD scenario — same architectural limitation as PR #22 ratelimit (testserver pre-started, env vars don't propagate). Unit tests cover the behavior. To enable BDD, testserver needs per-scenario config support. ## Changes - `pkg/cache/cache.go` (NEW, 58 lines): Service interface + InMemoryService - `pkg/cache/cache_test.go` (NEW, 125 lines, 6/6 unit tests PASS) - `pkg/config/config.go`: CacheConfig + defaults + env binds + getters (mirrors RateLimitConfig pattern) - `pkg/server/server.go`: `cacheService` field on Server, init in NewServer, use in handleVersion - `config.yaml`: cache section with defaults - go.mod / go.sum: `github.com/patrickmn/go-cache v2.1.0+incompatible` ## Test plan - [x] `go build ./pkg/cache/...` PASS - [x] `go build ./pkg/config/...` PASS - [x] `go build ./pkg/server/...` PASS - [x] `go test ./pkg/cache/...` 6/6 PASS - [x] `go test ./pkg/config/...` PASS - [x] `go test ./pkg/server/...` PASS - [x] `go test ./features/health/...` PASS (no regression) - [ ] CI passes on the branch ## Migration context ARCODANGE Phase 1 — autonomous run via Mistral Vibe with ICM workspace at `~/Work/Vibe/workspaces/cache-service-inmemory/`. **Optimization win**: T6 stages 01-02 cost **€2.50** (vs €5+ for similar T5 rate-limit) thanks to pre-extracted snippets in `shared/`. Documented in `~/.vibe/skills/prompt-builder/examples/add-feature.md`. 🤖 Co-Authored-By: Mistral Vibe (devstral-2 / mistral-medium-3.5) + Claude Opus 4.7
arcodange added 1 commit 2026-05-03 13:24:01 +02:00
Implements Phase 1 part 2 of ADR-0022 (Rate Limiting and Cache Strategy):
in-memory cache service using github.com/patrickmn/go-cache. Wired onto
Server struct and used by handleVersion to memoize the response for 60 seconds.

Companion to PR #22 (per-IP rate limit middleware).

Changes:
- New: pkg/cache/cache.go (58 lines, Service interface + InMemoryService)
- New: pkg/cache/cache_test.go (125 lines, 6 unit tests, all passing)
- Modified: pkg/config/config.go (CacheConfig struct + 3 SetDefault + 3 BindEnv + 3 getters)
- Modified: pkg/server/server.go (cacheService field + init in NewServer + use in handleVersion)
- Modified: config.yaml (cache section with defaults)
- go.mod / go.sum (github.com/patrickmn/go-cache v2.1.0+incompatible)

Closes #13 (Phase 1 fully complete: rate limit in PR #22, cache here).
Phase 2 (Redis-compatible shared cache via Dragonfly/KeyDB) deferred.

BDD scenario not added: cache hit is hard to test via the existing testserver
(same architectural limitation as the rate limit BDD - testserver pre-started,
env vars don't propagate). Behavior is fully covered by unit tests (6/6 PASS).
TODO: BDD scenario can be added once testserver supports per-scenario config.

Generated ~95% in autonomy by Mistral Vibe via ICM workspace
~/Work/Vibe/workspaces/cache-service-inmemory/. T6 cost €2.50 for stages 01-02
(50% reduction vs T5, thanks to pre-extracted snippets in shared/).
Trainer (Claude) finalized commit/PR (Mistral hit max-turns).

🤖 Co-Authored-By: Mistral Vibe (devstral-2 / mistral-medium-3.5)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
arcodange merged commit 358e3df38b into main 2026-05-03 13:24:18 +02:00
arcodange deleted branch feat/cache-service-inmemory 2026-05-03 13:24:19 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange/dance-lessons-coach#23