Class: LittleGhost::SessionStores::Memory

Inherits:
LittleGhost::SessionStore show all
Defined in:
lib/little_ghost/session_stores/memory.rb

Overview

Memory keeps conversations available for the life of one Ruby process. It is the default store and needs no application setup.

Data disappears when the process exits. Supplying an actor ID binds the session key to that actor; a later mismatch raises an error.

Instance Method Summary collapse

Methods inherited from LittleGhost::SessionStore

#project_conversation, #synchronize, #with_operation_context

Constructor Details

#initializeMemory

Starts with no saved conversations.



13
14
15
16
17
# File 'lib/little_ghost/session_stores/memory.rb', line 13

def initialize
  super
  @records = {}
  @records_mutex = Mutex.new
end

Instance Method Details

#append(id, messages:, state:, metadata:, expected_count:, actor_id: nil) ⇒ Object

Appends sanitized messages when expected_count still matches the stored conversation, then returns the updated snapshot.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/little_ghost/session_stores/memory.rb', line 33

def append(id, messages:, state:, metadata:, expected_count:, actor_id: nil)
  messages = persistable_messages(messages)
  @records_mutex.synchronize do
    key = id.to_s
    record = @records[key]
    validate_actor!(record, actor_id)
    current = record&.fetch(:snapshot) || empty_snapshot
    unless current.fetch(:messages).length == expected_count
      raise ProtocolError, "Session changed while it was being updated"
    end

    @records[key] = {
      actor_id: actor_id&.to_s,
      snapshot: {
        messages: [*current.fetch(:messages), *messages].freeze,
        state:,
        metadata:
      }.freeze
    }.freeze
    @records[key].fetch(:snapshot)
  end
end

#load(id, actor_id: nil) ⇒ Object

Loads the snapshot for id, returning nil before the first checkpoint. A supplied actor_id claims a new ID and must match on later access.



21
22
23
24
25
26
27
28
29
# File 'lib/little_ghost/session_stores/memory.rb', line 21

def load(id, actor_id: nil)
  @records_mutex.synchronize do
    key = id.to_s
    record = @records[key]
    validate_actor!(record, actor_id)
    @records[key] = {actor_id: actor_id.to_s, snapshot: nil} if !record && actor_id
    record&.fetch(:snapshot)
  end
end

#replace(id, messages:, state:, metadata:, actor_id: nil) ⇒ Object

Replaces the complete in-memory snapshot with sanitized messages.



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/little_ghost/session_stores/memory.rb', line 57

def replace(id, messages:, state:, metadata:, actor_id: nil)
  messages = persistable_messages(messages)
  @records_mutex.synchronize do
    key = id.to_s
    validate_actor!(@records[key], actor_id)
    @records[key] = {
      actor_id: actor_id&.to_s,
      snapshot: {messages:, state:, metadata:}.freeze
    }.freeze
    @records[key].fetch(:snapshot)
  end
end