Documentation ¶
Overview ¶
Package gopgsession provides a distributed session management library using PostgreSQL.
It implements an eventually consistent memory caching strategy on each node, offering a hybrid solution that leverages the benefits of both cookie-based and server-side session management. This package is designed for high-performance, scalable applications that require robust session handling across multiple nodes.
Index ¶
- Constants
- Variables
- type Config
- type DistributedLock
- type DistributedLockConfig
- type GetSessionOptions
- type HMACSHA256SignerPool
- func (s *HMACSHA256SignerPool) Sign(message []byte) ([]byte, error)
- func (s *HMACSHA256SignerPool) SignAndEncode(message string) (string, error)
- func (s *HMACSHA256SignerPool) Verify(message, signature []byte) bool
- func (s *HMACSHA256SignerPool) VerifyAndDecode(signedMessage string) (bool, string, error)
- type LockInfo
- type Session
- func (s *Session) DeleteAttribute(key string)
- func (s *Session) GetAttribute(key string) (SessionAttributeValue, bool)
- func (s *Session) GetAttributeAndRetainUnmarshaled(key string, v interface{}) (SessionAttributeValue, error)
- func (s *Session) GetAttributes() map[string]SessionAttributeValue
- func (s *Session) IsFromCache() bool
- func (s *Session) UpdateAttribute(key string, value interface{}, expiresAt *time.Time) error
- type SessionAttributeRecord
- type SessionAttributeValue
- type SessionManager
- func (sm *SessionManager) CreateSession(ctx context.Context, userID uuid.UUID, ...) (*Session, error)
- func (sm *SessionManager) DeleteAllSessions(ctx context.Context) error
- func (sm *SessionManager) DeleteAllUserSessions(ctx context.Context, userID uuid.UUID) error
- func (sm *SessionManager) DeleteSession(ctx context.Context, sessionID uuid.UUID) error
- func (sm *SessionManager) EncodeSessionIDAndVersion(sessionID uuid.UUID, version int) string
- func (sm *SessionManager) GetSession(ctx context.Context, sessionID uuid.UUID, options ...SessionOption) (*Session, error)
- func (sm *SessionManager) GetSessionWithVersion(ctx context.Context, sessionID uuid.UUID, version int, ...) (*Session, error)
- func (sm *SessionManager) NewDistributedLock(sessionID uuid.UUID, resource string, config *DistributedLockConfig) *DistributedLock
- func (sm *SessionManager) ParseSessionIDAndVersion(encodedData string) (uuid.UUID, int, error)
- func (sm *SessionManager) RemoveAllUserCachedSessionsFromAllNodes(userID uuid.UUID) error
- func (sm *SessionManager) Shutdown(ctx context.Context) error
- func (sm *SessionManager) UpdateSession(ctx context.Context, session *Session, options ...UpdateSessionOption) (*Session, error)
- type SessionOption
- type UpdateSessionOption
- type UpdateSessionOptions
Constants ¶
const ( NotificationTypeSessionsRemovalFromCache = "sessions_removal_from_cache" NotificationTypeUserSessionsRemovalFromCache = "user_sessions_removal_from_cache" )
Variables ¶
var ( // ErrLockAlreadyHeld is returned when attempting to acquire a lock that is already held by another node. ErrLockAlreadyHeld = errors.New("lock is already held by another node") // ErrLockNotHeld is returned when attempting to perform an operation on a lock that is not held by the current node. ErrLockNotHeld = errors.New("lock is not held by this node") // ErrLockExpired is returned when attempting to perform an operation on a lock that has expired. ErrLockExpired = errors.New("lock has expired") )
var DefaultDistributedLockConfig = DistributedLockConfig{ MaxRetries: 2, RetryDelay: 1 * time.Millisecond, HeartbeatInterval: 10 * time.Second, LeaseTime: 60 * time.Second, }
DefaultDistributedLockConfig provides default configuration values for DistributedLock.
var ErrAttributeNotFound = errors.New("attribute not found")
var ErrSessionVersionIsOutdated = errors.New("session version is outdated")
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct { // MaxSessions is the maximum number of concurrent sessions allowed per user. // When this limit is reached, the oldest session will be removed. MaxSessions int `json:"maxSessions"` // MaxAttributeLength is the maximum length (in bytes) allowed for a single session attribute value. MaxAttributeLength int `json:"maxAttributeLength"` // SessionExpiration is the duration after which a session expires if not accessed. SessionExpiration time.Duration `json:"sessionExpiration"` // InactivityDuration is the duration of inactivity after which a session is considered expired. InactivityDuration time.Duration `json:"inactivityDuration"` // CleanupInterval is the time interval between cleanup operations for expired sessions. CleanupInterval time.Duration `json:"cleanupInterval"` // CacheSize is the maximum number of sessions to keep in the in-memory cache. CacheSize int `json:"cacheSize"` // TablePrefix is the prefix to be used for all database tables created by the SessionManager. // This allows multiple SessionManager instances to coexist in the same database. TablePrefix string `json:"tablePrefix"` // SchemaName is the name of the PostgreSQL schema to use for session tables. // If empty, the default schema (usually "public") will be used. SchemaName string `json:"schemaName"` // CreateSchemaIfMissing, if true, will create the specified schema if it doesn't exist. CreateSchemaIfMissing bool `json:"createSchemaIfMissing"` // LastAccessUpdateInterval is the time interval between batch updates of session last access times. LastAccessUpdateInterval time.Duration `json:"lastAccessUpdateInterval"` // LastAccessUpdateBatchSize is the maximum number of sessions to update in a single batch operation. LastAccessUpdateBatchSize int `json:"lastAccessUpdateBatchSize"` // NotifyOnUpdates determines whether to send notifications on session updates. // This is a noisier option (true by default) but safer if you do not use additional cookies to note the last version. // For dozens of nodes, you may want to turn it off. NotifyOnUpdates bool // NotifyOnFailedUpdates sends a removal notification when, for example, a version check fails. FALSE by default. NotifyOnFailedUpdates bool // CustomPGLN is an optional custom PGLN instance. If not supplied, a new one will be created with defaults. CustomPGLN *pgln.PGListenNotify `json:"-"` }
Config holds the configuration options for the SessionManager.
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a Config struct with default values.
type DistributedLock ¶ added in v0.3.0
type DistributedLock struct {
// contains filtered or unexported fields
}
DistributedLock represents a distributed lock implementation.
func (*DistributedLock) ExtendLease ¶ added in v0.3.0
ExtendLease extends the lease time of the lock.
Parameters:
- ctx: The context for the operation.
- extension: The duration by which to extend the lease.
Returns:
- An error if the lease cannot be extended, nil otherwise.
type DistributedLockConfig ¶ added in v0.3.0
type DistributedLockConfig struct { // MaxRetries is the maximum number of attempts to acquire the lock. MaxRetries int // RetryDelay is the duration to wait between lock acquisition attempts. RetryDelay time.Duration // HeartbeatInterval is the duration between heartbeats to maintain the lock. HeartbeatInterval time.Duration // LeaseTime is the duration for which the lock is considered valid. LeaseTime time.Duration }
DistributedLockConfig holds the configuration options for a DistributedLock.
type GetSessionOptions ¶ added in v0.2.1
type HMACSHA256SignerPool ¶ added in v0.2.1
type HMACSHA256SignerPool struct {
// contains filtered or unexported fields
}
HMACSHA256SignerPool represents a limited pool of HMAC-SHA256 signers. It provides thread-safe access to a pool of HMAC signers for efficient signing and verification.
func NewHMACSHA256SignerPool ¶ added in v0.2.1
func NewHMACSHA256SignerPool(secret []byte, maxPoolSize int) *HMACSHA256SignerPool
NewHMACSHA256SignerPool initializes a new limited pool of HMAC-SHA256 signers.
Parameters:
- secret: A byte slice containing the secret key used for HMAC operations.
- maxPoolSize: An integer specifying the maximum number of HMAC signers to keep in the pool.
Returns:
- A pointer to a new HMACSHA256SignerPool instance.
func (*HMACSHA256SignerPool) Sign ¶ added in v0.2.1
func (s *HMACSHA256SignerPool) Sign(message []byte) ([]byte, error)
Sign signs a message using a pooled HMAC.
Parameters:
- message: A byte slice containing the message to be signed.
Returns:
- A byte slice containing the HMAC signature.
- An error if the signing process fails.
func (*HMACSHA256SignerPool) SignAndEncode ¶ added in v0.3.3
func (s *HMACSHA256SignerPool) SignAndEncode(message string) (string, error)
SignAndEncode signs a message and encodes it with the signature.
Parameters:
- message: A string containing the message to be signed.
Returns:
- A string containing the base64-encoded message and HMAC signature, separated by a delimiter.
- An error if the signing process fails.
func (*HMACSHA256SignerPool) Verify ¶ added in v0.2.1
func (s *HMACSHA256SignerPool) Verify(message, signature []byte) bool
Verify verifies a signed message using a pooled HMAC.
Parameters:
- message: A byte slice containing the original message that was signed.
- signature: A byte slice containing the HMAC signature to verify.
Returns:
- A boolean indicating whether the signature is valid (true) or not (false).
func (*HMACSHA256SignerPool) VerifyAndDecode ¶ added in v0.3.3
func (s *HMACSHA256SignerPool) VerifyAndDecode(signedMessage string) (bool, string, error)
VerifyAndDecode verifies a signed and encoded message and returns the original message.
Parameters:
- signedMessage: A string containing the base64-encoded message and HMAC signature.
Returns:
- A boolean indicating whether the signature is valid (true) or not (false).
- A string containing the original message.
- An error if the verification process fails.
type LockInfo ¶ added in v0.3.0
type LockInfo struct { NodeID uuid.UUID Resource string ExpiresAt time.Time LastHeartbeat time.Time }
LockInfo holds information about a lock.
type Session ¶
type Session struct { ID uuid.UUID `db:"id"` UserID uuid.UUID `db:"user_id"` // These are not updated in the cache often, only the table is the source of truth. LastAccessed time.Time `db:"last_accessed"` ExpiresAt time.Time `db:"expires_at"` UpdatedAt time.Time `db:"updated_at"` Version int `db:"version"` // contains filtered or unexported fields }
func (*Session) DeleteAttribute ¶ added in v0.2.1
DeleteAttribute removes an attribute from the session.
Parameters:
- key: The key of the attribute to delete.
func (*Session) GetAttribute ¶
func (s *Session) GetAttribute(key string) (SessionAttributeValue, bool)
GetAttribute retrieves a specific attribute from the session.
Parameters:
- key: The key of the attribute to retrieve.
Returns:
- The SessionAttributeValue for the given key and a boolean indicating whether the attribute was found.
func (*Session) GetAttributeAndRetainUnmarshaled ¶ added in v0.2.6
func (s *Session) GetAttributeAndRetainUnmarshaled(key string, v interface{}) (SessionAttributeValue, error)
GetAttributeAndRetainUnmarshaled retrieves a specific attribute, unmarshals it if necessary, and retains the unmarshaled value in memory for future use. This method is optimized to prevent repeated unmarshaling of the same attribute as long as the session remains in memory.
It's particularly beneficial for attributes that are frequently accessed and expensive to unmarshal. By retaining the unmarshaled value, subsequent calls to this method for the same attribute will return the cached unmarshaled value without the need for repeated unmarshaling operations.
The method also ensures thread-safety when updating the shared cache, only doing so if the cached value hasn't been modified by another goroutine.
Parameters:
- key: The key of the attribute to retrieve and unmarshal.
- v: A pointer to the struct where the unmarshaled value will be stored.
Returns:
- A copy of the SessionAttributeValue (which may be newly unmarshaled or previously cached) and an error if any occurred during the retrieval or unmarshaling process.
- If an attribute is not found it returns ErrAttributeNotFound
Usage:
var myStruct MyStructType attr, err := session.GetAttributeAndRetainUnmarshaled("myKey", &myStruct) if err != nil { // Handle error } // Use myStruct and attr as needed
func (*Session) GetAttributes ¶
func (s *Session) GetAttributes() map[string]SessionAttributeValue
GetAttributes returns all attributes of the session.
Returns:
- A map of all session attributes.
func (*Session) IsFromCache ¶ added in v0.2.7
IsFromCache returns true if the session was loaded from the cache, and false if it was loaded from the database table.
func (*Session) UpdateAttribute ¶
UpdateAttribute sets or updates an attribute for the session.
Parameters:
- key: The key of the attribute to update.
- value: The value to set for the attribute. This will be converted to a string.
- expiresAt: An optional pointer to a time.Time value indicating when the attribute should expire. If nil, the attribute will not have an expiration time.
The method will return an error if:
- The value cannot be converted to a string.
- The resulting string exceeds the maximum allowed length for an attribute value.
Example usage:
// Set an attribute without expiration err := session.UpdateAttribute("theme", "dark", nil) // Set an attribute with expiration expiresAt := time.Now().Add(24 * time.Hour) err := session.UpdateAttribute("temporary_flag", true, &expiresAt)
type SessionAttributeRecord ¶ added in v0.2.1
type SessionAttributeValue ¶ added in v0.2.1
type SessionManager ¶
type SessionManager struct { Config *Config // contains filtered or unexported fields }
SessionManager manages sessions in a PostgreSQL database with caching capabilities.
func NewSessionManager ¶
NewSessionManager creates a new SessionManager with the given configuration and connection string.
Parameters:
- ctx: A long-running context that should hold up until shutdown
- cfg: A pointer to a Config struct containing the configuration options for the SessionManager.
- db: An pgx (v5) stdlib
Returns:
- A pointer to the created SessionManager and an error if any occurred during initialization.
func (*SessionManager) CreateSession ¶
func (sm *SessionManager) CreateSession(ctx context.Context, userID uuid.UUID, attributes map[string]SessionAttributeValue) (*Session, error)
CreateSession creates a new session for the given user with the provided attributes.
Parameters:
- ctx: The context for the operation.
- userID: The UUID of the user for whom the session is being created.
- attributes: A map of initial attributes for the session.
Returns:
- A pointer to the created Session and an error if any occurred during creation.
func (*SessionManager) DeleteAllSessions ¶ added in v0.2.1
func (sm *SessionManager) DeleteAllSessions(ctx context.Context) error
DeleteAllSessions deletes all sessions from the database and cache.
Parameters:
- ctx: The context for the operation.
Returns:
- An error if any occurred during the deletion.
func (*SessionManager) DeleteAllUserSessions ¶
DeleteAllUserSessions deletes all sessions for a given user.
Parameters:
- ctx: The context for the operation.
- userID: The UUID of the user whose sessions should be deleted.
Returns:
- An error if any occurred during the deletion.
func (*SessionManager) DeleteSession ¶
DeleteSession deletes a session by its ID.
Parameters:
- ctx: The context for the operation.
- sessionID: The UUID of the session to delete.
Returns:
- An error if any occurred during the deletion.
func (*SessionManager) EncodeSessionIDAndVersion ¶ added in v0.2.1
func (sm *SessionManager) EncodeSessionIDAndVersion(sessionID uuid.UUID, version int) string
EncodeSessionIDAndVersion encodes a session ID and version into a single string.
Parameters:
- sessionID: The UUID of the session.
- version: The version of the session.
Returns:
- A string containing the encoded session ID and version.
func (*SessionManager) GetSession ¶
func (sm *SessionManager) GetSession(ctx context.Context, sessionID uuid.UUID, options ...SessionOption) (*Session, error)
GetSession retrieves a session by its ID with optional parameters.
Parameters:
- ctx: The context for the operation.
- sessionID: The UUID of the session to retrieve.
- options: Variadic SessionOption parameters to customize the retrieval behavior.
Returns:
- A pointer to the retrieved Session and an error if any occurred during retrieval.
func (*SessionManager) GetSessionWithVersion ¶ added in v0.2.1
func (sm *SessionManager) GetSessionWithVersion(ctx context.Context, sessionID uuid.UUID, version int, options ...SessionOption) (*Session, error)
GetSessionWithVersion retrieves a session by its ID and version with optional parameters.
Parameters:
- ctx: The context for the operation.
- sessionID: The UUID of the session to retrieve.
- version: The version of the session to retrieve.
- options: Variadic SessionOption parameters to customize the retrieval behavior.
Returns:
- A pointer to the retrieved Session and an error if any occurred during retrieval.
func (*SessionManager) NewDistributedLock ¶ added in v0.3.0
func (sm *SessionManager) NewDistributedLock(sessionID uuid.UUID, resource string, config *DistributedLockConfig) *DistributedLock
NewDistributedLock creates a new DistributedLock instance.
Parameters:
- sessionID: The UUID of the session associated with this lock.
- resource: The name of the resource being locked.
- config: Optional configuration for the lock. If nil, default configuration is used.
Returns:
- A pointer to the newly created DistributedLock.
func (*SessionManager) ParseSessionIDAndVersion ¶ added in v0.2.1
ParseSessionIDAndVersion parses an encoded session ID and version string.
Parameters:
- encodedData: The string containing the encoded session ID and version.
Returns:
- The parsed session UUID, version, and an error if any occurred during parsing.
func (*SessionManager) RemoveAllUserCachedSessionsFromAllNodes ¶ added in v0.2.1
func (sm *SessionManager) RemoveAllUserCachedSessionsFromAllNodes(userID uuid.UUID) error
RemoveAllUserCachedSessionsFromAllNodes removes all cached sessions for a given user from all nodes.
Parameters:
- userID: The UUID of the user whose cached sessions should be removed.
Returns:
- An error if any occurred during the removal process.
func (*SessionManager) Shutdown ¶
func (sm *SessionManager) Shutdown(ctx context.Context) error
Shutdown gracefully shuts down the SessionManager.
Parameters:
- ctx: The context for the shutdown operation.
Returns:
- An error if any occurred during the shutdown process.
func (*SessionManager) UpdateSession ¶
func (sm *SessionManager) UpdateSession(ctx context.Context, session *Session, options ...UpdateSessionOption) (*Session, error)
UpdateSession updates the session in the database with any changes made to its attributes.
Parameters:
- ctx: The context for the operation.
- session: A pointer to the Session to be updated.
- options: Variadic UpdateSessionOption parameters to customize the update behavior.
Returns:
- A pointer to the updated Session and an error if any occurred during the update.
type SessionOption ¶ added in v0.2.7
type SessionOption func(*GetSessionOptions)
SessionOption is a function type that modifies GetSessionOptions
func WithDoNotUpdateSessionLastAccess ¶ added in v0.2.7
func WithDoNotUpdateSessionLastAccess() SessionOption
WithDoNotUpdateSessionLastAccess sets the DoNotUpdateSessionLastAccess option
func WithForceRefresh ¶ added in v0.2.7
func WithForceRefresh() SessionOption
WithForceRefresh sets the ForceRefresh option
type UpdateSessionOption ¶ added in v0.2.7
type UpdateSessionOption func(*UpdateSessionOptions)
UpdateSessionOption is a function type that modifies UpdateSessionOptions
func WithCheckAttributeVersion ¶ added in v0.3.0
func WithCheckAttributeVersion() UpdateSessionOption
WithCheckAttributeVersion sets the CheckAttributeVersion option
func WithCheckVersion ¶ added in v0.2.7
func WithCheckVersion() UpdateSessionOption
WithCheckVersion sets the CheckVersion option to true
func WithDoNotNotify ¶ added in v0.2.7
func WithDoNotNotify() UpdateSessionOption
WithDoNotNotify sets the DoNotNotify option
type UpdateSessionOptions ¶ added in v0.2.7
UpdateSessionOptions holds the options for updating a session