69 lines
1.8 KiB
Go
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)
|