55 lines
2.1 KiB
Markdown
55 lines
2.1 KiB
Markdown
|
|
# ADR-001: Expose Native valkey.Client Without a Wrapper Layer
|
||
|
|
|
||
|
|
**Status:** Accepted
|
||
|
|
**Date:** 2026-03-18
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
Some infrastructure modules wrap their underlying client behind a custom interface that
|
||
|
|
re-exports only the operations they anticipate callers will need. This approach has two
|
||
|
|
failure modes:
|
||
|
|
|
||
|
|
1. The wrapper becomes a bottleneck: every new operation requires a new method on the
|
||
|
|
wrapper interface, creating churn.
|
||
|
|
2. The wrapper diverges from the upstream API surface, forcing callers to learn two APIs.
|
||
|
|
|
||
|
|
Valkey (and the compatible Redis protocol) has a rich, evolving command set. A thin wrapper
|
||
|
|
that re-exports commands one at a time would either be incomplete or grow unboundedly.
|
||
|
|
|
||
|
|
## Decision
|
||
|
|
|
||
|
|
The `Component` interface exposes the native `vk.Client` directly via `Client() vk.Client`.
|
||
|
|
Callers receive a `vk.Client` value and use the valkey-go command builder API directly:
|
||
|
|
|
||
|
|
```go
|
||
|
|
cmd := vkClient.B().Set().Key(key).Value(val).Ex(ttl).Build()
|
||
|
|
err = vkClient.Do(ctx, cmd).Error()
|
||
|
|
```
|
||
|
|
|
||
|
|
The `Provider` interface is the minimal consumer-facing surface:
|
||
|
|
|
||
|
|
```go
|
||
|
|
type Provider interface {
|
||
|
|
Client() vk.Client
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
This module's only responsibilities are: constructing the client from `Config`, verifying
|
||
|
|
connectivity on `OnStart`, issuing a `PING` for health checks, and closing the client on
|
||
|
|
`OnStop`. All command execution is delegated entirely to the caller via the native client.
|
||
|
|
|
||
|
|
## Consequences
|
||
|
|
|
||
|
|
**Positive:**
|
||
|
|
- Callers have access to the full valkey-go API with no intermediary layer.
|
||
|
|
- No wrapper code to maintain as the valkey-go API evolves.
|
||
|
|
- The module stays small and focused on lifecycle management.
|
||
|
|
- Optional client-side caching (`CacheSizeEachConn`) is supported by passing the config
|
||
|
|
option through to `vk.NewClient` — no wrapper changes needed.
|
||
|
|
|
||
|
|
**Negative:**
|
||
|
|
- Callers are coupled to the `valkey-go` library's API directly. Switching to a different
|
||
|
|
Valkey/Redis client would require changes at every call site.
|
||
|
|
- Mocking in tests requires either an `httptest`-style server or a mock that satisfies the
|
||
|
|
`vk.Client` interface, which is more complex than mocking a minimal custom interface.
|