session

package
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2026 License: GPL-3.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry added in v0.0.2

type Entry struct {
	WorkerID   string
	UserSub    string    // bound user identity; empty when OIDC is not configured
	LastAccess time.Time // updated on every proxy request; used for idle sweep
}

Entry holds the state for a single session.

type LayeredStore added in v0.0.4

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

LayeredStore layers a cache Store over a primary Store (see #286, parent #262). The primary is the source of truth (Postgres in production); the cache is an optional optimization (Redis).

Reads: cache first; on miss, fall back to primary and populate the cache on the way out.

Writes: primary first; cache mirrored best-effort. Cache errors are already swallowed inside the concrete stores (they log and return false/zero), so LayeredStore just calls both sequentially — the primary operation's outcome is the one surfaced to callers.

Aggregate queries (CountForWorker, EntriesForWorker) always go to the primary: the cache may hold a subset and can't answer accurately.

func NewLayeredStore added in v0.0.4

func NewLayeredStore(primary, cache Store) *LayeredStore

func (*LayeredStore) CountForWorker added in v0.0.4

func (s *LayeredStore) CountForWorker(workerID string) int

func (*LayeredStore) CountForWorkers added in v0.0.4

func (s *LayeredStore) CountForWorkers(workerIDs []string) int

func (*LayeredStore) Delete added in v0.0.4

func (s *LayeredStore) Delete(sessionID string)

func (*LayeredStore) DeleteByWorker added in v0.0.4

func (s *LayeredStore) DeleteByWorker(workerID string) int

func (*LayeredStore) EntriesForWorker added in v0.0.4

func (s *LayeredStore) EntriesForWorker(workerID string) map[string]Entry

func (*LayeredStore) Get added in v0.0.4

func (s *LayeredStore) Get(sessionID string) (Entry, bool)

func (*LayeredStore) RerouteWorker added in v0.0.4

func (s *LayeredStore) RerouteWorker(oldWorkerID, newWorkerID string) int

func (*LayeredStore) Set added in v0.0.4

func (s *LayeredStore) Set(sessionID string, entry Entry)

func (*LayeredStore) SweepIdle added in v0.0.4

func (s *LayeredStore) SweepIdle(maxAge time.Duration) int

SweepIdle runs against the primary. RedisStore.SweepIdle is a no-op because native TTL already expires idle cache entries around the same cutoff — idle sweep and TTL share the idle_ttl setting.

func (*LayeredStore) Touch added in v0.0.4

func (s *LayeredStore) Touch(sessionID string) bool

type MemoryStore added in v0.0.3

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

MemoryStore is a concurrent in-memory implementation of Store.

func NewMemoryStore added in v0.0.3

func NewMemoryStore() *MemoryStore

func (*MemoryStore) CountForWorker added in v0.0.3

func (s *MemoryStore) CountForWorker(workerID string) int

func (*MemoryStore) CountForWorkers added in v0.0.3

func (s *MemoryStore) CountForWorkers(workerIDs []string) int

CountForWorkers returns the total session count across the given worker IDs.

func (*MemoryStore) Delete added in v0.0.3

func (s *MemoryStore) Delete(sessionID string)

func (*MemoryStore) DeleteByWorker added in v0.0.3

func (s *MemoryStore) DeleteByWorker(workerID string) int

DeleteByWorker removes all sessions mapped to the given worker. Linear scan — acceptable at max_workers = 100.

func (*MemoryStore) EntriesForWorker added in v0.0.3

func (s *MemoryStore) EntriesForWorker(workerID string) map[string]Entry

EntriesForWorker returns a snapshot of all sessions for a worker.

func (*MemoryStore) Get added in v0.0.3

func (s *MemoryStore) Get(sessionID string) (Entry, bool)

Get returns the entry for the given session ID.

func (*MemoryStore) RerouteWorker added in v0.0.3

func (s *MemoryStore) RerouteWorker(oldWorkerID, newWorkerID string) int

RerouteWorker reassigns all sessions from oldWorkerID to newWorkerID. Used by container transfer to migrate sessions to the new worker.

func (*MemoryStore) Set added in v0.0.3

func (s *MemoryStore) Set(sessionID string, entry Entry)

Set creates or replaces a session entry.

func (*MemoryStore) SweepIdle added in v0.0.3

func (s *MemoryStore) SweepIdle(maxAge time.Duration) int

SweepIdle removes sessions whose LastAccess is older than maxAge. Returns the number of sessions removed.

func (*MemoryStore) Touch added in v0.0.3

func (s *MemoryStore) Touch(sessionID string) bool

Touch updates the LastAccess timestamp for an existing session. Returns false if the session does not exist.

type PostgresStore added in v0.0.4

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

PostgresStore implements session.Store against the blockyard_sessions table, making Postgres the source of truth for sticky sessions (see #286, parent #262).

expires_at is populated from idleTTL on every Set/Touch. A background sweep (RunExpiry) deletes rows whose expires_at has passed. This replaces Redis-native TTL expiry.

func NewPostgresStore added in v0.0.4

func NewPostgresStore(db *sqlx.DB, idleTTL time.Duration) *PostgresStore

NewPostgresStore returns a store backed by the blockyard_sessions table. idleTTL drives the expires_at column; 0 means "never expire" and is written as a far-future timestamp so the sweep column keeps a sensible default without needing NULL handling.

func (*PostgresStore) CountForWorker added in v0.0.4

func (s *PostgresStore) CountForWorker(workerID string) int

func (*PostgresStore) CountForWorkers added in v0.0.4

func (s *PostgresStore) CountForWorkers(workerIDs []string) int

func (*PostgresStore) Delete added in v0.0.4

func (s *PostgresStore) Delete(sessionID string)

func (*PostgresStore) DeleteByWorker added in v0.0.4

func (s *PostgresStore) DeleteByWorker(workerID string) int

func (*PostgresStore) EntriesForWorker added in v0.0.4

func (s *PostgresStore) EntriesForWorker(workerID string) map[string]Entry

func (*PostgresStore) Get added in v0.0.4

func (s *PostgresStore) Get(sessionID string) (Entry, bool)

func (*PostgresStore) RerouteWorker added in v0.0.4

func (s *PostgresStore) RerouteWorker(oldWorkerID, newWorkerID string) int

func (*PostgresStore) RunExpiry added in v0.0.4

func (s *PostgresStore) RunExpiry(ctx context.Context, interval time.Duration)

RunExpiry deletes rows whose expires_at has passed, every interval. Blocks until ctx is cancelled. Caller runs it in a goroutine.

This replaces Redis-native TTL expiry: without it, sessions that are created and then never touched again (e.g. a user closes their tab mid-handshake) would live forever. SweepIdle is not a substitute — that runs only when the operator configures session_idle_ttl.

func (*PostgresStore) Set added in v0.0.4

func (s *PostgresStore) Set(sessionID string, entry Entry)

func (*PostgresStore) SweepIdle added in v0.0.4

func (s *PostgresStore) SweepIdle(maxAge time.Duration) int

SweepIdle deletes sessions whose last_access is older than maxAge. Matches MemoryStore semantics — callers drive idle sweeps via the autoscaler. Natural expiry (expires_at) is handled separately by RunExpiry so the two loops can run at different cadences.

func (*PostgresStore) Touch added in v0.0.4

func (s *PostgresStore) Touch(sessionID string) bool

type RedisStore added in v0.0.3

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

RedisStore implements session.Store using Redis hashes.

Key schema:

{prefix}session:{sessionID}  ->  hash {worker_id, user_sub, last_access}

Each session key has a TTL equal to idleTTL. Touch refreshes it. SweepIdle is a no-op — Redis TTL expiry handles idle cleanup.

func NewRedisStore added in v0.0.3

func NewRedisStore(client *redisstate.Client, idleTTL time.Duration) *RedisStore

func (*RedisStore) CountForWorker added in v0.0.3

func (s *RedisStore) CountForWorker(workerID string) int

func (*RedisStore) CountForWorkers added in v0.0.3

func (s *RedisStore) CountForWorkers(workerIDs []string) int

func (*RedisStore) Delete added in v0.0.3

func (s *RedisStore) Delete(sessionID string)

func (*RedisStore) DeleteByWorker added in v0.0.3

func (s *RedisStore) DeleteByWorker(workerID string) int

func (*RedisStore) EntriesForWorker added in v0.0.3

func (s *RedisStore) EntriesForWorker(workerID string) map[string]Entry

func (*RedisStore) Get added in v0.0.3

func (s *RedisStore) Get(sessionID string) (Entry, bool)

func (*RedisStore) RerouteWorker added in v0.0.3

func (s *RedisStore) RerouteWorker(oldWorkerID, newWorkerID string) int

func (*RedisStore) Set added in v0.0.3

func (s *RedisStore) Set(sessionID string, entry Entry)

func (*RedisStore) SweepIdle added in v0.0.3

func (s *RedisStore) SweepIdle(_ time.Duration) int

SweepIdle is a no-op for Redis — TTL-based expiry handles idle cleanup.

func (*RedisStore) Touch added in v0.0.3

func (s *RedisStore) Touch(sessionID string) bool

type Store

type Store interface {
	Get(sessionID string) (Entry, bool)
	Set(sessionID string, entry Entry)
	Touch(sessionID string) bool
	Delete(sessionID string)
	DeleteByWorker(workerID string) int
	CountForWorker(workerID string) int
	CountForWorkers(workerIDs []string) int
	RerouteWorker(oldWorkerID, newWorkerID string) int
	EntriesForWorker(workerID string) map[string]Entry
	SweepIdle(maxAge time.Duration) int
}

Store defines the contract for session state storage. MemoryStore is the in-process implementation; Redis implements the same interface for shared state during rolling updates.

Jump to

Keyboard shortcuts

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