Class: Llmemory::ShortTerm::Stores::RedisStore

Inherits:
Base
  • Object
show all
Includes:
Crypto::FieldHelpers
Defined in:
lib/llmemory/short_term/stores/redis_store.rb

Constant Summary collapse

KEY_PREFIX =
"llmemory:checkpoint"
MAX_CAS_RETRIES =
5

Instance Method Summary collapse

Constructor Details

#initialize(redis_url: nil, cipher: nil) ⇒ RedisStore

Returns a new instance of RedisStore.



17
18
19
20
21
22
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 17

def initialize(redis_url: nil, cipher: nil)
  @redis_url = redis_url || Llmemory.configuration.redis_url
  @redis = nil
  @cipher = cipher || Llmemory.build_cipher
  @conn_mutex = Mutex.new
end

Instance Method Details

#delete(user_id, session_id) ⇒ Object



44
45
46
47
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 44

def delete(user_id, session_id)
  with_redis { |client| client.del(key_for(user_id, session_id)) }
  true
end

#list_sessions(user_id:) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 86

def list_sessions(user_id:)
  encoded_user = KeyCodec.encode(user_id)
  scan_keys("#{KEY_PREFIX}:#{encoded_user}:*").filter_map do |k|
    parts = k.split(":", 4)
    next unless parts.size >= 4

    KeyCodec.decode(parts[3])
  end
end

#list_usersObject



77
78
79
80
81
82
83
84
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 77

def list_users
  scan_keys("#{KEY_PREFIX}:*").filter_map do |k|
    parts = k.split(":", 4)
    next unless parts.size >= 4

    KeyCodec.decode(parts[2])
  end.uniq
end

#load(user_id, session_id) ⇒ Object



37
38
39
40
41
42
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 37

def load(user_id, session_id)
  with_redis do |client|
    data = client.get(key_for(user_id, session_id))
    data ? deserialize(data) : nil
  end
end

#save(user_id, session_id, state) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 24

def save(user_id, session_id, state)
  with_redis do |client|
    key = key_for(user_id, session_id)
    payload = serialize(state)
    if pseudo_session?(session_id)
      client.set(key, payload)
    else
      client.set(key, payload, ex: session_ttl_seconds)
    end
  end
  true
end

#update(user_id, session_id, &block) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/llmemory/short_term/stores/redis_store.rb', line 49

def update(user_id, session_id, &block)
  key = key_for(user_id, session_id)
  retries = 0

  loop do
    result = with_redis do |client|
      client.watch(key) do
        raw = client.get(key)
        current = raw ? deserialize(raw) : nil
        new_state = yield(current)
        next new_state if new_state.nil?

        payload = serialize(new_state)
        if pseudo_session?(session_id)
          client.multi { |multi| multi.set(key, payload) }
        else
          client.multi { |multi| multi.set(key, payload, ex: session_ttl_seconds) }
        end
        new_state
      end
    end
    return result unless result.nil?

    retries += 1
    raise Llmemory::StoreError, "Redis CAS update failed after #{MAX_CAS_RETRIES} retries" if retries >= MAX_CAS_RETRIES
  end
end