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)
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
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) <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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
cache.Service):Set / Get / Delete / Flush / ItemCountInMemoryServicebacked by go-cache (TTL + automatic cleanup)cache.*(Enabled, DefaultTTLSeconds=300, CleanupIntervalSeconds=600)handleVersionnow memoizes the response for 60 seconds (cache key per format)Out of scope
Changes
pkg/cache/cache.go(NEW, 58 lines): Service interface + InMemoryServicepkg/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:cacheServicefield on Server, init in NewServer, use in handleVersionconfig.yaml: cache section with defaultsgithub.com/patrickmn/go-cache v2.1.0+incompatibleTest plan
go build ./pkg/cache/...PASSgo build ./pkg/config/...PASSgo build ./pkg/server/...PASSgo test ./pkg/cache/...6/6 PASSgo test ./pkg/config/...PASSgo test ./pkg/server/...PASSgo test ./features/health/...PASS (no regression)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