mudis 0.5.0 → 0.7.0

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.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "spec_helper"
4
+
5
+ RSpec.describe "Mudis Metrics" do # rubocop:disable Metrics/BlockLength
6
+ it "tracks hits and misses" do
7
+ Mudis.write("hit_me", "value")
8
+ Mudis.read("hit_me")
9
+ Mudis.read("miss_me")
10
+ metrics = Mudis.metrics
11
+ expect(metrics[:hits]).to eq(1)
12
+ expect(metrics[:misses]).to eq(1)
13
+ end
14
+
15
+ it "includes per-bucket stats" do
16
+ Mudis.write("a", "x" * 50)
17
+ metrics = Mudis.metrics
18
+ expect(metrics).to include(:buckets)
19
+ expect(metrics[:buckets]).to be_an(Array)
20
+ expect(metrics[:buckets].first).to include(:index, :keys, :memory_bytes, :lru_size)
21
+ end
22
+
23
+ it "resets only the metrics without clearing cache" do
24
+ Mudis.write("metrics_key", "value")
25
+ Mudis.read("metrics_key")
26
+ Mudis.read("missing_key")
27
+ expect(Mudis.metrics[:hits]).to eq(1)
28
+ expect(Mudis.metrics[:misses]).to eq(1)
29
+ Mudis.reset_metrics!
30
+ expect(Mudis.metrics[:hits]).to eq(0)
31
+ expect(Mudis.metrics[:misses]).to eq(0)
32
+ expect(Mudis.read("metrics_key")).to eq("value")
33
+ end
34
+ end
data/spec/mudis_spec.rb CHANGED
@@ -1,314 +1,183 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "spec_helper"
4
-
5
- RSpec.describe Mudis do # rubocop:disable Metrics/BlockLength
6
- before(:each) do
7
- Mudis.stop_expiry_thread
8
- Mudis.instance_variable_set(:@buckets, nil)
9
- Mudis.instance_variable_set(:@stores, Array.new(Mudis.buckets) { {} })
10
- Mudis.instance_variable_set(:@mutexes, Array.new(Mudis.buckets) { Mutex.new })
11
- Mudis.instance_variable_set(:@lru_heads, Array.new(Mudis.buckets) { nil })
12
- Mudis.instance_variable_set(:@lru_tails, Array.new(Mudis.buckets) { nil })
13
- Mudis.instance_variable_set(:@lru_nodes, Array.new(Mudis.buckets) { {} })
14
- Mudis.instance_variable_set(:@current_bytes, Array.new(Mudis.buckets, 0))
15
- Mudis.instance_variable_set(:@metrics, { hits: 0, misses: 0, evictions: 0, rejected: 0 })
16
- Mudis.serializer = JSON
17
- Mudis.compress = false
18
- Mudis.max_value_bytes = nil
19
- end
20
-
21
- describe ".write and .read" do
22
- it "writes and reads a value" do
23
- Mudis.write("foo", { bar: "baz" })
24
- result = Mudis.read("foo")
25
- expect(result).to eq({ "bar" => "baz" })
26
- end
27
-
28
- it "returns nil for non-existent keys" do
29
- expect(Mudis.read("nope")).to be_nil
30
- end
31
- end
32
-
33
- describe ".exists?" do
34
- it "returns true if key exists" do
35
- Mudis.write("check", [1, 2, 3])
36
- expect(Mudis.exists?("check")).to be true
37
- end
38
-
39
- it "returns false if key does not exist" do
40
- expect(Mudis.exists?("missing")).to be false
41
- end
42
- end
43
-
44
- describe ".delete" do
45
- it "deletes a key" do
46
- Mudis.write("temp", 42)
47
- Mudis.delete("temp")
48
- expect(Mudis.read("temp")).to be_nil
49
- end
50
- end
51
-
52
- describe ".update" do
53
- it "updates a cached value" do
54
- Mudis.write("counter", 5)
55
- Mudis.update("counter") { |v| v + 1 }
56
- expect(Mudis.read("counter")).to eq(6)
57
- end
58
- end
59
-
60
- describe ".fetch" do
61
- it "returns cached value if exists" do
62
- Mudis.write("k", 123)
63
- result = Mudis.fetch("k", expires_in: 60) { 999 } # fix: use keyword arg
64
- expect(result).to eq(123)
65
- end
66
-
67
- it "writes and returns block result if missing" do
68
- Mudis.delete("k")
69
- result = Mudis.fetch("k", expires_in: 60) { 999 } # fix
70
- expect(result).to eq(999)
71
- expect(Mudis.read("k")).to eq(999)
72
- end
73
-
74
- it "forces overwrite if force: true" do
75
- Mudis.write("k", 100)
76
- result = Mudis.fetch("k", force: true) { 200 } # fix
77
- expect(result).to eq(200)
78
- end
79
- end
80
-
81
- describe ".clear" do
82
- it "removes a key from the cache" do
83
- Mudis.write("to_clear", 123)
84
- expect(Mudis.read("to_clear")).to eq(123)
85
- Mudis.clear("to_clear")
86
- expect(Mudis.read("to_clear")).to be_nil
87
- end
88
- end
89
-
90
- describe ".replace" do
91
- it "replaces value only if key exists" do
92
- Mudis.write("to_replace", 100)
93
- Mudis.replace("to_replace", 200)
94
- expect(Mudis.read("to_replace")).to eq(200)
95
-
96
- Mudis.delete("to_replace")
97
- Mudis.replace("to_replace", 300)
98
- expect(Mudis.read("to_replace")).to be_nil
99
- end
100
- end
101
-
102
- describe ".inspect" do
103
- it "returns metadata for a cached key" do
104
- Mudis.write("key1", "abc", expires_in: 60)
105
- meta = Mudis.inspect("key1")
106
-
107
- expect(meta).to include(:key, :bucket, :expires_at, :created_at, :size_bytes, :compressed)
108
- expect(meta[:key]).to eq("key1")
109
- expect(meta[:compressed]).to eq(false)
110
- end
111
-
112
- it "returns nil for missing key" do
113
- expect(Mudis.inspect("unknown")).to be_nil
114
- end
115
- end
116
-
117
- describe "namespacing" do
118
- it "uses thread-local namespace in block" do
119
- Mudis.with_namespace("test") do
120
- Mudis.write("foo", "bar")
121
- end
122
- expect(Mudis.read("foo", namespace: "test")).to eq("bar")
123
- expect(Mudis.read("foo")).to be_nil
124
- end
125
-
126
- it "supports explicit namespace override" do
127
- Mudis.write("x", 1, namespace: "alpha")
128
- Mudis.write("x", 2, namespace: "beta")
129
- expect(Mudis.read("x", namespace: "alpha")).to eq(1)
130
- expect(Mudis.read("x", namespace: "beta")).to eq(2)
131
- expect(Mudis.read("x")).to be_nil
132
- end
133
- end
134
-
135
- describe "expiry handling" do
136
- it "expires values after specified time" do
137
- Mudis.write("short_lived", "gone soon", expires_in: 1)
138
- sleep 2
139
- expect(Mudis.read("short_lived")).to be_nil
140
- end
141
- end
142
-
143
- describe ".metrics" do
144
- it "tracks hits and misses" do
145
- Mudis.write("hit_me", "value")
146
- Mudis.read("hit_me") # hit
147
- Mudis.read("miss_me") # miss
148
- metrics = Mudis.metrics
149
- expect(metrics[:hits]).to eq(1)
150
- expect(metrics[:misses]).to eq(1)
151
- end
152
- end
153
-
154
- describe "memory guards" do
155
- before do
156
- Mudis.stop_expiry_thread
157
- Mudis.instance_variable_set(:@buckets, 1)
158
- Mudis.instance_variable_set(:@stores, [{}])
159
- Mudis.instance_variable_set(:@mutexes, [Mutex.new])
160
- Mudis.instance_variable_set(:@lru_heads, [nil])
161
- Mudis.instance_variable_set(:@lru_tails, [nil])
162
- Mudis.instance_variable_set(:@lru_nodes, [{}])
163
- Mudis.instance_variable_set(:@current_bytes, [0])
164
-
165
- Mudis.max_value_bytes = nil
166
- Mudis.instance_variable_set(:@threshold_bytes, 1_000_000) # optional
167
- Mudis.hard_memory_limit = true
168
- Mudis.instance_variable_set(:@max_bytes, 100) # artificially low
169
- end
170
-
171
- it "rejects writes that exceed max memory" do
172
- big_value = "a" * 90
173
- Mudis.write("a", big_value)
174
- expect(Mudis.read("a")).to eq(big_value)
175
-
176
- big_value_2 = "b" * 90 # rubocop:disable Naming/VariableNumber
177
- Mudis.write("b", big_value_2)
178
- expect(Mudis.read("b")).to be_nil
179
- expect(Mudis.metrics[:rejected]).to be > 0
180
- end
181
- end
182
-
183
- describe "LRU eviction" do
184
- it "evicts old entries when size limit is reached" do
185
- Mudis.stop_expiry_thread
186
-
187
- # Force one bucket
188
- Mudis.instance_variable_set(:@buckets, 1)
189
- Mudis.instance_variable_set(:@stores, [{}])
190
- Mudis.instance_variable_set(:@mutexes, [Mutex.new])
191
- Mudis.instance_variable_set(:@lru_heads, [nil])
192
- Mudis.instance_variable_set(:@lru_tails, [nil])
193
- Mudis.instance_variable_set(:@lru_nodes, [{}])
194
- Mudis.instance_variable_set(:@current_bytes, [0])
195
- Mudis.hard_memory_limit = false
196
- # Set very small threshold
197
- Mudis.instance_variable_set(:@threshold_bytes, 60)
198
- Mudis.max_value_bytes = 100
199
-
200
- big_val1 = "a" * 50
201
- big_val2 = "b" * 50
202
-
203
- Mudis.write("a", big_val1)
204
- Mudis.write("b", big_val2)
205
-
206
- expect(Mudis.read("a")).to be_nil
207
- expect(Mudis.read("b")).not_to be_nil
208
- end
209
- end
210
-
211
- describe ".all_keys" do
212
- it "lists all stored keys" do
213
- Mudis.write("k1", 1)
214
- Mudis.write("k2", 2)
215
- expect(Mudis.all_keys).to include("k1", "k2")
216
- end
217
- end
218
-
219
- it "respects max_bytes when updated externally" do
220
- Mudis.max_bytes = 100
221
- expect(Mudis.send(:max_bytes)).to eq(100)
222
- end
223
-
224
- describe ".current_memory_bytes" do
225
- it "returns a non-zero byte count after writes" do
226
- Mudis.write("size_test", "a" * 100)
227
- expect(Mudis.current_memory_bytes).to be > 0
228
- end
229
- end
230
-
231
- describe ".metrics" do
232
- it "includes per-bucket stats" do
233
- Mudis.write("a", "x" * 50)
234
- metrics = Mudis.metrics
235
-
236
- expect(metrics).to include(:buckets)
237
- expect(metrics[:buckets]).to be_an(Array)
238
- expect(metrics[:buckets].first).to include(:index, :keys, :memory_bytes, :lru_size)
239
- end
240
- end
241
-
242
- describe ".least_touched" do
243
- it "returns keys with lowest read access counts" do
244
- Mudis.reset!
245
- Mudis.write("a", 1)
246
- Mudis.write("b", 2)
247
- Mudis.write("c", 3)
248
-
249
- Mudis.read("a")
250
- Mudis.read("a")
251
- Mudis.read("b")
252
-
253
- least = Mudis.least_touched(2)
254
- expect(least.map(&:first)).to include("c") # Never read
255
- expect(least.first.last).to eq(0)
256
- end
257
- end
258
-
259
- describe ".configure" do
260
- it "applies configuration settings correctly" do
261
- Mudis.configure do |c|
262
- c.serializer = JSON
263
- c.compress = true
264
- c.max_value_bytes = 12_345
265
- c.hard_memory_limit = true
266
- c.max_bytes = 987_654
267
- end
268
-
269
- expect(Mudis.compress).to eq(true)
270
- expect(Mudis.max_value_bytes).to eq(12_345)
271
- expect(Mudis.hard_memory_limit).to eq(true)
272
- expect(Mudis.max_bytes).to eq(987_654)
273
- end
274
- end
275
-
276
- describe ".reset!" do
277
- it "clears all stores, memory, and metrics" do
278
- Mudis.write("reset_key", "value")
279
- expect(Mudis.read("reset_key")).to eq("value")
280
- expect(Mudis.current_memory_bytes).to be > 0
281
- expect(Mudis.metrics[:hits]).to be >= 0
282
-
283
- Mudis.reset!
284
-
285
- metrics = Mudis.metrics
286
- expect(metrics[:hits]).to eq(0)
287
- expect(metrics[:misses]).to eq(0)
288
- expect(metrics[:evictions]).to eq(0)
289
- expect(metrics[:rejected]).to eq(0)
290
- expect(Mudis.current_memory_bytes).to eq(0)
291
- expect(Mudis.all_keys).to be_empty
292
-
293
- # Optionally confirm reset_key is now gone
294
- expect(Mudis.read("reset_key")).to be_nil
295
- end
296
- end
297
-
298
- describe ".reset_metrics!" do
299
- it "resets only the metrics without clearing cache" do
300
- Mudis.write("metrics_key", "value")
301
- Mudis.read("metrics_key") # generates :hits
302
- Mudis.read("missing_key") # generates :misses
303
-
304
- expect(Mudis.metrics[:hits]).to eq(1)
305
- expect(Mudis.metrics[:misses]).to eq(1)
306
-
307
- Mudis.reset_metrics!
308
-
309
- expect(Mudis.metrics[:hits]).to eq(0)
310
- expect(Mudis.metrics[:misses]).to eq(0)
311
- expect(Mudis.read("metrics_key")).to eq("value") # still exists
312
- end
313
- end
314
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "spec_helper"
4
+
5
+ RSpec.describe Mudis do # rubocop:disable Metrics/BlockLength
6
+ before(:each) do
7
+ Mudis.stop_expiry_thread
8
+ Mudis.instance_variable_set(:@buckets, nil)
9
+ Mudis.instance_variable_set(:@stores, Array.new(Mudis.buckets) { {} })
10
+ Mudis.instance_variable_set(:@mutexes, Array.new(Mudis.buckets) { Mutex.new })
11
+ Mudis.instance_variable_set(:@lru_heads, Array.new(Mudis.buckets) { nil })
12
+ Mudis.instance_variable_set(:@lru_tails, Array.new(Mudis.buckets) { nil })
13
+ Mudis.instance_variable_set(:@lru_nodes, Array.new(Mudis.buckets) { {} })
14
+ Mudis.instance_variable_set(:@current_bytes, Array.new(Mudis.buckets, 0))
15
+ Mudis.instance_variable_set(:@metrics, { hits: 0, misses: 0, evictions: 0, rejected: 0 })
16
+ Mudis.serializer = JSON
17
+ Mudis.compress = false
18
+ Mudis.max_value_bytes = nil
19
+ end
20
+
21
+ describe ".write and .read" do
22
+ it "writes and reads a value" do
23
+ Mudis.write("foo", { bar: "baz" })
24
+ result = Mudis.read("foo")
25
+ expect(result).to eq({ "bar" => "baz" })
26
+ end
27
+
28
+ it "returns nil for non-existent keys" do
29
+ expect(Mudis.read("nope")).to be_nil
30
+ end
31
+ end
32
+
33
+ describe ".exists?" do
34
+ it "returns true if key exists" do
35
+ Mudis.write("check", [1, 2, 3])
36
+ expect(Mudis.exists?("check")).to be true
37
+ end
38
+
39
+ it "returns false if key does not exist" do
40
+ expect(Mudis.exists?("missing")).to be false
41
+ end
42
+ end
43
+
44
+ describe ".delete" do
45
+ it "deletes a key" do
46
+ Mudis.write("temp", 42)
47
+ Mudis.delete("temp")
48
+ expect(Mudis.read("temp")).to be_nil
49
+ end
50
+ end
51
+
52
+ describe ".update" do
53
+ it "updates a cached value" do
54
+ Mudis.write("counter", 5)
55
+ Mudis.update("counter") { |v| v + 1 }
56
+ expect(Mudis.read("counter")).to eq(6)
57
+ end
58
+ end
59
+
60
+ describe ".fetch" do
61
+ it "returns cached value if exists" do
62
+ Mudis.write("k", 123)
63
+ result = Mudis.fetch("k", expires_in: 60) { 999 } # fix: use keyword arg
64
+ expect(result).to eq(123)
65
+ end
66
+
67
+ it "writes and returns block result if missing" do
68
+ Mudis.delete("k")
69
+ result = Mudis.fetch("k", expires_in: 60) { 999 } # fix
70
+ expect(result).to eq(999)
71
+ expect(Mudis.read("k")).to eq(999)
72
+ end
73
+
74
+ it "forces overwrite if force: true" do
75
+ Mudis.write("k", 100)
76
+ result = Mudis.fetch("k", force: true) { 200 } # fix
77
+ expect(result).to eq(200)
78
+ end
79
+ end
80
+
81
+ describe ".clear" do
82
+ it "removes a key from the cache" do
83
+ Mudis.write("to_clear", 123)
84
+ expect(Mudis.read("to_clear")).to eq(123)
85
+ Mudis.clear("to_clear")
86
+ expect(Mudis.read("to_clear")).to be_nil
87
+ end
88
+ end
89
+
90
+ describe ".replace" do
91
+ it "replaces value only if key exists" do
92
+ Mudis.write("to_replace", 100)
93
+ Mudis.replace("to_replace", 200)
94
+ expect(Mudis.read("to_replace")).to eq(200)
95
+
96
+ Mudis.delete("to_replace")
97
+ Mudis.replace("to_replace", 300)
98
+ expect(Mudis.read("to_replace")).to be_nil
99
+ end
100
+ end
101
+
102
+ describe ".inspect" do
103
+ it "returns metadata for a cached key" do
104
+ Mudis.write("key1", "abc", expires_in: 60)
105
+ meta = Mudis.inspect("key1")
106
+
107
+ expect(meta).to include(:key, :bucket, :expires_at, :created_at, :size_bytes, :compressed)
108
+ expect(meta[:key]).to eq("key1")
109
+ expect(meta[:compressed]).to eq(false)
110
+ end
111
+
112
+ it "returns nil for missing key" do
113
+ expect(Mudis.inspect("unknown")).to be_nil
114
+ end
115
+ end
116
+
117
+ describe "expiry handling" do
118
+ it "expires values after specified time" do
119
+ Mudis.write("short_lived", "gone soon", expires_in: 1)
120
+ sleep 2
121
+ expect(Mudis.read("short_lived")).to be_nil
122
+ end
123
+ end
124
+
125
+ describe ".all_keys" do
126
+ it "lists all stored keys" do
127
+ Mudis.write("k1", 1)
128
+ Mudis.write("k2", 2)
129
+ expect(Mudis.all_keys).to include("k1", "k2")
130
+ end
131
+ end
132
+
133
+ it "respects max_bytes when updated externally" do
134
+ Mudis.max_bytes = 100
135
+ expect(Mudis.send(:max_bytes)).to eq(100)
136
+ end
137
+
138
+ describe ".current_memory_bytes" do
139
+ it "returns a non-zero byte count after writes" do
140
+ Mudis.configure do |c|
141
+ c.max_value_bytes = nil
142
+ c.hard_memory_limit = false
143
+ end
144
+
145
+ Mudis.write("size_test", "a" * 100)
146
+ expect(Mudis.current_memory_bytes).to be > 0
147
+ end
148
+ end
149
+
150
+ describe ".least_touched" do
151
+ it "returns keys with lowest read access counts" do
152
+ Mudis.reset!
153
+ Mudis.write("a", 1)
154
+ Mudis.write("b", 2)
155
+ Mudis.write("c", 3)
156
+
157
+ Mudis.read("a")
158
+ Mudis.read("a")
159
+ Mudis.read("b")
160
+
161
+ least = Mudis.least_touched(2)
162
+ expect(least.map(&:first)).to include("c") # Never read
163
+ expect(least.first.last).to eq(0)
164
+ end
165
+ end
166
+
167
+ describe ".configure" do
168
+ it "applies configuration settings correctly" do
169
+ Mudis.configure do |c|
170
+ c.serializer = JSON
171
+ c.compress = true
172
+ c.max_value_bytes = 12_345
173
+ c.hard_memory_limit = true
174
+ c.max_bytes = 987_654
175
+ end
176
+
177
+ expect(Mudis.compress).to eq(true)
178
+ expect(Mudis.max_value_bytes).to eq(12_345)
179
+ expect(Mudis.hard_memory_limit).to eq(true)
180
+ expect(Mudis.max_bytes).to eq(987_654)
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Mudis Namespace Operations" do # rubocop:disable Metrics/BlockLength
6
+ before(:each) do
7
+ Mudis.reset!
8
+ end
9
+
10
+ it "uses thread-local namespace in block" do
11
+ Mudis.with_namespace("test") do
12
+ Mudis.write("foo", "bar")
13
+ end
14
+ expect(Mudis.read("foo", namespace: "test")).to eq("bar")
15
+ expect(Mudis.read("foo")).to be_nil
16
+ end
17
+
18
+ it "supports explicit namespace override" do
19
+ Mudis.write("x", 1, namespace: "alpha")
20
+ Mudis.write("x", 2, namespace: "beta")
21
+ expect(Mudis.read("x", namespace: "alpha")).to eq(1)
22
+ expect(Mudis.read("x", namespace: "beta")).to eq(2)
23
+ expect(Mudis.read("x")).to be_nil
24
+ end
25
+
26
+ describe ".keys" do
27
+ it "returns only keys for the given namespace" do
28
+ Mudis.write("user:1", "Alice", namespace: "users")
29
+ Mudis.write("user:2", "Bob", namespace: "users")
30
+ Mudis.write("admin:1", "Charlie", namespace: "admins")
31
+
32
+ result = Mudis.keys(namespace: "users")
33
+ expect(result).to contain_exactly("user:1", "user:2")
34
+ end
35
+
36
+ it "returns an empty array if no keys exist for namespace" do
37
+ expect(Mudis.keys(namespace: "nonexistent")).to eq([])
38
+ end
39
+
40
+ it "raises an error if namespace is missing" do
41
+ expect { Mudis.keys(namespace: nil) }.to raise_error(ArgumentError, /namespace is required/)
42
+ end
43
+ end
44
+
45
+ describe ".clear_namespace" do
46
+ it "deletes all keys in the given namespace" do
47
+ Mudis.write("a", 1, namespace: "ns1")
48
+ Mudis.write("b", 2, namespace: "ns1")
49
+ Mudis.write("x", 9, namespace: "ns2")
50
+
51
+ expect(Mudis.read("a", namespace: "ns1")).to eq(1)
52
+ expect(Mudis.read("b", namespace: "ns1")).to eq(2)
53
+
54
+ Mudis.clear_namespace(namespace: "ns1")
55
+
56
+ expect(Mudis.read("a", namespace: "ns1")).to be_nil
57
+ expect(Mudis.read("b", namespace: "ns1")).to be_nil
58
+ expect(Mudis.read("x", namespace: "ns2")).to eq(9)
59
+ end
60
+
61
+ it "does nothing if namespace has no keys" do
62
+ expect { Mudis.clear_namespace(namespace: "ghost") }.not_to raise_error
63
+ end
64
+
65
+ it "raises an error if namespace is nil" do
66
+ expect { Mudis.clear_namespace(namespace: nil) }.to raise_error(ArgumentError, /namespace is required/)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Mudis Reset Features" do
6
+ before { Mudis.reset! }
7
+
8
+ describe ".reset!" do
9
+ it "clears all stores, memory, and metrics" do
10
+ Mudis.write("reset_key", "value")
11
+ expect(Mudis.read("reset_key")).to eq("value")
12
+ Mudis.reset!
13
+ expect(Mudis.metrics[:hits]).to eq(0)
14
+ expect(Mudis.all_keys).to be_empty
15
+ expect(Mudis.read("reset_key")).to be_nil
16
+ end
17
+ end
18
+
19
+ describe ".reset_metrics!" do
20
+ it "resets only the metrics without clearing cache" do
21
+ Mudis.write("metrics_key", "value")
22
+ Mudis.read("metrics_key")
23
+ Mudis.read("missing_key")
24
+ expect(Mudis.metrics[:hits]).to eq(1)
25
+ expect(Mudis.metrics[:misses]).to eq(1)
26
+ Mudis.reset_metrics!
27
+ expect(Mudis.metrics[:hits]).to eq(0)
28
+ expect(Mudis.read("metrics_key")).to eq("value")
29
+ end
30
+ end
31
+ end