swagger 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +62 -0
- data/README.rdoc +9 -7
- data/Rakefile +7 -43
- data/lib/resque_extension.rb +3 -3
- data/lib/resque_value.rb +0 -1
- data/lib/swagger.rb +5 -2
- data/lib/swagger/commands/helpers.rb +16 -0
- data/lib/swagger/commands/keys.rb +21 -0
- data/lib/swagger/commands/lists.rb +53 -0
- data/lib/swagger/commands/sets.rb +25 -0
- data/lib/swagger/commands/sorted_sets.rb +56 -0
- data/lib/swagger/commands/strings.rb +60 -0
- data/lib/swagger/redis.rb +26 -0
- data/lib/swagger/swallow.rb +14 -0
- data/lib/swagger/version.rb +7 -0
- data/spec/resque_extension_spec.rb +6 -7
- data/spec/spec_helper.rb +17 -14
- data/spec/support/helpers.rb +7 -0
- data/spec/swagger/commands/sorted_sets_spec.rb +175 -0
- data/spec/swagger/commands/strings_spec.rb +58 -0
- data/spec/swagger/redis_spec.rb +171 -0
- data/swagger.gemspec +12 -52
- metadata +74 -35
- data/VERSION +0 -1
- data/lib/redis_impersonator.rb +0 -129
- data/spec/redis_impersonator_spec.rb +0 -171
- data/spec/spec.opts +0 -1
@@ -0,0 +1,14 @@
|
|
1
|
+
module Swagger
|
2
|
+
module Swallow
|
3
|
+
|
4
|
+
def swallow(method, return_value = nil)
|
5
|
+
define_method(method) do |*args|
|
6
|
+
if defined?(LOGGER)
|
7
|
+
LOGGER.write "Swagger::Redis swallowed #{method} with the following arguments #{args.inspect}"
|
8
|
+
end
|
9
|
+
return_value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -1,12 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'Resque' do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
it 'swaps redis implementation with Swagger::Redis' do
|
5
|
+
Resque.redis.should be_a(Swagger::Redis)
|
6
|
+
end
|
7
|
+
|
9
8
|
it 'can connect to the database' do
|
10
9
|
Resque.should.respond_to?(:connect_to_database)
|
11
10
|
end
|
12
|
-
end
|
11
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,31 +1,34 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
3
4
|
|
4
|
-
|
5
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
require 'resque'
|
6
6
|
require 'swagger'
|
7
|
-
require 'spec'
|
8
|
-
require 'spec/autorun'
|
9
7
|
|
10
|
-
|
8
|
+
Dir['./spec/support/*.rb'].map {|f| require f }
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color_enabled = true
|
12
|
+
config.before { ResqueValue.delete_all }
|
16
13
|
end
|
17
14
|
|
18
15
|
Resque.swagger!
|
19
16
|
|
20
17
|
ActiveRecord::Base.establish_connection('adapter' => 'sqlite3', 'database' => 'test.db')
|
21
18
|
|
22
|
-
|
19
|
+
begin
|
20
|
+
ActiveRecord::Base.connection.drop_table :resque_values
|
21
|
+
rescue
|
22
|
+
puts "unable to drop resque_values, probably because it has not been created yet"
|
23
|
+
end
|
24
|
+
|
23
25
|
ActiveRecord::Base.connection.create_table :resque_values do |table|
|
24
26
|
table.column :key, :string
|
25
27
|
table.column :key_type, :string
|
26
|
-
table.column :
|
28
|
+
table.column :score, :integer
|
29
|
+
table.column :value, :text
|
30
|
+
table.timestamps
|
27
31
|
end
|
28
32
|
|
29
33
|
ActiveRecord::Base.connection.add_index :resque_values, :key
|
30
|
-
ActiveRecord::Base.connection.add_index :resque_values, [:key, :key_type]
|
31
|
-
|
34
|
+
ActiveRecord::Base.connection.add_index :resque_values, [:key, :key_type]
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Swagger
|
4
|
+
describe Redis, 'sorted sets' do
|
5
|
+
|
6
|
+
describe '#zadd' do
|
7
|
+
it 'adds a new record' do
|
8
|
+
expect_count_to_change { add_record }
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'sets the record attributes correctly' do
|
12
|
+
record = add_record
|
13
|
+
record.key.should eq('key')
|
14
|
+
record.score.should eq(100)
|
15
|
+
record.value.should eq('value')
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with a record added' do
|
19
|
+
let!(:record) { add_record }
|
20
|
+
|
21
|
+
it 'does not add a new record if the values are the same' do
|
22
|
+
expect_count_to_not_change { add_record }
|
23
|
+
end
|
24
|
+
|
25
|
+
it "updates the record's score if it's different" do
|
26
|
+
add_record(:score => 500)
|
27
|
+
record.reload.score.should eq(500)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'adds another record if the key is different' do
|
31
|
+
expect_count_to_change { add_record(:key => 'key2') }
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'adds another record if the value is different' do
|
35
|
+
expect_count_to_change { add_record(:value => 'value2') }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#zrem' do
|
41
|
+
context 'with a record added' do
|
42
|
+
let!(:record) { add_record(:key => 'k', :value => 'v') }
|
43
|
+
|
44
|
+
it 'deletes the record' do
|
45
|
+
expect_count_to_change(-1) { subject.zrem(:k, 'v') }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#zcard' do
|
51
|
+
context 'with 3 records added' do
|
52
|
+
before do
|
53
|
+
add_record(:score => '1', :value => '#1')
|
54
|
+
add_record(:score => '3', :value => '#3')
|
55
|
+
add_record(:score => '2', :value => '#2')
|
56
|
+
end
|
57
|
+
|
58
|
+
specify { subject.zcard(:key).should eq(3) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#zrange' do
|
63
|
+
context 'with 5 records added' do
|
64
|
+
before do
|
65
|
+
add_record(:score => 1, :value => '#1')
|
66
|
+
add_record(:score => 3, :value => '#3')
|
67
|
+
add_record(:score => 2, :value => '#2')
|
68
|
+
add_record(:score => 5, :value => '#5')
|
69
|
+
add_record(:score => 4, :value => '#4')
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'given the entire range' do
|
73
|
+
let(:values) { subject.zrange(:key, 0, -1) }
|
74
|
+
|
75
|
+
specify { values.should have(5).values }
|
76
|
+
|
77
|
+
it 'sorts the values by score' do
|
78
|
+
values[0].should eq('#1')
|
79
|
+
values[1].should eq('#2')
|
80
|
+
values[2].should eq('#3')
|
81
|
+
values[3].should eq('#4')
|
82
|
+
values[4].should eq('#5')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'given a range of 1 to 3' do
|
87
|
+
let(:values) { subject.zrange(:key, 1, 3) }
|
88
|
+
|
89
|
+
specify { values.should have(3).values }
|
90
|
+
|
91
|
+
it 'sorts the values by score' do
|
92
|
+
values[0].should eql('#2')
|
93
|
+
values[1].should eql('#3')
|
94
|
+
values[2].should eql('#4')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#zrangebyscore' do
|
101
|
+
context 'with 5 records added' do
|
102
|
+
before do
|
103
|
+
add_record(:score => 1, :value => '#1')
|
104
|
+
add_record(:score => 3, :value => '#3')
|
105
|
+
add_record(:score => 2, :value => '#2')
|
106
|
+
add_record(:score => 5, :value => '#5')
|
107
|
+
add_record(:score => 4, :value => '#4')
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'given the entire range' do
|
111
|
+
let(:values) { subject.zrangebyscore(:key, 1, 5) }
|
112
|
+
|
113
|
+
specify { values.should have(5).values }
|
114
|
+
|
115
|
+
it 'sorts the values by score' do
|
116
|
+
values[0].should eq('#1')
|
117
|
+
values[1].should eq('#2')
|
118
|
+
values[2].should eq('#3')
|
119
|
+
values[3].should eq('#4')
|
120
|
+
values[4].should eq('#5')
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'and :limit option' do
|
124
|
+
context 'with 1 offset and 3 count' do
|
125
|
+
let(:values) do
|
126
|
+
subject.zrangebyscore(:key, 1, 5, :limit => [1, 3])
|
127
|
+
end
|
128
|
+
|
129
|
+
specify { values.should have(3).values }
|
130
|
+
|
131
|
+
it 'sorts the values by score' do
|
132
|
+
values[0].should eq('#2')
|
133
|
+
values[1].should eq('#3')
|
134
|
+
values[2].should eq('#4')
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'given -inf (lowest score) and 3' do
|
141
|
+
let(:values) { subject.zrangebyscore(:key, '-inf', 3) }
|
142
|
+
|
143
|
+
specify { values.should have(3).values }
|
144
|
+
|
145
|
+
it 'sorts the values by score' do
|
146
|
+
values[0].should eq('#1')
|
147
|
+
values[1].should eq('#2')
|
148
|
+
values[2].should eq('#3')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'given 3 and +inf (highest score)' do
|
153
|
+
let(:values) { subject.zrangebyscore(:key, 3, '+inf') }
|
154
|
+
|
155
|
+
specify { values.should have(3).values }
|
156
|
+
|
157
|
+
it 'sorts the values by score' do
|
158
|
+
values[0].should eq('#3')
|
159
|
+
values[1].should eq('#4')
|
160
|
+
values[2].should eq('#5')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_record(args = {})
|
167
|
+
key = args.fetch(:key) { 'key' }
|
168
|
+
score = args.fetch(:score) { 100 }
|
169
|
+
value = args.fetch(:value) { 'value' }
|
170
|
+
|
171
|
+
subject.zadd(key, score, value)
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Swagger
|
4
|
+
describe Redis, 'strings' do
|
5
|
+
|
6
|
+
describe '#setnx' do
|
7
|
+
it 'adds a new record' do
|
8
|
+
expect_count_to_change { add_record }
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'sets the record attributes correctly' do
|
12
|
+
record = add_record
|
13
|
+
record.key.should eq('key')
|
14
|
+
record.value.should eq('value')
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with a record added' do
|
18
|
+
let!(:record) { add_record }
|
19
|
+
|
20
|
+
it 'does not add a new record if the values are the same' do
|
21
|
+
expect_count_to_not_change { add_record }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "does not update the record's value if it's different" do
|
25
|
+
add_record(:value => 'foo')
|
26
|
+
record.reload.value.should eq('value')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#incr' do
|
32
|
+
let!(:record) { add_record(:value => '1') }
|
33
|
+
|
34
|
+
it "increments a record's value by one" do
|
35
|
+
subject.incr('key')
|
36
|
+
record.reload.value.should eq('2')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#decr' do
|
41
|
+
let!(:record) { add_record(:value => '1') }
|
42
|
+
|
43
|
+
it "decrements a record's value by one" do
|
44
|
+
subject.decr('key')
|
45
|
+
record.reload.value.should eq('0')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_record(args = {})
|
50
|
+
key = args.fetch(:key) { 'key' }
|
51
|
+
value = args.fetch(:value) { 'value' }
|
52
|
+
|
53
|
+
subject.setnx(key, value)
|
54
|
+
ResqueValue.find_by_key_and_value(key, value)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Swagger
|
4
|
+
describe Redis do
|
5
|
+
it 'responds to info' do
|
6
|
+
subject.info.should_not be_nil
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'swallows calls to namespace' do
|
10
|
+
lambda{subject.namespace = 'value'}.should_not raise_error
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'manipulating key values' do
|
14
|
+
it 'it can get key values' do
|
15
|
+
subject.set('key', 'value').should == 'value'
|
16
|
+
subject.get('key').should == 'value'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'can create new key values' do
|
20
|
+
subject.set('key', 'value').should == 'value'
|
21
|
+
ResqueValue.first.value.should == 'value'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can delete key values' do
|
25
|
+
subject.set('key', 'value').should == 'value'
|
26
|
+
subject.del('key')
|
27
|
+
subject.get('key').should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can get multiple values by keys' do
|
31
|
+
subject.set('key-1', 'one')
|
32
|
+
subject.set('key-2', 'two')
|
33
|
+
subject.mapped_mget('key-1', 'key-2')['key-1'].should == 'one'
|
34
|
+
subject.mapped_mget('key-1', 'key-2')['key-2'].should == 'two'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'always returns all keys when pattern is *' do
|
38
|
+
subject.set('key-1', 'one')
|
39
|
+
subject.set('key-2', 'two')
|
40
|
+
subject.keys('*').should include('key-1', 'key-2')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'raises error when pattern is not *' do
|
44
|
+
lambda{subject.keys('something not *')}.should raise_error
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'managing workes in a set' do
|
49
|
+
it 'can add workers to the queue' do
|
50
|
+
worker = Resque::Worker.new(queues = ['queue1'])
|
51
|
+
subject.sadd(:workers, worker)
|
52
|
+
ResqueValue.first.value.should == worker.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns all values in the workers set' do
|
56
|
+
worker = Resque::Worker.new(queues = ['queue1'])
|
57
|
+
subject.sadd(:workers, worker)
|
58
|
+
subject.smembers(:workers).first.should == worker.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'removes a worker from the workers set by name' do
|
62
|
+
worker = Resque::Worker.new(queues = ['queue1'])
|
63
|
+
subject.sadd(:workers, worker)
|
64
|
+
subject.srem(:workers, worker)
|
65
|
+
subject.smembers(:workers).should be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should only add a value to a set once' do
|
69
|
+
subject.sadd(:test, 'one')
|
70
|
+
subject.sadd(:test, 'one')
|
71
|
+
subject.smembers(:test).size.should == 1
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'indicates when worker is in the workers set' do
|
75
|
+
worker = Resque::Worker.new(queues = ['queue1'])
|
76
|
+
|
77
|
+
subject.sismember(:workers, worker).should == false
|
78
|
+
subject.sadd(:workers, worker)
|
79
|
+
subject.sismember(:workers, worker).should == true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'can delete a whole set by name' do
|
83
|
+
subject.sadd(:test, 'one')
|
84
|
+
subject.sadd(:test, 'two')
|
85
|
+
subject.del(:test)
|
86
|
+
subject.smembers(:test).should be_empty
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'working with lists' do
|
91
|
+
it 'should return nil if no items on a queue' do
|
92
|
+
subject.lpop('some_queue').should be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'ingores index and adds item to list' do
|
96
|
+
subject.lset('some_queue', 88, 'value')
|
97
|
+
subject.llen('some_queue').should == 1
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should add item to queue and then pop it back off' do
|
101
|
+
subject.rpush('some_queue', 'value')
|
102
|
+
subject.lpop('some_queue').should == 'value'
|
103
|
+
subject.lpop('some_queue').should be_nil
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should tell you how many items are in a list' do
|
107
|
+
subject.rpush('some_queue', 'one')
|
108
|
+
subject.rpush('some_queue', 'two')
|
109
|
+
subject.llen('some_queue').should == 2
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should be able to paginate through a list' do
|
113
|
+
subject.rpush('some_queue', 'one')
|
114
|
+
subject.rpush('some_queue', 'two')
|
115
|
+
subject.rpush('some_queue', 'three')
|
116
|
+
subject.lrange('some_queue', 0, 1).first.should == 'one'
|
117
|
+
subject.lrange('some_queue', 2, 3).first.should == 'three'
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should get all results if you pass -1 to lrange' do
|
121
|
+
subject.rpush('some_queue', 'one')
|
122
|
+
subject.rpush('some_queue', 'two')
|
123
|
+
subject.rpush('some_queue', 'three')
|
124
|
+
subject.lrange('some_queue', 0, -1).should include('one', 'two', 'three')
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should remove items from queue' do
|
128
|
+
subject.rpush('some_queue', 'one')
|
129
|
+
subject.rpush('some_queue', 'two')
|
130
|
+
subject.rpush('some_queue', 'two')
|
131
|
+
subject.lrem('some_queue', 0, 'two').should == 2
|
132
|
+
subject.lrange('some_queue', 0, -1).should include('one')
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should trim according to the specifed start and end" do
|
136
|
+
1.upto(6){|i| subject.rpush('some_queue', i)}
|
137
|
+
subject.ltrim('some_queue', 1, 3)
|
138
|
+
subject.llen('some_queue').should == 3
|
139
|
+
subject.lrange('some_queue', 0, 2).should == ["2","3","4"]
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should not affect other keys when trimming" do
|
143
|
+
1.upto(3){|i| subject.rpush('some_queue', i)}
|
144
|
+
subject.set('something_else', 'independent value')
|
145
|
+
subject.ltrim('some_queue', 0, 0)
|
146
|
+
subject.get('something_else').should == 'independent value'
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should get a range of values" do
|
150
|
+
1.upto(6){|i| subject.rpush('some_queue', i)}
|
151
|
+
subject.lrange('some_queue', 0, 5).should == ['1','2','3','4','5','6']
|
152
|
+
subject.lrange('some_queue', 1, 3).should == ['2','3','4']
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should increment a value' do
|
157
|
+
subject.incrby('something', 2)
|
158
|
+
subject.get('something').should == '2'
|
159
|
+
subject.incrby('something', 1)
|
160
|
+
subject.get('something').should == '3'
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should decrement a value' do
|
164
|
+
subject.incrby('something', 2)
|
165
|
+
subject.get('something').should == '2'
|
166
|
+
subject.decrby('something', 1)
|
167
|
+
subject.get('something').should == '1'
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|