lex-agentic-memory 0.1.8 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/lib/legion/extensions/agentic/memory/archaeology/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/archaeology/runners/cognitive_archaeology.rb +6 -0
- data/lib/legion/extensions/agentic/memory/compression/actors/maintenance.rb +22 -0
- data/lib/legion/extensions/agentic/memory/echo/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/echo_chamber/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/echo_chamber/runners/cognitive_echo_chamber.rb +6 -0
- data/lib/legion/extensions/agentic/memory/immune_memory/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/nostalgia/actors/maintenance.rb +22 -0
- data/lib/legion/extensions/agentic/memory/palimpsest/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/reserve/actors/maintenance.rb +22 -0
- data/lib/legion/extensions/agentic/memory/semantic_priming/actors/decay.rb +22 -0
- data/lib/legion/extensions/agentic/memory/semantic_satiation/actors/recovery.rb +22 -0
- data/lib/legion/extensions/agentic/memory/trace/actors/quota.rb +22 -0
- data/lib/legion/extensions/agentic/memory/trace/helpers/hot_tier.rb +98 -0
- data/lib/legion/extensions/agentic/memory/trace/helpers/postgres_store.rb +393 -0
- data/lib/legion/extensions/agentic/memory/trace/runners/consolidation.rb +7 -0
- data/lib/legion/extensions/agentic/memory/trace.rb +22 -1
- data/lib/legion/extensions/agentic/memory/version.rb +1 -1
- data/spec/legion/extensions/agentic/memory/archaeology/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/compression/actors/maintenance_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/echo/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/echo_chamber/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/immune_memory/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/nostalgia/actors/maintenance_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/palimpsest/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/reserve/actors/maintenance_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/semantic_priming/actors/decay_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/semantic_satiation/actors/recovery_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/trace/actors/quota_spec.rb +24 -0
- data/spec/legion/extensions/agentic/memory/trace/helpers/hot_tier_spec.rb +337 -0
- data/spec/legion/extensions/agentic/memory/trace/helpers/postgres_store_spec.rb +464 -0
- metadata +27 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Actors
|
|
6
|
+
class Every # rubocop:disable Lint/EmptyClass
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
$LOADED_FEATURES << 'legion/extensions/actors/every'
|
|
12
|
+
|
|
13
|
+
require 'legion/extensions/agentic/memory/semantic_priming/actors/decay'
|
|
14
|
+
|
|
15
|
+
RSpec.describe Legion::Extensions::Agentic::Memory::SemanticPriming::Actors::Decay do
|
|
16
|
+
subject(:actor) { described_class.new }
|
|
17
|
+
|
|
18
|
+
it { expect(actor.runner_class).to eq(Legion::Extensions::Agentic::Memory::SemanticPriming::Runners::SemanticPriming) }
|
|
19
|
+
it { expect(actor.runner_function).to eq('decay') }
|
|
20
|
+
it { expect(actor.time).to eq(30) }
|
|
21
|
+
it { expect(actor.use_runner?).to be false }
|
|
22
|
+
it { expect(actor.check_subtask?).to be false }
|
|
23
|
+
it { expect(actor.generate_task?).to be false }
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Actors
|
|
6
|
+
class Every # rubocop:disable Lint/EmptyClass
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
$LOADED_FEATURES << 'legion/extensions/actors/every'
|
|
12
|
+
|
|
13
|
+
require 'legion/extensions/agentic/memory/semantic_satiation/actors/recovery'
|
|
14
|
+
|
|
15
|
+
RSpec.describe Legion::Extensions::Agentic::Memory::SemanticSatiation::Actors::Recovery do
|
|
16
|
+
subject(:actor) { described_class.new }
|
|
17
|
+
|
|
18
|
+
it { expect(actor.runner_class).to eq(Legion::Extensions::Agentic::Memory::SemanticSatiation::Runners::SemanticSatiation) }
|
|
19
|
+
it { expect(actor.runner_function).to eq('recover') }
|
|
20
|
+
it { expect(actor.time).to eq(60) }
|
|
21
|
+
it { expect(actor.use_runner?).to be false }
|
|
22
|
+
it { expect(actor.check_subtask?).to be false }
|
|
23
|
+
it { expect(actor.generate_task?).to be false }
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Actors
|
|
6
|
+
class Every # rubocop:disable Lint/EmptyClass
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
$LOADED_FEATURES << 'legion/extensions/actors/every'
|
|
12
|
+
|
|
13
|
+
require 'legion/extensions/agentic/memory/trace/actors/quota'
|
|
14
|
+
|
|
15
|
+
RSpec.describe Legion::Extensions::Agentic::Memory::Trace::Actor::Quota do
|
|
16
|
+
subject(:actor) { described_class.new }
|
|
17
|
+
|
|
18
|
+
it { expect(actor.runner_class).to eq(Legion::Extensions::Agentic::Memory::Trace::Runners::Consolidation) }
|
|
19
|
+
it { expect(actor.runner_function).to eq('enforce_quota') }
|
|
20
|
+
it { expect(actor.time).to eq(300) }
|
|
21
|
+
it { expect(actor.use_runner?).to be false }
|
|
22
|
+
it { expect(actor.check_subtask?).to be false }
|
|
23
|
+
it { expect(actor.generate_task?).to be false }
|
|
24
|
+
end
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
# Legion::Cache::RedisHash lives in legion-cache. The installed gem version may not have it
|
|
6
|
+
# yet, so we define a minimal stub for testing HotTier in isolation.
|
|
7
|
+
unless defined?(Legion::Cache::RedisHash)
|
|
8
|
+
module Legion
|
|
9
|
+
module Cache
|
|
10
|
+
module RedisHash
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def redis_available? = false
|
|
14
|
+
def hset(_key, _hash) = false
|
|
15
|
+
def hgetall(_key) = nil
|
|
16
|
+
def hdel(_key, *_fields) = 0
|
|
17
|
+
def zadd(_key, _score, _member) = false
|
|
18
|
+
def zrangebyscore(_key, _min, _max, **) = []
|
|
19
|
+
def zrem(_key, _member) = false
|
|
20
|
+
def expire(_key, _seconds) = false
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
RSpec.describe Legion::Extensions::Agentic::Memory::Trace::Helpers::HotTier do
|
|
27
|
+
subject(:mod) { described_class }
|
|
28
|
+
|
|
29
|
+
let(:tenant_id) { 'tenant-abc' }
|
|
30
|
+
let(:trace_id) { 'trace-uuid-001' }
|
|
31
|
+
|
|
32
|
+
let(:trace) do
|
|
33
|
+
{
|
|
34
|
+
trace_id: trace_id,
|
|
35
|
+
trace_type: :semantic,
|
|
36
|
+
content_payload: 'ruby is great',
|
|
37
|
+
strength: 0.85,
|
|
38
|
+
peak_strength: 0.95,
|
|
39
|
+
confidence: 0.9,
|
|
40
|
+
partition_id: tenant_id,
|
|
41
|
+
last_reinforced: Time.now
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# --- available? ---
|
|
46
|
+
|
|
47
|
+
describe '.available?' do
|
|
48
|
+
context 'when Legion::Cache::RedisHash is not defined' do
|
|
49
|
+
it 'returns a falsy value gracefully' do
|
|
50
|
+
hide_const('Legion::Cache::RedisHash')
|
|
51
|
+
expect(mod.available?).to be_falsy
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'when Legion::Cache::RedisHash is defined but not connected' do
|
|
56
|
+
before do
|
|
57
|
+
stub_const('Legion::Cache::RedisHash', Module.new)
|
|
58
|
+
allow(Legion::Cache::RedisHash).to receive(:redis_available?).and_return(false)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'returns false' do
|
|
62
|
+
expect(mod.available?).to be false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'when Legion::Cache::RedisHash is defined and connected' do
|
|
67
|
+
before do
|
|
68
|
+
stub_const('Legion::Cache::RedisHash', Module.new)
|
|
69
|
+
allow(Legion::Cache::RedisHash).to receive(:redis_available?).and_return(true)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'returns true' do
|
|
73
|
+
expect(mod.available?).to be true
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'when an exception is raised' do
|
|
78
|
+
before { allow(mod).to receive(:available?).and_call_original }
|
|
79
|
+
|
|
80
|
+
it 'returns false without raising' do
|
|
81
|
+
stub_const('Legion::Cache::RedisHash', Module.new)
|
|
82
|
+
allow(Legion::Cache::RedisHash).to receive(:redis_available?).and_raise(RuntimeError, 'boom')
|
|
83
|
+
expect(mod.available?).to be false
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# --- trace_key ---
|
|
89
|
+
|
|
90
|
+
describe '.trace_key' do
|
|
91
|
+
it 'builds a namespaced key from tenant and trace id' do
|
|
92
|
+
expect(mod.trace_key('tenant-1', 'trace-2')).to eq('legion:trace:tenant-1:trace-2')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'handles nil tenant gracefully' do
|
|
96
|
+
expect(mod.trace_key(nil, 'trace-2')).to eq('legion:trace::trace-2')
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# --- serialize_trace / deserialize_trace round-trip ---
|
|
101
|
+
|
|
102
|
+
describe '.serialize_trace' do
|
|
103
|
+
subject(:serialized) { mod.serialize_trace(trace) }
|
|
104
|
+
|
|
105
|
+
it 'returns a Hash with string keys only' do
|
|
106
|
+
expect(serialized.keys).to all(be_a(String))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'includes all expected fields' do
|
|
110
|
+
expect(serialized.keys).to include(
|
|
111
|
+
'trace_id', 'trace_type', 'content_payload',
|
|
112
|
+
'strength', 'peak_strength', 'confidence',
|
|
113
|
+
'storage_tier', 'partition_id', 'last_reinforced'
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'sets storage_tier to "hot"' do
|
|
118
|
+
expect(serialized['storage_tier']).to eq('hot')
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'converts trace_id to string' do
|
|
122
|
+
expect(serialized['trace_id']).to eq(trace_id)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'converts trace_type to string' do
|
|
126
|
+
expect(serialized['trace_type']).to eq('semantic')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'converts numeric fields to strings' do
|
|
130
|
+
expect(serialized['strength']).to eq('0.85')
|
|
131
|
+
expect(serialized['peak_strength']).to eq('0.95')
|
|
132
|
+
expect(serialized['confidence']).to eq('0.9')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'uses Time.now when last_reinforced is nil' do
|
|
136
|
+
t = mod.serialize_trace(trace.merge(last_reinforced: nil))
|
|
137
|
+
expect(t['last_reinforced']).not_to be_empty
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe '.deserialize_trace' do
|
|
142
|
+
let(:data) do
|
|
143
|
+
{
|
|
144
|
+
'trace_id' => trace_id,
|
|
145
|
+
'trace_type' => 'semantic',
|
|
146
|
+
'content_payload' => 'ruby is great',
|
|
147
|
+
'strength' => '0.85',
|
|
148
|
+
'peak_strength' => '0.95',
|
|
149
|
+
'confidence' => '0.9',
|
|
150
|
+
'storage_tier' => 'hot',
|
|
151
|
+
'partition_id' => tenant_id,
|
|
152
|
+
'last_reinforced' => Time.now.to_s
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
subject(:deserialized) { mod.deserialize_trace(data) }
|
|
157
|
+
|
|
158
|
+
it 'returns a hash with symbol keys' do
|
|
159
|
+
expect(deserialized).to be_a(Hash)
|
|
160
|
+
expect(deserialized.keys).to all(be_a(Symbol))
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'sets trace_id correctly' do
|
|
164
|
+
expect(deserialized[:trace_id]).to eq(trace_id)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it 'converts trace_type back to a symbol' do
|
|
168
|
+
expect(deserialized[:trace_type]).to eq(:semantic)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'converts numeric strings back to floats' do
|
|
172
|
+
expect(deserialized[:strength]).to be_within(0.001).of(0.85)
|
|
173
|
+
expect(deserialized[:peak_strength]).to be_within(0.001).of(0.95)
|
|
174
|
+
expect(deserialized[:confidence]).to be_within(0.001).of(0.9)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'forces storage_tier to :hot' do
|
|
178
|
+
expect(deserialized[:storage_tier]).to eq(:hot)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'preserves partition_id' do
|
|
182
|
+
expect(deserialized[:partition_id]).to eq(tenant_id)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe 'serialize -> deserialize round-trip' do
|
|
187
|
+
it 'recovers numeric values from serialized form' do
|
|
188
|
+
serialized = mod.serialize_trace(trace)
|
|
189
|
+
deserialized = mod.deserialize_trace(serialized)
|
|
190
|
+
|
|
191
|
+
expect(deserialized[:trace_id]).to eq(trace[:trace_id])
|
|
192
|
+
expect(deserialized[:trace_type]).to eq(trace[:trace_type])
|
|
193
|
+
expect(deserialized[:strength]).to be_within(0.001).of(trace[:strength])
|
|
194
|
+
expect(deserialized[:confidence]).to be_within(0.001).of(trace[:confidence])
|
|
195
|
+
expect(deserialized[:storage_tier]).to eq(:hot)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# --- cache_trace ---
|
|
200
|
+
|
|
201
|
+
describe '.cache_trace' do
|
|
202
|
+
context 'when unavailable' do
|
|
203
|
+
before { allow(mod).to receive(:available?).and_return(false) }
|
|
204
|
+
|
|
205
|
+
it 'returns nil without calling RedisHash' do
|
|
206
|
+
expect(Legion::Cache::RedisHash).not_to receive(:hset)
|
|
207
|
+
expect(mod.cache_trace(trace, tenant_id: tenant_id)).to be_nil
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
context 'when available' do
|
|
212
|
+
before do
|
|
213
|
+
allow(mod).to receive(:available?).and_return(true)
|
|
214
|
+
allow(Legion::Cache::RedisHash).to receive(:hset).and_return(true)
|
|
215
|
+
allow(Legion::Cache::RedisHash).to receive(:expire).and_return(true)
|
|
216
|
+
allow(Legion::Cache::RedisHash).to receive(:zadd).and_return(true)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'calls hset with the correct key and serialized data' do
|
|
220
|
+
key = mod.trace_key(tenant_id, trace_id)
|
|
221
|
+
expect(Legion::Cache::RedisHash).to receive(:hset).with(key, hash_including('trace_id' => trace_id))
|
|
222
|
+
mod.cache_trace(trace, tenant_id: tenant_id)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'calls expire with HOT_TTL' do
|
|
226
|
+
key = mod.trace_key(tenant_id, trace_id)
|
|
227
|
+
expect(Legion::Cache::RedisHash).to receive(:expire).with(key, described_class::HOT_TTL)
|
|
228
|
+
mod.cache_trace(trace, tenant_id: tenant_id)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'adds to the sorted-set index' do
|
|
232
|
+
index_key = "legion:tier:hot:#{tenant_id}"
|
|
233
|
+
expect(Legion::Cache::RedisHash).to receive(:zadd).with(index_key, anything, trace_id)
|
|
234
|
+
mod.cache_trace(trace, tenant_id: tenant_id)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'falls back to partition_id when tenant_id is not provided' do
|
|
238
|
+
key = mod.trace_key(trace[:partition_id], trace_id)
|
|
239
|
+
expect(Legion::Cache::RedisHash).to receive(:hset).with(key, anything)
|
|
240
|
+
mod.cache_trace(trace)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# --- fetch_trace ---
|
|
246
|
+
|
|
247
|
+
describe '.fetch_trace' do
|
|
248
|
+
context 'when unavailable' do
|
|
249
|
+
before { allow(mod).to receive(:available?).and_return(false) }
|
|
250
|
+
|
|
251
|
+
it 'returns nil' do
|
|
252
|
+
expect(mod.fetch_trace(trace_id, tenant_id: tenant_id)).to be_nil
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
context 'when available but key is missing' do
|
|
257
|
+
before do
|
|
258
|
+
allow(mod).to receive(:available?).and_return(true)
|
|
259
|
+
allow(Legion::Cache::RedisHash).to receive(:hgetall).and_return({})
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'returns nil' do
|
|
263
|
+
expect(mod.fetch_trace(trace_id, tenant_id: tenant_id)).to be_nil
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context 'when available and key exists' do
|
|
268
|
+
let(:cached_data) do
|
|
269
|
+
{
|
|
270
|
+
'trace_id' => trace_id,
|
|
271
|
+
'trace_type' => 'semantic',
|
|
272
|
+
'content_payload' => 'ruby is great',
|
|
273
|
+
'strength' => '0.85',
|
|
274
|
+
'peak_strength' => '0.95',
|
|
275
|
+
'confidence' => '0.9',
|
|
276
|
+
'storage_tier' => 'hot',
|
|
277
|
+
'partition_id' => tenant_id,
|
|
278
|
+
'last_reinforced' => Time.now.to_s
|
|
279
|
+
}
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
before do
|
|
283
|
+
allow(mod).to receive(:available?).and_return(true)
|
|
284
|
+
allow(Legion::Cache::RedisHash).to receive(:hgetall).and_return(cached_data)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'returns a deserialized trace hash' do
|
|
288
|
+
result = mod.fetch_trace(trace_id, tenant_id: tenant_id)
|
|
289
|
+
expect(result).not_to be_nil
|
|
290
|
+
expect(result[:trace_id]).to eq(trace_id)
|
|
291
|
+
expect(result[:trace_type]).to eq(:semantic)
|
|
292
|
+
expect(result[:storage_tier]).to eq(:hot)
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# --- evict_trace ---
|
|
298
|
+
|
|
299
|
+
describe '.evict_trace' do
|
|
300
|
+
context 'when unavailable' do
|
|
301
|
+
before { allow(mod).to receive(:available?).and_return(false) }
|
|
302
|
+
|
|
303
|
+
it 'returns nil without calling Cache.delete' do
|
|
304
|
+
expect(Legion::Cache).not_to receive(:delete)
|
|
305
|
+
expect(mod.evict_trace(trace_id, tenant_id: tenant_id)).to be_nil
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
context 'when available' do
|
|
310
|
+
before do
|
|
311
|
+
allow(mod).to receive(:available?).and_return(true)
|
|
312
|
+
allow(Legion::Cache).to receive(:delete).and_return(true)
|
|
313
|
+
allow(Legion::Cache::RedisHash).to receive(:zrem).and_return(true)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it 'deletes the trace key from Cache' do
|
|
317
|
+
key = mod.trace_key(tenant_id, trace_id)
|
|
318
|
+
expect(Legion::Cache).to receive(:delete).with(key)
|
|
319
|
+
mod.evict_trace(trace_id, tenant_id: tenant_id)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it 'removes the entry from the sorted-set index' do
|
|
323
|
+
index_key = "legion:tier:hot:#{tenant_id}"
|
|
324
|
+
expect(Legion::Cache::RedisHash).to receive(:zrem).with(index_key, trace_id)
|
|
325
|
+
mod.evict_trace(trace_id, tenant_id: tenant_id)
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# --- HOT_TTL constant ---
|
|
331
|
+
|
|
332
|
+
describe 'HOT_TTL' do
|
|
333
|
+
it 'is 86400 (24 hours in seconds)' do
|
|
334
|
+
expect(described_class::HOT_TTL).to eq(86_400)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|