Middleware
Because every provider is a Provider, decorators from github.com/xavidop/mamori/middleware nest freely. They instrument the resolve path; native watch is delegated to the wrapped provider.
Using middleware
import "github.com/xavidop/mamori/middleware"
mamori.WithProvider(
middleware.Cache(5*time.Minute, // memoize resolves for a TTL
middleware.Audit(logger, // log every access, never the payload
middleware.RateLimit(10, // <= 10 resolves/second
middleware.Failover( // primary, then replicas
primarySM, replicaSM,
),
),
),
),
)
| Middleware | What it does |
|---|---|
Cache(ttl, inner) |
Memoize successful resolves for ttl. Errors and not-found are not cached. |
Audit(logger, inner) |
Log scheme, ref, latency, and outcome. Never the value. |
Failover(primary, replicas...) |
Try primary, then each replica on a transport error. Not-found is authoritative. |
RateLimit(rps, inner) |
Space resolves to at most rps per second. |
Prefix(prefix, inner) |
Rewrite each ref’s path under a namespace (multi-tenant). |
Cache and RateLimit accept a WithClock option for deterministic tests.
Writing middleware
Middleware is just a Provider that wraps another Provider:
func Trace(inner mamori.Provider) mamori.Provider {
return &tracer{inner: inner}
}
type tracer struct{ inner mamori.Provider }
func (t *tracer) Scheme() string { return t.inner.Scheme() }
func (t *tracer) Resolve(ctx context.Context, ref mamori.Ref) (mamori.Value, error) {
start := time.Now()
v, err := t.inner.Resolve(ctx, ref)
log.Printf("resolve %s took %s (err=%v)", ref.Raw, time.Since(start), err)
return v, err
}
// Optionally forward Watch so a watchable inner stays watchable:
func (t *tracer) Watch(ctx context.Context, ref mamori.Ref) (<-chan mamori.Update, error) {
if wp, ok := t.inner.(mamori.WatchableProvider); ok {
return wp.Watch(ctx, ref)
}
return nil, errors.New("inner is not watchable") // mamori falls back to polling
}
The shipped middleware uses a shared wrapper that preserves WatchableProvider and BatchProvider when the inner supports them, so decoration never silently drops a capability.