Class: Phronomy::Memory::Storage::InMemory

Inherits:
Base
  • Object
show all
Defined in:
lib/phronomy/memory/storage/in_memory.rb

Overview

In-process storage for conversation messages backed by per-thread-id Actor instances from ThreadActorRegistry. Messages are lost when the process exits.

Examples:

storage = Phronomy::Memory::Storage::InMemory.new
manager = Phronomy::Memory::ConversationManager.new(storage: storage, ...)

Defined Under Namespace

Classes: ThreadData

Constant Summary collapse

THREAD_DATA_KEY =

Thread-local key for per-thread-id storage data (namespaced by store instance object_id to support multiple independent InMemory stores).

:phronomy_storage_in_memory_data

Instance Method Summary collapse

Methods inherited from Base

#purge

Constructor Details

#initializeInMemory

Returns a new instance of InMemory.



18
19
# File 'lib/phronomy/memory/storage/in_memory.rb', line 18

def initialize
end

Instance Method Details

#append_raw(thread_id:, messages:, starting_seq:, recorded_at: nil) ⇒ Object

Parameters:

  • thread_id (String)
  • messages (Array)
  • starting_seq (Integer)
  • recorded_at (Time, nil) (defaults to: nil)

    timestamp for test overrides; defaults to +Time.now+



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/phronomy/memory/storage/in_memory.rb', line 53

def append_raw(thread_id:, messages:, starting_seq:, recorded_at: nil)
  now = recorded_at || Time.now
  Phronomy::ThreadActorRegistry.for(thread_id).call do
    data = thread_data
    messages.each_with_index do |msg, i|
      seq = starting_seq + i
      data.raw_messages << {seq: seq, message: msg, recorded_at: now}
      data.hwm = [data.hwm, seq].max
    end
  end
end

#clear(thread_id:) ⇒ Object

Parameters:

  • thread_id (String)


38
39
40
41
42
43
# File 'lib/phronomy/memory/storage/in_memory.rb', line 38

def clear(thread_id:)
  store_id = object_id
  Phronomy::ThreadActorRegistry.for(thread_id).call do
    (Thread.current[THREAD_DATA_KEY] ||= {}).delete(store_id)
  end
end

#clear_compactions(thread_id:) ⇒ Object

Parameters:

  • thread_id (String)


114
115
116
# File 'lib/phronomy/memory/storage/in_memory.rb', line 114

def clear_compactions(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.compactions.clear }
end

#clear_raw(thread_id:) ⇒ Object

Parameters:

  • thread_id (String)


89
90
91
# File 'lib/phronomy/memory/storage/in_memory.rb', line 89

def clear_raw(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.raw_messages.clear }
end

#load(thread_id:) ⇒ Array

Parameters:

  • thread_id (String)

Returns:

  • (Array)


27
28
29
# File 'lib/phronomy/memory/storage/in_memory.rb', line 27

def load(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { (thread_data.store || []).dup }
end

#load_compactions(thread_id:) ⇒ Array<Hash>

Parameters:

  • thread_id (String)

Returns:

  • (Array<Hash>)


109
110
111
# File 'lib/phronomy/memory/storage/in_memory.rb', line 109

def load_compactions(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.compactions.dup }
end

#load_raw(thread_id:) ⇒ Array<Hash>

Parameters:

  • thread_id (String)

Returns:

  • (Array<Hash>)


84
85
86
# File 'lib/phronomy/memory/storage/in_memory.rb', line 84

def load_raw(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.raw_messages.dup }
end

#next_seq(thread_id:) ⇒ Integer

Parameters:

  • thread_id (String)

Returns:

  • (Integer)


67
68
69
# File 'lib/phronomy/memory/storage/in_memory.rb', line 67

def next_seq(thread_id:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.hwm + 1 }
end

#purge_older_than(thread_id:, older_than:) ⇒ Object

Remove raw messages recorded before +older_than+ for this thread.

Parameters:

  • thread_id (String)
  • older_than (Time)


122
123
124
125
126
# File 'lib/phronomy/memory/storage/in_memory.rb', line 122

def purge_older_than(thread_id:, older_than:)
  Phronomy::ThreadActorRegistry.for(thread_id).call do
    thread_data.raw_messages.reject! { |entry| entry[:recorded_at] && entry[:recorded_at] < older_than }
  end
end

#save(thread_id:, messages:) ⇒ Object

Parameters:

  • thread_id (String)
  • messages (Array)


33
34
35
# File 'lib/phronomy/memory/storage/in_memory.rb', line 33

def save(thread_id:, messages:)
  Phronomy::ThreadActorRegistry.for(thread_id).call { thread_data.store = messages.dup }
end

#save_compaction(thread_id:, start_seq:, end_seq:, summary_text:) ⇒ Object

Parameters:

  • thread_id (String)
  • start_seq (Integer)
  • end_seq (Integer)
  • summary_text (String)


101
102
103
104
105
# File 'lib/phronomy/memory/storage/in_memory.rb', line 101

def save_compaction(thread_id:, start_seq:, end_seq:, summary_text:)
  Phronomy::ThreadActorRegistry.for(thread_id).call do
    thread_data.compactions << {start_seq: start_seq, end_seq: end_seq, summary_text: summary_text}
  end
end

#with_thread_lock(thread_id:, &block) ⇒ Object

Routes +block+ through the per-thread-id Actor, serialising all operations for the same thread. Reentrant calls (the block itself calling storage methods that also route through the Actor) are safe because Actor#call detects the same-thread case and executes inline.

Parameters:

  • thread_id (String)


78
79
80
# File 'lib/phronomy/memory/storage/in_memory.rb', line 78

def with_thread_lock(thread_id:, &block)
  Phronomy::ThreadActorRegistry.for(thread_id).call(&block)
end