redis_recipes 0.3.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,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Range Lookup X: Lookup" do
4
+
5
+ def add(member, min, max)
6
+ evalsha :add, keys: ["my_store"], argv: [member, min, max]
7
+ end
8
+
9
+ def lookup(value)
10
+ evalsha :lookup, keys: ["my_store"], argv: [value]
11
+ end
12
+
13
+ before do
14
+ add("A", 0, 8)
15
+ add("B", 4, 6)
16
+ add("C", 2, 9)
17
+ add("D", 7, 10)
18
+ end
19
+
20
+ def state
21
+ ranges = {}
22
+ redis.zrange('my_store:~', 0, -1, with_scores: true).each do |value, score|
23
+ ranges[score.to_f] = redis.smembers("my_store:#{value}").sort
24
+ end
25
+ ranges
26
+ end
27
+
28
+ it 'should catch invalid arguments' do
29
+ lambda { evalsha :lookup }.should raise_error(Redis::CommandError, /wrong number of arguments/)
30
+ lambda { evalsha :lookup, keys: ["one"] }.should raise_error(Redis::CommandError, /wrong number of arguments/)
31
+ lambda { evalsha :lookup, keys: ["one"], argv: ["one", 2] }.should raise_error(Redis::CommandError, /wrong number of arguments/)
32
+ end
33
+
34
+ it 'should catch non-numeric ranges' do
35
+ lambda { evalsha :lookup, keys: ["one"], argv: ["one"] }.should raise_error(Redis::CommandError, /not numeric or out of range/)
36
+ end
37
+
38
+ it 'should return the members when found' do
39
+ lookup(0).should =~ ["A"]
40
+ lookup(1).should =~ ["A"]
41
+ lookup(2).should =~ ["A", "C"]
42
+ lookup(3).should =~ ["A", "C"]
43
+ lookup(4).should =~ ["A", "B", "C"]
44
+ lookup(5).should =~ ["A", "B", "C"]
45
+ lookup(6).should =~ ["A", "C"]
46
+ lookup(7).should =~ ["A", "C", "D"]
47
+ lookup(8).should =~ ["C", "D"]
48
+ lookup(9).should =~ ["D"]
49
+ lookup(10).should =~ []
50
+ end
51
+
52
+ it 'should return an empty set if not found' do
53
+ lookup(-1).should =~ []
54
+ lookup(11).should =~ []
55
+ lookup(111).should =~ []
56
+ end
57
+
58
+ it 'should support float lookups' do
59
+ lookup(-0.1).should =~ []
60
+ lookup(6.5).should =~ ["A", "C"]
61
+ lookup(7.5).should =~ ["A", "C", "D"]
62
+ lookup(9.99).should =~ ["D"]
63
+ end
64
+
65
+ end
@@ -0,0 +1,186 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Range Lookup X: Removing" do
4
+
5
+ def state(c = :to_i)
6
+ ranges = {}
7
+ redis.zrange('my_store:~', 0, -1, with_scores: true).each do |value, score|
8
+ ranges[score.send(c)] = redis.smembers("my_store:#{value}").sort.join
9
+ end
10
+ ranges
11
+ end
12
+
13
+ def brackets
14
+ redis.zrange('my_store:~', 0, -1)
15
+ end
16
+
17
+ def add(member, min, max)
18
+ evalsha :add, keys: ["my_store"], argv: [member, min, max]
19
+ end
20
+
21
+ def remove(member, min, max)
22
+ evalsha :remove, keys: ["my_store"], argv: [member, min, max]
23
+ end
24
+
25
+ def scenario(pairs)
26
+ pairs.each do |member, range|
27
+ add member.to_s, range.first, range.last
28
+ end
29
+ end
30
+
31
+ describe "general" do
32
+
33
+ it 'should catch invalid arguments' do
34
+ lambda { evalsha :remove }.should raise_error(Redis::CommandError, /wrong number of arguments/)
35
+ lambda { evalsha :remove, keys: ["one"] }.should raise_error(Redis::CommandError, /wrong number of arguments/)
36
+ lambda { evalsha :remove, keys: ["one"], argv: ["one", 2] }.should raise_error(Redis::CommandError, /wrong number of arguments/)
37
+ lambda { evalsha :remove, keys: ["one", "two"], argv: ["one", 2, 3] }.should raise_error(Redis::CommandError, /wrong number of arguments/)
38
+ end
39
+
40
+ it 'should catch non-numeric ranges' do
41
+ lambda { evalsha :remove, keys: ["one"], argv: ["one", "two", 3] }.should raise_error(Redis::CommandError, /not numeric or out of range/)
42
+ lambda { evalsha :remove, keys: ["one"], argv: ["one", 2, "three"] }.should raise_error(Redis::CommandError, /not numeric or out of range/)
43
+ lambda { evalsha :remove, keys: ["one"], argv: ["one", 3, 2] }.should raise_error(Redis::CommandError, /not numeric or out of range/)
44
+ end
45
+
46
+ end
47
+
48
+ describe "removing" do
49
+ before { add("A", 8, 17) }
50
+
51
+ it 'should return OK if successful' do
52
+ remove("A", 8, 17).should == "OK"
53
+ end
54
+
55
+ it 'should support negative ranges & zero bounds' do
56
+ scenario B: -5..0, C: 0..5
57
+
58
+ lambda {
59
+ remove("B", -5, 0)
60
+ remove("C", 0, 5)
61
+ }.should change { state }.
62
+ from(-5 => "B", 0 => "C", 5 => "", 8 => "A", 17 => "").
63
+ to(8 => "A", 17 => "")
64
+ end
65
+
66
+ it 'should clean up index' do
67
+ scenario B: 15..22, C: 15..23
68
+
69
+ lambda {
70
+ remove("B", 15, 22)
71
+ }.should change { brackets }.to ["8", "15", "17", "23"]
72
+
73
+ lambda {
74
+ remove("C", 15, 23)
75
+ }.should change { brackets }.to ["8", "17"]
76
+
77
+ lambda {
78
+ remove("A", 8, 17)
79
+ }.should change { brackets }.to []
80
+ end
81
+
82
+ end
83
+
84
+ describe "use cases" do
85
+
86
+ it "should remove from [A: 1-2, B: 3-4]" do
87
+ scenario A: 1..2, B: 3..4
88
+ lambda { remove("A", 1, 2) }.should change { state }.
89
+ from(1 => "A", 2 => "", 3 => "B", 4 => "").
90
+ to(3 => "B", 4 => "")
91
+ end
92
+
93
+ it "should remove from [A: 3-4, B: 1-2]" do
94
+ scenario A: 3..4, B: 1..2
95
+ lambda { remove("A", 3, 4) }.should change { state }.
96
+ from(1 => "B", 2 => "", 3 => "A", 4 => "").
97
+ to(1 => "B", 2 => "")
98
+ end
99
+
100
+ it "should remove from [A: 1-3, B: 2-4]" do
101
+ scenario A: 1..3, B: 2..4
102
+ lambda { remove("A", 1, 3) }.should change { state }.
103
+ from(1 => "A", 2 => "AB", 3 => "B", 4 => "").
104
+ to(2 => "B", 4 => "")
105
+ end
106
+
107
+ it "should remove from [A: 2-4, B: 1-3]" do
108
+ scenario A: 2..4, B: 1..3
109
+ lambda { remove("A", 2, 4) }.should change { state }.
110
+ from(1 => "B", 2 => "AB", 3 => "A", 4 => "").
111
+ to(1 => "B", 3 => "")
112
+ end
113
+
114
+ it "should remove from [A: 1-4, B: 2-3]" do
115
+ scenario A: 1..4, B: 2..3
116
+ lambda { remove("A", 1, 4) }.should change { state }.
117
+ from(1 => "A", 2 => "AB", 3 => "A", 4 => "").
118
+ to(2 => "B", 3 => "")
119
+ end
120
+
121
+ it "should remove from [A: 2-3, B: 1-4]" do
122
+ scenario A: 2..3, B: 1..4
123
+ lambda { remove("A", 2, 3) }.should change { state }.
124
+ from(1 => "B", 2 => "AB", 3 => "B", 4 => "").
125
+ to(1 => "B", 4 => "")
126
+ end
127
+
128
+ it "should remove from [A: 1-3, B: 3-4]" do
129
+ scenario A: 1..3, B: 3..4
130
+ lambda { remove("A", 1, 3) }.should change { state }.
131
+ from(1 => "A", 3 => "B", 4 => "").
132
+ to(3 => "B", 4 => "")
133
+ end
134
+
135
+ it "should remove from [A: 1-4, B: 3-4]" do
136
+ scenario A: 1..4, B: 3..4
137
+ lambda { remove("A", 1, 4) }.should change { state }.
138
+ from(1 => "A", 3 => "AB", 4 => "").
139
+ to(3 => "B", 4 => "")
140
+ end
141
+
142
+ it "should remove from [A: 3-4, B: 1-3]" do
143
+ scenario A: 3..4, B: 1..3
144
+ lambda { remove("A", 3, 4) }.should change { state }.
145
+ from(1 => "B", 3 => "A", 4 => "").
146
+ to(1 => "B", 3 => "")
147
+ end
148
+
149
+ it "should remove from [A: 3-4, B: 1-4]" do
150
+ scenario A: 3..4, B: 1..4
151
+ lambda { remove("A", 3, 4) }.should change { state }.
152
+ from(1 => "B", 3 => "AB", 4 => "").
153
+ to(1 => "B", 4 => "")
154
+ end
155
+
156
+ it "should remove from [A: 1-4, B: 1-2]" do
157
+ scenario A: 1..4, B: 1..2
158
+ lambda { remove("A", 1, 4) }.should change { state }.
159
+ from(1 => "AB", 2 => "A", 4 => "").
160
+ to(1 => "B", 2 => "")
161
+ end
162
+
163
+ it "should remove from [A: 2-4, B: 1-2]" do
164
+ scenario A: 2..4, B: 1..2
165
+ lambda { remove("A", 2, 4) }.should change { state }.
166
+ from(1 => "B", 2 => "A", 4 => "").
167
+ to(1 => "B", 2 => "")
168
+ end
169
+
170
+ it "should remove from [A: 1-4, B: 1-4]" do
171
+ scenario A: 1..4, B: 1..4
172
+ lambda { remove("A", 1, 4) }.should change { state }.
173
+ from(1 => "AB", 4 => "").
174
+ to(1 => "B", 4 => "")
175
+ end
176
+
177
+ it "should remove from [A: 1-4]" do
178
+ scenario A: 1..4
179
+ lambda { remove("A", 1, 4) }.should change { state }.
180
+ from(1 => "A", 4 => "").
181
+ to({})
182
+ end
183
+
184
+ end
185
+
186
+ end
@@ -0,0 +1,64 @@
1
+ ENV["REDIS_URL"] ||= 'redis://127.0.0.1:6379/9'
2
+
3
+ require 'bundler/setup'
4
+ require 'rspec'
5
+ require 'redis'
6
+
7
+ count = Redis.current.dbsize
8
+ unless count.zero?
9
+ STDERR.puts
10
+ STDERR.puts " !! WARNING!"
11
+ STDERR.puts " !! ========"
12
+ STDERR.puts " !!"
13
+ STDERR.puts " !! Your Redis (test) database at #{Redis.current.id} contains #{count} keys."
14
+ STDERR.puts " !! Running specs would wipe your database and result in potentail data loss."
15
+ STDERR.puts " !! Please specify a REDIS_URL environment variable to point to an empty database."
16
+ STDERR.puts
17
+ abort
18
+ end
19
+
20
+ version = Redis.current.info["redis_version"]
21
+ unless version >= "2.5"
22
+ STDERR.puts
23
+ STDERR.puts " !! WARNING!"
24
+ STDERR.puts " !! ========"
25
+ STDERR.puts " !!"
26
+ STDERR.puts " !! Your Redis (test) database at #{Redis.current.id} v#{version} is not suitable."
27
+ STDERR.puts " !! Please upgrade to Redis 2.6, or higher."
28
+ STDERR.puts
29
+ abort
30
+ end
31
+
32
+ module RSpec::RedisHelper
33
+ ROOT = File.expand_path("../../lib", __FILE__)
34
+
35
+ def redis
36
+ Redis.current
37
+ end
38
+
39
+ def evalsha(name, *args)
40
+ part = File.basename(File.dirname(self.class.file_path)).to_sym
41
+ redis.evalsha scripts[part][name], *args
42
+ end
43
+
44
+ def scripts
45
+ @scripts ||= Dir[File.join(ROOT, "**/*.lua")].inject({}) do |result, file|
46
+ part, name = file.sub(ROOT, "").sub(".lua", "").split("/").reject(&:empty?).map(&:to_sym)
47
+ result[part] ||= {}
48
+ result[part][name] = redis.script :load, File.read(file)
49
+ result
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ RSpec.configure do |config|
56
+
57
+ config.after do
58
+ redis.unwatch
59
+ redis.flushdb
60
+ end
61
+
62
+ config.include RSpec::RedisHelper
63
+
64
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_recipes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Black Square Media
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Require Redis 2.6.0 or higher
63
+ email: info@blacksquaremedia.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - .rspec
69
+ - Gemfile
70
+ - Gemfile.lock
71
+ - README.md
72
+ - Rakefile
73
+ - lib/range_lookup/README.md
74
+ - lib/range_lookup/add.lua
75
+ - lib/range_lookup/lookup.lua
76
+ - lib/range_lookup/remove.lua
77
+ - lib/range_lookup_x/README.md
78
+ - lib/range_lookup_x/add.lua
79
+ - lib/range_lookup_x/lookup.lua
80
+ - lib/range_lookup_x/remove.lua
81
+ - redis_recipes.gemspec
82
+ - spec/range_lookup/add_spec.rb
83
+ - spec/range_lookup/lookup_spec.rb
84
+ - spec/range_lookup/remove_spec.rb
85
+ - spec/range_lookup_x/add_spec.rb
86
+ - spec/range_lookup_x/lookup_spec.rb
87
+ - spec/range_lookup_x/remove_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: https://github.com/bsm/redis_recipes
90
+ licenses: []
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: 1.9.0
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: 1.3.6
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.24
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Redis LUA recipes.
113
+ test_files:
114
+ - spec/range_lookup/add_spec.rb
115
+ - spec/range_lookup/lookup_spec.rb
116
+ - spec/range_lookup/remove_spec.rb
117
+ - spec/range_lookup_x/add_spec.rb
118
+ - spec/range_lookup_x/lookup_spec.rb
119
+ - spec/range_lookup_x/remove_spec.rb
120
+ - spec/spec_helper.rb
121
+ has_rdoc: