Files
galaxy-game/gateway/internal/session/readthrough.go
T
2026-04-02 19:18:42 +02:00

69 lines
1.8 KiB
Go

package session
import (
"context"
"errors"
"fmt"
)
// ReadThroughCache resolves authenticated sessions from a process-local
// SnapshotStore first and falls back to another Cache only on a local miss.
type ReadThroughCache struct {
local SnapshotStore
fallback Cache
}
// NewReadThroughCache constructs a hot-path cache that seeds local snapshots
// from fallback on demand.
func NewReadThroughCache(local SnapshotStore, fallback Cache) (*ReadThroughCache, error) {
if local == nil {
return nil, errors.New("new read-through session cache: nil local cache")
}
if fallback == nil {
return nil, errors.New("new read-through session cache: nil fallback cache")
}
return &ReadThroughCache{
local: local,
fallback: fallback,
}, nil
}
// Lookup resolves deviceSessionID from local first, then performs one fallback
// lookup on a local miss and seeds the local cache with the returned snapshot.
func (c *ReadThroughCache) Lookup(ctx context.Context, deviceSessionID string) (Record, error) {
if c == nil {
return Record{}, errors.New("lookup session from read-through cache: nil cache")
}
record, err := c.local.Lookup(ctx, deviceSessionID)
switch {
case err == nil:
return record, nil
case !errors.Is(err, ErrNotFound):
return Record{}, fmt.Errorf("lookup session from read-through cache: %w", err)
}
record, err = c.fallback.Lookup(ctx, deviceSessionID)
if err != nil {
return Record{}, err
}
if err := c.local.Upsert(record); err != nil {
return Record{}, fmt.Errorf("lookup session from read-through cache: seed local cache: %w", err)
}
return cloneRecord(record), nil
}
// Local returns the mutable process-local snapshot store used by c.
func (c *ReadThroughCache) Local() SnapshotStore {
if c == nil {
return nil
}
return c.local
}
var _ Cache = (*ReadThroughCache)(nil)