remix-stash 0.9.0 → 0.9.6
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.
- data/.gitignore +1 -0
- data/LICENSE +21 -0
- data/README.markdown +32 -0
- data/Rakefile +12 -0
- data/VERSION +1 -0
- data/benchmarks/get_set.rb +35 -0
- data/benchmarks/payload.rb +125 -0
- data/examples/eval.rb +8 -0
- data/examples/gate.rb +6 -0
- data/examples/getset.rb +13 -0
- data/examples/scope.rb +17 -0
- data/examples/stash.rb +16 -0
- data/harness.rb +19 -0
- data/lib/remix/stash/cluster.rb +79 -0
- data/lib/remix/stash/extension.rb +7 -0
- data/lib/remix/stash/protocol.rb +139 -0
- data/lib/remix/stash.rb +256 -0
- data/remix-stash.gemspec +67 -0
- data/spec/extension_spec.rb +37 -0
- data/spec/spec.rb +10 -0
- data/spec/stash_spec.rb +411 -0
- metadata +36 -8
data/spec/stash_spec.rb
ADDED
@@ -0,0 +1,411 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec'
|
2
|
+
|
3
|
+
class StashSpec < Spec
|
4
|
+
|
5
|
+
def setup
|
6
|
+
stash.clear
|
7
|
+
Stash.class_eval("@@instances.clear")
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'coherency' do
|
11
|
+
|
12
|
+
should 'only allow valid coherency settings' do
|
13
|
+
stash.default(:coherency => :action)
|
14
|
+
stash.default(:coherency => :dynamic)
|
15
|
+
stash.default(:coherency => :transaction)
|
16
|
+
assert_raises ArgumentError do
|
17
|
+
stash.default(:coherency => :other)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'support :action coherency' do
|
22
|
+
one = stash(:one).release
|
23
|
+
two = stash(:one)
|
24
|
+
two.default(:coherency => :action)
|
25
|
+
one[:value] = 42
|
26
|
+
assert_equal 42, two[:value]
|
27
|
+
one.clear
|
28
|
+
one[:value] = 43
|
29
|
+
assert_equal 42, two[:value]
|
30
|
+
Stash.cycle_action
|
31
|
+
assert_equal 43, two[:value]
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'support :dynamic coherency' do
|
35
|
+
one = stash(:one).release
|
36
|
+
two = stash(:one)
|
37
|
+
two.default(:coherency => :dynamic)
|
38
|
+
one[:value] = 42
|
39
|
+
assert_equal 42, two[:value]
|
40
|
+
one.clear
|
41
|
+
one[:value] = 43
|
42
|
+
assert_equal 43, two[:value]
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'support :explicit coherency' do
|
46
|
+
one = stash(:one).release
|
47
|
+
two = stash(:one)
|
48
|
+
two.default(:coherency => :transaction)
|
49
|
+
one[:value] = 42
|
50
|
+
assert_equal 42, two[:value]
|
51
|
+
one.clear
|
52
|
+
one[:value] = 43
|
53
|
+
assert_equal 42, two[:value]
|
54
|
+
Stash.cycle_action
|
55
|
+
assert_equal 42, two[:value]
|
56
|
+
two.cycle
|
57
|
+
assert_equal 43, two[:value]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'defaults' do
|
63
|
+
|
64
|
+
should 'default to :action coherency' do
|
65
|
+
assert_equal :action, stash.default[:coherency]
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'use a default cluster on localhost:11211' do
|
69
|
+
local = Stash.cluster(:default)
|
70
|
+
assert_equal [['localhost:11211', 'localhost', 11211]], local.hosts
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context '.cycle_action' do
|
76
|
+
|
77
|
+
setup do
|
78
|
+
@cycle = stash(:action).release
|
79
|
+
@stash = stash(:action)
|
80
|
+
@stash.default(:coherency => :action)
|
81
|
+
end
|
82
|
+
|
83
|
+
should 'cycle all action conherent scopes' do
|
84
|
+
@stash.set('a', 42)
|
85
|
+
@cycle.clear
|
86
|
+
assert_equal 42, @stash.get('a')
|
87
|
+
Stash.cycle_action
|
88
|
+
assert_nil @stash.get('a')
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context '.define_cluster' do
|
94
|
+
|
95
|
+
should 'setup a cluster using an array of host/port pairs' do
|
96
|
+
Stash.define_cluster(:simple => %w[one:1 two:2], :sample => %w[miro.local:11211])
|
97
|
+
assert Stash.cluster(:simple)
|
98
|
+
assert Stash.cluster(:sample)
|
99
|
+
end
|
100
|
+
|
101
|
+
should 'default to port 11211' do
|
102
|
+
Stash.define_cluster(:default_port => 'default')
|
103
|
+
assert_equal [['default', 'default', 11211]], Stash.cluster(:default_port).hosts
|
104
|
+
end
|
105
|
+
|
106
|
+
should 'allow Cluster object to be passed in' do
|
107
|
+
cluster = Stash::Cluster.new(%w[localhost:11211])
|
108
|
+
Stash.define_cluster(:object => cluster)
|
109
|
+
assert_equal cluster, Stash.cluster(:object)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
context '#add' do
|
115
|
+
|
116
|
+
should 'allow keys to be set with new values' do
|
117
|
+
assert stash.add('f', '42')
|
118
|
+
assert_equal '42', stash.read('f')
|
119
|
+
end
|
120
|
+
|
121
|
+
should 'not overwrite existing values' do
|
122
|
+
stash['f'] = '43'
|
123
|
+
assert !stash.add('f', '42')
|
124
|
+
assert_equal '43', stash['f']
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
context '#clear' do
|
130
|
+
|
131
|
+
setup do
|
132
|
+
stash(:a).default(:coherency => :dynamic)
|
133
|
+
end
|
134
|
+
|
135
|
+
should 'flush all when called without keys on root' do
|
136
|
+
stash(:a).set(:b, :c)
|
137
|
+
stash.set(:d, :e)
|
138
|
+
stash.clear
|
139
|
+
assert_nil stash(:a).get(:b)
|
140
|
+
assert_nil stash.get(:d)
|
141
|
+
end
|
142
|
+
|
143
|
+
should 'clear just a scope when called without keys on a non-root node' do
|
144
|
+
stash(:a).set(:b, :c)
|
145
|
+
stash.set(:d, :e)
|
146
|
+
stash(:a).clear
|
147
|
+
assert_nil stash(:a).get(:b)
|
148
|
+
assert_equal :e, stash.get(:d)
|
149
|
+
end
|
150
|
+
|
151
|
+
should 'clear just a key when called with keys on any node' do
|
152
|
+
stash(:a).set(:b, :c)
|
153
|
+
stash.set(:d, :e)
|
154
|
+
stash.clear(:d)
|
155
|
+
assert_equal :c, stash(:a).get(:b)
|
156
|
+
assert_nil stash.get(:d)
|
157
|
+
stash(:a).clear
|
158
|
+
assert_nil stash(:a).get(:b)
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
context '#clear_scope' do
|
164
|
+
|
165
|
+
should 'remove the prior scope' do
|
166
|
+
stash[:foo] = :bar
|
167
|
+
stash.scope {42}
|
168
|
+
stash[:foo] = :qux
|
169
|
+
stash.clear_scope
|
170
|
+
assert_equal :bar, stash[:foo]
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
context '#cycle' do
|
176
|
+
|
177
|
+
should 'clear the cached vector' do
|
178
|
+
one = stash(:one).release
|
179
|
+
two = stash(:one)
|
180
|
+
one[:a] = :b
|
181
|
+
assert_equal :b, two[:a]
|
182
|
+
one.clear
|
183
|
+
one[:a] = :c
|
184
|
+
two.cycle
|
185
|
+
assert_equal :c, two[:a]
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
context '#decr' do
|
191
|
+
|
192
|
+
should 'decrement numeric values by a positive integer' do
|
193
|
+
stash.write(:a, '10')
|
194
|
+
stash.decr(:a, 1)
|
195
|
+
assert_equal 9, stash.read(:a).to_i
|
196
|
+
stash.decr(:a, 3)
|
197
|
+
assert_equal 6, stash.read(:a).to_i
|
198
|
+
end
|
199
|
+
|
200
|
+
should 'return the new numeric value' do
|
201
|
+
stash.write(:a, '45')
|
202
|
+
assert_equal 42, stash.decr(:a, 3)
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
context '#default' do
|
208
|
+
|
209
|
+
should 'return a Hash of default options' do
|
210
|
+
assert_kind_of Hash, stash(:one).default
|
211
|
+
end
|
212
|
+
|
213
|
+
should 'allow setting default options' do
|
214
|
+
s = stash(:two)
|
215
|
+
long_time = 5000
|
216
|
+
s.default(:ttl => long_time)
|
217
|
+
assert_equal long_time, s.default[:ttl]
|
218
|
+
end
|
219
|
+
|
220
|
+
should 'merge with top-level default options' do
|
221
|
+
s = stash(:three)
|
222
|
+
stash.default(:ttl => 3600)
|
223
|
+
assert_equal 3600, s.default[:ttl]
|
224
|
+
s.default(:ttl => 4800)
|
225
|
+
assert_equal 4800, s.default[:ttl]
|
226
|
+
assert_equal 3600, stash.default[:ttl]
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
context '#delete' do
|
232
|
+
|
233
|
+
should 'remove a key from the cache' do
|
234
|
+
stash[:foo] = 42
|
235
|
+
stash.delete(:foo)
|
236
|
+
assert_nil stash[:foo]
|
237
|
+
end
|
238
|
+
|
239
|
+
should 'return true when deleted' do
|
240
|
+
stash[:foo] = 42
|
241
|
+
assert stash.delete(:foo)
|
242
|
+
end
|
243
|
+
|
244
|
+
should 'return false when not found' do
|
245
|
+
assert !stash.delete(:foo)
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
context '#eval' do
|
251
|
+
|
252
|
+
should 'evaluate the block on a cache miss' do
|
253
|
+
ran = false
|
254
|
+
stash.eval(:a) {ran = true}
|
255
|
+
assert ran
|
256
|
+
end
|
257
|
+
|
258
|
+
should 'not evaluate on a cache hit' do
|
259
|
+
ran = false
|
260
|
+
stash[:a] = 42
|
261
|
+
stash.eval(:a) {ran = false}
|
262
|
+
assert !ran
|
263
|
+
end
|
264
|
+
|
265
|
+
should 'pass keys in as optional block arguments' do
|
266
|
+
assert 42, stash.eval(42) {|a| a}
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
context '#gate' do
|
272
|
+
|
273
|
+
should 'not evaluate on a key miss' do
|
274
|
+
ran = false
|
275
|
+
stash.gate(:k) {ran = true}
|
276
|
+
assert !ran
|
277
|
+
end
|
278
|
+
|
279
|
+
should 'evaluate on a key hit' do
|
280
|
+
ran = false
|
281
|
+
stash[:k] = :hit
|
282
|
+
stash.gate(:k) {ran = true}
|
283
|
+
assert ran
|
284
|
+
end
|
285
|
+
|
286
|
+
should 'return true on hit' do
|
287
|
+
stash[:k] = :hit
|
288
|
+
assert stash.gate(:k) {}
|
289
|
+
end
|
290
|
+
|
291
|
+
should 'return false on miss' do
|
292
|
+
assert !stash.gate(:k) {}
|
293
|
+
end
|
294
|
+
|
295
|
+
should 'pass keys in as optional block arguments' do
|
296
|
+
key = nil
|
297
|
+
stash[42] = true
|
298
|
+
stash.gate(42) {|k| key = k}
|
299
|
+
assert_equal 42, key
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
context '#get' do
|
305
|
+
|
306
|
+
should 'allow simple get on the same keyspace as eval' do
|
307
|
+
stash.eval(:foo) {42}
|
308
|
+
assert_equal 42, stash[:foo]
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
context '#incr' do
|
314
|
+
|
315
|
+
should 'increment numeric values by the passed integer' do
|
316
|
+
stash.write(:a, '10')
|
317
|
+
assert_equal 12, stash.incr(:a, 2)
|
318
|
+
end
|
319
|
+
|
320
|
+
should 'return nil if it failed to increment' do
|
321
|
+
assert_nil stash.incr(:a, 3)
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
context '#read' do
|
327
|
+
|
328
|
+
should 'read raw strings from the cache' do
|
329
|
+
stash[:a] = 42
|
330
|
+
assert_equal Marshal.dump(42), stash.read(:a)
|
331
|
+
end
|
332
|
+
|
333
|
+
should 'return nil when the key is not found' do
|
334
|
+
assert_nil stash.read(:not_found)
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
|
339
|
+
context '#release' do
|
340
|
+
|
341
|
+
should 'return itself' do
|
342
|
+
assert_instance_of Stash, stash(:one).release
|
343
|
+
end
|
344
|
+
|
345
|
+
should 'remove it from the name registery' do
|
346
|
+
assert_not_equal stash(:one).release, stash(:one)
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
context '#scope' do
|
352
|
+
|
353
|
+
should 'set an implicit scope variable for keyspaces' do
|
354
|
+
a = 1
|
355
|
+
stash.scope {a}
|
356
|
+
stash[:k] = :v
|
357
|
+
a = 2
|
358
|
+
assert_nil stash[:k]
|
359
|
+
end
|
360
|
+
|
361
|
+
should 'be used by the vector key' do
|
362
|
+
one = stash(:one).release
|
363
|
+
two = stash(:one)
|
364
|
+
a = 0
|
365
|
+
one.scope {a}
|
366
|
+
one[:a] = 1
|
367
|
+
two.clear
|
368
|
+
one.cycle
|
369
|
+
assert_equal 1, one[:a]
|
370
|
+
end
|
371
|
+
|
372
|
+
should 'return self' do
|
373
|
+
assert_equal stash, stash.scope {}
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
context '#set' do
|
379
|
+
|
380
|
+
should 'allow simple set on the same keyspace as eval' do
|
381
|
+
stash.set(:a, 42)
|
382
|
+
assert_equal 42, stash.eval(:a) {fail 'expected cache hit'}
|
383
|
+
end
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
context '#transaction' do
|
388
|
+
|
389
|
+
should 'cycle the vector at the end of the transaction block' do
|
390
|
+
one = stash(:one).release
|
391
|
+
two = stash(:one)
|
392
|
+
one.transaction do
|
393
|
+
one[:a] = 42
|
394
|
+
two.clear
|
395
|
+
assert_equal 42, one[:a]
|
396
|
+
end
|
397
|
+
assert_nil one[:a]
|
398
|
+
end
|
399
|
+
|
400
|
+
end
|
401
|
+
|
402
|
+
context '#write' do
|
403
|
+
|
404
|
+
should 'write raw strings to the cache' do
|
405
|
+
stash.write(42, '42')
|
406
|
+
assert_equal '42', stash.read(42)
|
407
|
+
end
|
408
|
+
|
409
|
+
end
|
410
|
+
|
411
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remix-stash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Mitchell
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-22 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -19,10 +19,31 @@ executables: []
|
|
19
19
|
|
20
20
|
extensions: []
|
21
21
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.markdown
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- LICENSE
|
28
|
+
- README.markdown
|
29
|
+
- Rakefile
|
30
|
+
- VERSION
|
31
|
+
- benchmarks/get_set.rb
|
32
|
+
- benchmarks/payload.rb
|
33
|
+
- examples/eval.rb
|
34
|
+
- examples/gate.rb
|
35
|
+
- examples/getset.rb
|
36
|
+
- examples/scope.rb
|
37
|
+
- examples/stash.rb
|
38
|
+
- harness.rb
|
39
|
+
- lib/remix/stash.rb
|
40
|
+
- lib/remix/stash/cluster.rb
|
41
|
+
- lib/remix/stash/extension.rb
|
42
|
+
- lib/remix/stash/protocol.rb
|
43
|
+
- remix-stash.gemspec
|
44
|
+
- spec/extension_spec.rb
|
45
|
+
- spec/spec.rb
|
46
|
+
- spec/stash_spec.rb
|
26
47
|
has_rdoc: true
|
27
48
|
homepage: http://github.com/binary42/remix-stash
|
28
49
|
post_install_message:
|
@@ -49,5 +70,12 @@ rubygems_version: 1.3.1
|
|
49
70
|
signing_key:
|
50
71
|
specification_version: 2
|
51
72
|
summary: Remix your memcache
|
52
|
-
test_files:
|
53
|
-
|
73
|
+
test_files:
|
74
|
+
- spec/extension_spec.rb
|
75
|
+
- spec/spec.rb
|
76
|
+
- spec/stash_spec.rb
|
77
|
+
- examples/eval.rb
|
78
|
+
- examples/gate.rb
|
79
|
+
- examples/getset.rb
|
80
|
+
- examples/scope.rb
|
81
|
+
- examples/stash.rb
|