session.go
Overview
The session.go file within the database package implements an in-memory representation of a session for the database-backed session service. It provides a concrete local session implementation that manages session metadata, event history, and session-scoped mutable state with concurrent access control. This file encapsulates the core data structures and logic to maintain a session's state and events in memory, facilitating transactional updates and querying within the database session service context.
Although the file is part of the database session backend, it manages session state and events in memory with synchronization primitives. It also handles filtering out temporary state keys from events and updating session state based on incoming event state deltas. This local session implementation conforms to interfaces defined in the Session Management topic, serving as an internal representation of sessions managed by the database-backed session service.
Types and Structures
localSession
A struct representing a single user session in memory, with fields and methods managing session data and concurrency.
Fields:
appName string: The application name to which the session belongs.userID string: Identifier for the user owning the session.sessionID string: Unique identifier for this session.mu sync.RWMutex: Read-write mutex guarding access to mutable fields.events []*session.Event: Ordered list of events recorded in the session.state map[string]any: Mutable key-value state scoped to the session.updatedAt time.Time: Timestamp of the last session update.
Implements:
session.Session interface, providing session metadata, state, events, and update time.
Methods on localSession
ID() string
Returns the session's unique identifier (sessionID).
AppName() string
Returns the name of the application associated with the session.
UserID() string
Returns the user ID associated with the session.
State() session.State
Returns a session.State interface wrapping the session's state map guarded by the session mutex.
Usage: Enables retrieval and modification of session state with concurrency safety.
Returns: A
statestruct pointer implementing session.State.
Events() session.Events
Returns a session.Events interface wrapping the internal slice of session events.
Usage: Provides read-only access to the sequence of recorded events.
Returns: An
eventstype that implements session.Events.
LastUpdateTime() time.Time
Returns the timestamp of the last update to the session.
Implementation: Uses a read lock to safely retrieve
updatedAt.
appendEvent(event *session.Event) error
Appends a new event to the session's event history and updates the session state accordingly.
Parameters:
event *session.Event: The event to append.
Returns: An error if state update fails; otherwise
nil.Behavior:
Ignores partial events (
event.Partial == true) which are not persisted.Filters out temporary state keys from the event's state delta using trimTempDeltaState.
Calls updateSessionState to apply the event's state delta to session state.
Adds the event to the internal events slice.
Updates the
updatedAttimestamp to the event’s timestamp.
Concurrency: Uses a write lock on the session mutex (
mu).
Supporting Types and Methods
events
A slice type alias for []*session.Event implementing the session.Events interface.
Methods:
All() iter.Seq[*session.Event]: Returns a sequence iterator over all events.Len() int: Returns the number of events.At(i int) *session.Event: Returns the event at indexiornilif out of range.
state
Wraps a session state map and mutex, implementing the session.State interface.
Fields:
mu *sync.RWMutex: Pointer to the mutex guarding the underlying state map.state map[string]any: The key-value store representing session state.
Methods:
Get(key string) (any, error): Retrieves the value for the given state key.Returns session.ErrStateKeyNotExist if the key is not found.
Uses a read lock for concurrency safety.
All() iter.Seq2[string, any]: Returns an iterator over all key-value pairs.Uses read locking with careful lock/unlock around yielding each pair to avoid holding the lock during the callback.
Set(key string, value any) error: Sets or updates a key-value pair in the session state.Uses a write lock for concurrency safety.
Always returns
nil.
Key Functions
trimTempDeltaState(event *session.Event) *session.Event
Filters out temporary state delta keys from an event’s state delta map.
Purpose: Prevents ephemeral state keys (those prefixed with session.KeyPrefixTemp) from being persisted to session state.
Behavior:
Creates a new filtered map excluding keys starting with the
temp:prefix.Replaces the event’s Actions.StateDelta with the filtered map.
Returns: The modified event.
updateSessionState(sess *localSession, event *session.Event) error
Applies the state delta from an event to the session’s state map.
Parameters:
sess *localSession: The session to update.event *session.Event: The event containing the state delta.
Returns: An error if any issue occurs (currently always returns
nil).Behavior:
Initializes session state map if nil.
Iterates over state delta entries, skipping keys with the temporary prefix.
Updates the session’s state map with the filtered keys and values.
Implementation Details and Concurrency
The
localSessionuses async.RWMutexto guard all mutable fields (events,state,updatedAt), enabling safe concurrent read and write access.State retrieval and iteration methods use read locks, while state mutation and event appending use write locks.
Filtering of temporary state keys is performed before state application to ensure ephemeral data is not persisted.
The event list is stored as a slice and appended in order as events arrive.
The session state map holds arbitrary key-value pairs (
map[string]any) representing session-specific mutable state.
Interaction with Other Components
This file provides the in-memory session model used internally by the Database Session Service to represent sessions during transactional updates.
Implements interfaces from the
sessionpackage (session.Session, session.Events, session.State), which are part of the broader Session Management topic.The
localSessioninstance is typically created and managed by the database service to represent session data fetched from or persisted to the underlying SQL database.The event appending and state update logic here complements the transactional operations performed by the database service, allowing atomic and consistent session state mutations.
The trimTempDeltaState and updateSessionState functions ensure that temporary keys are filtered and state is updated consistently, aligning with the overall system design for state scoping and persistence.
Usage Example
// Assume sess is an instance of *localSession and event is a *session.Event
// Append a new event to the session
err := sess.appendEvent(event)
if err != nil {
// handle error
}
// Retrieve session state
state := sess.State()
val, err := state.Get("key")
if err == nil {
fmt.Println("Value:", val)
}
// Iterate all events
for it := sess.Events().All(); ; {
var e *session.Event
if !it(func(ev *session.Event) bool {
e = ev
return false // stop after retrieving one for example
}) {
break
}
fmt.Println(e)
}
Mermaid Class Diagram
classDiagram
class localSession {
-appName: string
-userID: string
-sessionID: string
-mu: sync.RWMutex
-events: []*session.Event
-state: map[string]any
-updatedAt: time.Time
+ID()
+AppName()
+UserID()
+State()
+Events()
+LastUpdateTime()
+appendEvent(event *session.Event) error
}
class events {
-events: []*session.Event
+All()
+Len()
+At(i int)
}
class state {
-mu: *sync.RWMutex
-state: map[string]any
+Get(key string) (any, error)
+All()
+Set(key string, value any) error
}
localSession --> state : provides
localSession --> events : provides
This documentation covers the structure, behavior, and integration of the session.go file’s contents within the database session service subsystem of the Session Management topic. It focuses on the in-memory session representation, event handling, and state management implemented here.