genstore

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNilRedisClient = errors.New("redis genstore: nil client")

Functions

This section is empty.

Types

type GenStore

type GenStore interface {
	// Snapshot returns the current generation; missing => 0.
	Snapshot(ctx context.Context, storageKey string) (uint64, error)
	// SnapshotMany returns gens for many keys; missing => 0.
	SnapshotMany(ctx context.Context, storageKeys []string) (map[string]uint64, error)
	// Bump atomically increments and returns the new generation.
	Bump(ctx context.Context, storageKey string) (uint64, error)
	// Cleanup prunes old metadata if applicable (no-op for Redis).
	Cleanup(retention time.Duration)
	// Close releases resources (no-op ok).
	Close(context.Context) error
}

GenStore abstracts where generations live. Use LocalGenStore (default) for in-process gens, or RedisGenStore for distributed gens.

type LocalGenStore

type LocalGenStore struct {
	// contains filtered or unexported fields
}

LocalGenStore keeps generations in-process (no network I/O). Optionally starts a background cleanup goroutine that periodically prunes keys whose generation hasn't been bumped for at least `retention` duration.

  • Reads take a shared RLock (Snapshot, SnapshotMany).
  • Bumps take an exclusive Lock and are O(1).
  • Cleanup takes an exclusive Lock and scans the map.

Ctx parameters are accepted to satisfy the GenStore interface, but are ignored because all operations are local and non-blocking.

func NewLocalGenStore

func NewLocalGenStore(cleanupInterval, retention time.Duration) *LocalGenStore

NewLocalGenStore constructs a LocalGenStore.

If both cleanupInterval > 0 and retention > 0, a background goroutine is started that calls Cleanup(retention) every cleanupInterval. If either is non-positive, no background cleanup runs and you may call Cleanup manually.

func (*LocalGenStore) Bump

func (s *LocalGenStore) Bump(_ context.Context, k string) (uint64, error)

Bump atomically increments the generation for key k and updates UpdatedAt. If the key does not exist, it is created with Gen=1.

Returns the new generation value.

func (*LocalGenStore) Cleanup

func (s *LocalGenStore) Cleanup(retention time.Duration)

Cleanup removes keys whose UpdatedAt is older than retention ago.

This bounds memory usage of the in-process map for long-inactive keys. Reads remain correct if a key is cleaned up: Snapshot will report 0 until the next bump recreates the entry.

func (*LocalGenStore) Close

func (s *LocalGenStore) Close(_ context.Context) error

Close stops the optional cleanup goroutine and releases the ticker. Safe to call Close multiple times; subsequent calls are no-ops.

func (*LocalGenStore) Snapshot

func (s *LocalGenStore) Snapshot(_ context.Context, k string) (uint64, error)

Snapshot returns the current generation for key k.

Returns 0 if the key has never been bumped (i.e., missing in the map). This is safe for CAS semantics: a 0 snapshot simply causes stale writes to be skipped and stale reads to self-heal in the higher-level cache.

func (*LocalGenStore) SnapshotMany

func (s *LocalGenStore) SnapshotMany(_ context.Context, ks []string) (map[string]uint64, error)

SnapshotMany returns the current generations for all requested keys.

acquires the read lock once for the entire batch to avoid per-key lock/unlock overhead. Missing keys map to 0 (zero value).

type RedisGenStore

type RedisGenStore struct {
	// contains filtered or unexported fields
}

RedisGenStore shares per-key generations across processes and survives restarts. Optionally, a TTL can be applied to generation keys to prevent unbounded growth. If a generation key expires, readers observe gen=0 and cache entries self-heal.

func NewRedisGenStore

func NewRedisGenStore(client redis.UniversalClient, namespace string) *RedisGenStore

NewRedisGenStore creates a Redis-backed generation store without TTL.

func NewRedisGenStoreWithOptions added in v0.3.1

func NewRedisGenStoreWithOptions(opts RedisGenStoreOptions) (*RedisGenStore, error)

NewRedisGenStoreWithOptions creates a Redis-backed generation store with explicit lifecycle ownership. CloseClient should be true only when this genstore exclusively owns the client.

func NewRedisGenStoreWithTTL

func NewRedisGenStoreWithTTL(client redis.UniversalClient, namespace string, ttl time.Duration) *RedisGenStore

NewRedisGenStoreWithTTL creates a Redis-backed generation store with TTL. If ttl <= 0, keys do not expire.

func (*RedisGenStore) Bump

func (s *RedisGenStore) Bump(ctx context.Context, storageKey string) (uint64, error)

Bump atomically increments the generation and (optionally) refreshes TTL. When ttl > 0, INCR + EXPIRE are pipelined in a single round-trip and the INCR result is captured from the pipeline (no extra INCR).

func (*RedisGenStore) Cleanup

func (s *RedisGenStore) Cleanup(time.Duration)

Cleanup is not applicable for RedisGenStore (Redis handles expiry if TTL is set).

func (*RedisGenStore) Close

func (s *RedisGenStore) Close(context.Context) error

Close closes the underlying Redis client only when this genstore owns it. Shared clients are left open by default.

func (*RedisGenStore) Snapshot

func (s *RedisGenStore) Snapshot(ctx context.Context, storageKey string) (uint64, error)

Snapshot returns the current generation. Missing keys are treated as generation 0.

func (*RedisGenStore) SnapshotMany

func (s *RedisGenStore) SnapshotMany(ctx context.Context, storageKeys []string) (map[string]uint64, error)

SnapshotMany returns generations for multiple keys. Missing keys map to 0.

type RedisGenStoreOptions added in v0.3.1

type RedisGenStoreOptions struct {
	Client      redis.UniversalClient
	Namespace   string
	TTL         time.Duration
	CloseClient bool
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL