worker_roulette 0.1.7 → 0.1.9

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.
@@ -1,184 +1,162 @@
1
1
  require "spec_helper"
2
+ module WorkerRoulette
3
+ describe WorkerRoulette do
4
+ let(:sender) {'katie_80'}
5
+ let(:work_orders) {["hello", "foreman"]}
6
+ let(:default_headers) {Hash['headers' => {'sender' => sender}]}
7
+ let(:hello_work_order) {Hash['payload' => "hello"]}
8
+ let(:foreman_work_order) {Hash['payload' => "foreman"]}
9
+ let(:work_orders_with_headers) {default_headers.merge({'payload' => work_orders})}
10
+ let(:jsonized_work_orders_with_headers) {[WorkerRoulette.dump(work_orders_with_headers)]}
11
+ let(:worker_roulette) { WorkerRoulette.start }
2
12
 
3
- describe WorkerRoulette do
4
- let(:sender) {'katie_80'}
5
- let(:work_orders) {["hello", "foreman"]}
6
- let(:default_headers) {Hash['headers' => {'sender' => sender}]}
7
- let(:hello_work_order) {Hash['payload' => "hello"]}
8
- let(:foreman_work_order) {Hash['payload' => "foreman"]}
9
- let(:work_orders_with_headers) {default_headers.merge({'payload' => work_orders})}
10
- let(:jsonized_work_orders_with_headers) {[WorkerRoulette.dump(work_orders_with_headers)]}
13
+ let(:redis) {Redis.new(worker_roulette.redis_config)}
11
14
 
12
- let(:redis) {Redis.new(WorkerRoulette.redis_config)}
13
-
14
- before do
15
- WorkerRoulette.start
16
- end
17
-
18
- it "should exist" do
19
- expect(WorkerRoulette).not_to be_nil
20
- end
21
-
22
- context Foreman do
23
- let(:subject) {WorkerRoulette.foreman(sender)}
24
-
25
- it "should be working on behalf of a sender" do
26
- expect(subject.sender).to eq(sender)
15
+ it "should exist" do
16
+ expect(worker_roulette).to be_instance_of(WorkerRoulette)
27
17
  end
28
18
 
29
- it "should enqueue_work_order two work_orders in the sender's slot in the switchboard" do
30
- subject.enqueue_work_order(work_orders.first) {}
31
- subject.enqueue_work_order(work_orders.last) {}
32
- expect(redis.lrange(sender, 0, -1)).to eq(work_orders.map {|m| WorkerRoulette.dump(default_headers.merge({'payload' => m})) })
33
- end
34
-
35
- it "should enqueue_work_order an array of work_orders without headers in the sender's slot in the switchboard" do
36
- subject.enqueue_work_order_without_headers(work_orders)
37
- expect(redis.lrange(sender, 0, -1)).to eq([WorkerRoulette.dump(work_orders)])
38
- end
19
+ context Foreman do
20
+ let(:subject) {worker_roulette.foreman(sender)}
39
21
 
40
- it "should enqueue_work_order an array of work_orders with default headers in the sender's slot in the switchboard" do
41
- subject.enqueue_work_order(work_orders)
42
- expect(redis.lrange(sender, 0, -1)).to eq(jsonized_work_orders_with_headers)
43
- end
22
+ it "should be working on behalf of a sender" do
23
+ expect(subject.sender).to eq(sender)
24
+ end
44
25
 
45
- it "should enqueue_work_order an array of work_orders with additional headers in the sender's slot in the switchboard" do
46
- extra_headers = {'foo' => 'bars'}
47
- subject.enqueue_work_order(work_orders, extra_headers)
48
- work_orders_with_headers['headers'].merge!(extra_headers)
49
- expect(redis.lrange(sender, 0, -1)).to eq([WorkerRoulette.dump(work_orders_with_headers)])
50
- end
26
+ it "should enqueue_work_order two work_orders in the sender's work queue" do
27
+ subject.enqueue_work_order(work_orders.first) {}
28
+ subject.enqueue_work_order(work_orders.last) {}
29
+ expect(redis.lrange(sender, 0, -1)).to eq(work_orders.map {|m| WorkerRoulette.dump(default_headers.merge({'payload' => m})) })
30
+ end
51
31
 
52
- it "should post the sender's id to the job board with an order number" do
53
- subject.enqueue_work_order(work_orders.first)
54
- WorkerRoulette.foreman('other_forman').enqueue_work_order(work_orders.last)
55
- expect(redis.zrange(subject.job_board_key, 0, -1, with_scores: true)).to eq([[sender, 1.0], ["other_forman", 2.0]])
56
- end
32
+ it "should enqueue_work_order an array of work_orders without headers in the sender's work queue" do
33
+ subject.enqueue_work_order_without_headers(work_orders)
34
+ expect(redis.lrange(sender, 0, -1)).to eq([WorkerRoulette.dump(work_orders)])
35
+ end
57
36
 
58
- it "should generate a monotically increasing score for senders not on the job board, but not for senders already there" do
59
- other_forman = WorkerRoulette.foreman('other_forman')
60
- expect(redis.get(subject.counter_key)).to be_nil
61
- subject.enqueue_work_order(work_orders.first)
62
- expect(redis.get(subject.counter_key)).to eq("1")
63
- subject.enqueue_work_order(work_orders.last)
64
- expect(redis.get(subject.counter_key)).to eq("1")
65
- other_forman.enqueue_work_order(work_orders.last)
66
- expect(redis.get(other_forman.counter_key)).to eq("2")
67
- end
37
+ it "should enqueue_work_order an array of work_orders with default headers in the sender's work queue" do
38
+ subject.enqueue_work_order(work_orders)
39
+ expect(redis.lrange(sender, 0, -1)).to eq(jsonized_work_orders_with_headers)
40
+ end
68
41
 
69
- it "should publish a notification that a new job is ready" do
70
- result = nil
71
- redis_tradesman = Redis.new
72
- redis_tradesman.subscribe(WorkerRoulette::JOB_NOTIFICATIONS) do |on|
73
- on.subscribe do |channel, subscription|
74
- subject.enqueue_work_order(work_orders)
75
- end
42
+ it "should enqueue_work_order an array of work_orders with additional headers in the sender's work queue" do
43
+ extra_headers = {'foo' => 'bars'}
44
+ subject.enqueue_work_order(work_orders, extra_headers)
45
+ work_orders_with_headers['headers'].merge!(extra_headers)
46
+ expect(redis.lrange(sender, 0, -1)).to eq([WorkerRoulette.dump(work_orders_with_headers)])
47
+ end
76
48
 
77
- on.message do |channel, notification|
78
- result = notification
79
- redis_tradesman.unsubscribe(WorkerRoulette::JOB_NOTIFICATIONS)
80
- end
49
+ it "should post the sender's id to the job board with an order number" do
50
+ subject.enqueue_work_order(work_orders.first)
51
+ worker_roulette.foreman('other_forman').enqueue_work_order(work_orders.last)
52
+ expect(redis.zrange(subject.job_board_key, 0, -1, with_scores: true)).to eq([[sender, 1.0], ["other_forman", 2.0]])
81
53
  end
82
54
 
83
- expect(result).to eq(WorkerRoulette::JOB_NOTIFICATIONS)
55
+ it "should generate a monotically increasing score for senders not on the job board, but not for senders already there" do
56
+ other_forman = worker_roulette.foreman('other_forman')
57
+ expect(redis.get(subject.counter_key)).to be_nil
58
+ subject.enqueue_work_order(work_orders.first)
59
+ expect(redis.get(subject.counter_key)).to eq("1")
60
+ subject.enqueue_work_order(work_orders.last)
61
+ expect(redis.get(subject.counter_key)).to eq("1")
62
+ other_forman.enqueue_work_order(work_orders.last)
63
+ expect(redis.get(other_forman.counter_key)).to eq("2")
64
+ end
84
65
  end
85
- end
86
66
 
87
- context Tradesman do
88
- let(:foreman) {WorkerRoulette.foreman(sender)}
89
- let(:subject) {WorkerRoulette.tradesman}
67
+ context Tradesman do
68
+ let(:foreman) {worker_roulette.foreman(sender)}
69
+ let(:subject) {worker_roulette.tradesman}
90
70
 
91
- before do
92
- foreman.enqueue_work_order(work_orders)
93
- end
71
+ before do
72
+ foreman.enqueue_work_order(work_orders)
73
+ end
94
74
 
95
- it "should have a last sender if it found messages" do
96
- expect(subject.work_orders!.length).to eq(1)
97
- expect(subject.last_sender).to eq(sender)
98
- end
75
+ it "should have a last sender if it found messages" do
76
+ expect(subject.work_orders!.length).to eq(1)
77
+ expect(subject.last_sender).to eq(sender)
78
+ end
99
79
 
100
- it "should not have a last sender if it found no messages" do
101
- expect(subject.work_orders!.length).to eq(1)
102
- expect(subject.work_orders!.length).to eq(0)
103
- expect(subject.last_sender).to be_nil
104
- end
80
+ it "should not have a last sender if it found no messages" do
81
+ expect(subject.work_orders!.length).to eq(1)
82
+ expect(subject.work_orders!.length).to eq(0)
83
+ expect(subject.last_sender).to be_nil
84
+ end
105
85
 
106
- it "should drain one set of work_orders from the sender's slot in the switchboard" do
107
- expect(subject.work_orders!).to eq([work_orders_with_headers])
108
- expect(subject.work_orders!).to be_empty
109
- expect(subject.work_orders!).to be_empty #does not throw an error if queue is already empty
110
- end
86
+ it "should drain one set of work_orders from the sender's work queue" do
87
+ expect(subject.work_orders!).to eq([work_orders_with_headers])
88
+ expect(subject.work_orders!).to be_empty
89
+ expect(subject.work_orders!).to be_empty #does not throw an error if queue is already empty
90
+ end
111
91
 
112
- it "should drain all the work_orders from the sender's slot in the switchboard" do
113
- foreman.enqueue_work_order(work_orders)
114
- expect(subject.work_orders!).to eq([work_orders_with_headers, work_orders_with_headers])
115
- expect(subject.work_orders!).to be_empty
116
- expect(subject.work_orders!).to be_empty #does not throw an error if queue is already empty
117
- end
92
+ it "should drain all the work_orders from the sender's work queue" do
93
+ foreman.enqueue_work_order(work_orders)
94
+ expect(subject.work_orders!).to eq([work_orders_with_headers, work_orders_with_headers])
95
+ expect(subject.work_orders!).to be_empty
96
+ expect(subject.work_orders!).to be_empty #does not throw an error if queue is already empty
97
+ end
118
98
 
119
- it "should take the oldest sender off the job board (FIFO)" do
120
- oldest_sender = sender.to_s
121
- most_recent_sender = 'most_recent_sender'
122
- most_recent_foreman = WorkerRoulette.foreman(most_recent_sender)
123
- most_recent_foreman.enqueue_work_order(work_orders)
124
- expect(redis.zrange(subject.job_board_key, 0, -1)).to eq([oldest_sender, most_recent_sender])
125
- subject.work_orders!
126
- expect(redis.zrange(subject.job_board_key, 0, -1)).to eq([most_recent_sender])
127
- end
99
+ it "should take the oldest sender off the job board (FIFO)" do
100
+ oldest_sender = sender.to_s
101
+ most_recent_sender = 'most_recent_sender'
102
+ most_recent_foreman = worker_roulette.foreman(most_recent_sender)
103
+ most_recent_foreman.enqueue_work_order(work_orders)
104
+ expect(redis.zrange(subject.job_board_key, 0, -1)).to eq([oldest_sender, most_recent_sender])
105
+ subject.work_orders!
106
+ expect(redis.zrange(subject.job_board_key, 0, -1)).to eq([most_recent_sender])
107
+ end
128
108
 
129
- it "should get the work_orders from the next queue when a new job is ready" do
130
- subject.work_orders!
131
- expect(subject).to receive(:work_orders!).twice.and_call_original
109
+ it "should get the work_orders from the next queue when a new job is ready, then poll for new work" do
110
+ subject.work_orders!
111
+ expect(subject).to receive(:work_orders!).and_call_original
112
+ expect(subject.timer).to receive(:after)
132
113
 
133
- publisher = -> {foreman.enqueue_work_order(work_orders); subject.unsubscribe}
114
+ foreman.enqueue_work_order(work_orders)
134
115
 
135
- subject.wait_for_work_orders(publisher) do |redis_work_orders|
136
- expect(redis_work_orders).to eq([work_orders_with_headers])
137
- expect(subject.last_sender).to be_nil
116
+ subject.wait_for_work_orders do |redis_work_orders|
117
+ expect(redis_work_orders).to eq([work_orders_with_headers])
118
+ expect(subject.last_sender).to eq('katie_80')
119
+ end
138
120
  end
139
- end
140
-
141
- it "should publish and subscribe on custom channels" do
142
- tradesman = WorkerRoulette.tradesman('good_channel')
143
- expect(tradesman).to receive(:work_orders!).twice.and_call_original
144
121
 
145
- good_foreman = WorkerRoulette.foreman('foreman', 'good_channel')
146
- bad_foreman = WorkerRoulette.foreman('foreman', 'bad_channel')
122
+ it "should publish and subscribe on custom channels" do
123
+ tradesman = worker_roulette.tradesman('good_channel')
124
+ expect(tradesman).to receive(:work_orders!).and_call_original
147
125
 
126
+ good_foreman = worker_roulette.foreman('foreman', 'good_channel')
127
+ bad_foreman = worker_roulette.foreman('foreman', 'bad_channel')
148
128
 
149
- publish = -> do
150
129
  good_foreman.enqueue_work_order('some old fashion work')
151
130
  bad_foreman.enqueue_work_order('evil biddings you should not carry out')
152
- tradesman.unsubscribe
153
- end
154
131
 
155
- tradesman.wait_for_work_orders(publish) do |work|
156
- expect(work.to_s).to match("some old fashion work")
157
- expect(work.to_s).not_to match("evil")
158
- expect(tradesman.last_sender).to be_nil
132
+ tradesman.wait_for_work_orders do |work|
133
+ expect(work.to_s).to match("some old fashion work")
134
+ expect(work.to_s).not_to match("evil")
135
+ expect(tradesman.last_sender).to eq('foreman')
136
+ end
159
137
  end
160
- end
161
138
 
162
- context "Failure" do
163
- it "should not put the sender_id and work_orders back if processing fails bc new work_orders may have been processed while that process failed" do; end
164
- end
139
+ context "Failure" do
140
+ it "should not put the sender_id and work_orders back if processing fails bc new work_orders may have been processed while that process failed" do; end
141
+ end
165
142
 
166
- context "Concurrent Access" do
167
- it "should pool its connections" do
168
- Array.new(100) do
169
- Thread.new {WorkerRoulette.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}}
170
- end.each(&:join)
171
- WorkerRoulette.tradesman_connection_pool.with do |pooled_redis|
172
- expect(pooled_redis.info["connected_clients"].to_i).to be > (WorkerRoulette.pool_size)
143
+ context "Concurrent Access" do
144
+ it "should pool its connections" do
145
+ Array.new(100) do
146
+ Thread.new {worker_roulette.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}}
147
+ end.each(&:join)
148
+ worker_roulette.tradesman_connection_pool.with do |pooled_redis|
149
+ expect(pooled_redis.info["connected_clients"].to_i).to be > (worker_roulette.pool_size)
150
+ end
173
151
  end
174
- end
175
152
 
176
- #This may be fixed soon (10 Feb 2014 - https://github.com/redis/redis-rb/pull/389 and https://github.com/redis/redis-rb/issues/364)
177
- it "should not be fork() proof -- forking reconnects need to be handled in the calling code (until redis gem is udpated, then we should be fork-proof)" do
178
- WorkerRoulette.start
179
- WorkerRoulette.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}
180
- fork do
181
- expect {WorkerRoulette.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}}.to raise_error(Redis::InheritedError)
153
+ #This may be fixed soon (10 Feb 2014 - https://github.com/redis/redis-rb/pull/389 and https://github.com/redis/redis-rb/issues/364)
154
+ it "should not be fork() proof -- forking reconnects need to be handled in the calling code (until redis gem is udpated, then we should be fork-proof)" do
155
+ instance = WorkerRoulette.start
156
+ instance.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}
157
+ fork do
158
+ expect {instance.tradesman_connection_pool.with {|pooled_redis| pooled_redis.get("foo")}}.to raise_error(Redis::InheritedError)
159
+ end
182
160
  end
183
161
  end
184
162
  end
data/spec/spec_helper.rb CHANGED
@@ -1,17 +1,18 @@
1
- require 'worker_roulette'
2
- require 'evented-spec'
3
- require 'rspec'
4
- require 'pry'
1
+ module WorkerRoulette
2
+ require 'worker_roulette'
3
+ require 'evented-spec'
4
+ require 'rspec'
5
+ require 'pry'
5
6
 
6
- require File.expand_path(File.join("..", "..", "lib", "worker_roulette.rb"), __FILE__)
7
- include WorkerRoulette
7
+ require File.expand_path(File.join("..", "..", "lib", "worker_roulette.rb"), __FILE__)
8
8
 
9
- Dir[File.join(File.dirname(__FILE__), 'helpers', '**/*.rb')].sort.each { |file| require file.gsub(".rb", "")}
9
+ Dir[File.join(File.dirname(__FILE__), 'helpers', '**/*.rb')].sort.each { |file| require file.gsub(".rb", "")}
10
10
 
11
- EM::Hiredis.reconnect_timeout = 0.01
11
+ EM::Hiredis.reconnect_timeout = 0.01
12
12
 
13
- RSpec.configure do |c|
14
- c.after(:each) do
15
- Redis.new(WorkerRoulette.redis_config).flushdb
13
+ RSpec.configure do |c|
14
+ c.after(:each) do
15
+ Redis.new(WorkerRoulette.start.redis_config).flushdb
16
+ end
16
17
  end
17
- end
18
+ end
@@ -1,23 +1,24 @@
1
1
  require 'spec_helper'
2
2
  module WorkerRoulette
3
- describe "Evented Read Lock" do
3
+ describe "Evented Read Lock" do
4
4
  include EventedSpec::EMSpec
5
5
 
6
- let(:redis) {Redis.new(WorkerRoulette.redis_config)}
6
+ let(:redis) {Redis.new(WorkerRoulette.start.redis_config)}
7
7
  let(:sender) {'katie_80'}
8
8
  let(:work_orders) {"hellot"}
9
9
  let(:lock_key) {"L*:#{sender}"}
10
10
  let(:default_headers) {Hash['headers' => {'sender' => sender}]}
11
11
  let(:work_orders_with_headers) {default_headers.merge({'payload' => work_orders})}
12
12
  let(:jsonized_work_orders_with_headers) {[WorkerRoulette.dump(work_orders_with_headers)]}
13
- let(:foreman) {WorkerRoulette.foreman(sender)}
14
- let(:number_two) {WorkerRoulette.foreman('number_two')}
15
- let(:subject) {WorkerRoulette.tradesman}
16
- let(:subject_two) {WorkerRoulette.tradesman}
13
+ let(:worker_roulette) { WorkerRoulette.start(evented: true) }
14
+ let(:foreman) {worker_roulette.foreman(sender)}
15
+ let(:number_two) {worker_roulette.foreman('number_two')}
16
+ let(:subject) {worker_roulette.tradesman}
17
+ let(:subject_two) {worker_roulette.tradesman}
18
+ let(:lua) { Lua.new(worker_roulette.tradesman_connection_pool) }
17
19
 
18
20
  em_before do
19
- WorkerRoulette.start(evented: true)
20
- Lua.clear_cache!
21
+ lua.clear_cache!
21
22
  redis.script(:flush)
22
23
  redis.flushdb
23
24
  end
@@ -29,9 +30,9 @@ module WorkerRoulette
29
30
  end
30
31
  end
31
32
 
32
- it "should set the lock to expire in 1 second" do
33
+ it "should set the lock to expire in 3 seconds" do
33
34
  evented_readlock_preconditions do
34
- expect(redis.ttl(lock_key)).to eq(1)
35
+ expect(redis.ttl(lock_key)).to eq(3)
35
36
  done
36
37
  end
37
38
  end
@@ -45,13 +46,13 @@ module WorkerRoulette
45
46
  end
46
47
 
47
48
  it "should read from the first available queue that is not locked" do
48
- evented_readlock_preconditions do
49
- foreman.enqueue_work_order(work_orders) do #locked
50
- number_two.enqueue_work_order(work_orders) do #unlocked
49
+ evented_readlock_preconditions do
50
+ foreman.enqueue_work_order(work_orders) do #locked
51
+ number_two.enqueue_work_order(work_orders) do #unlocked
51
52
  subject_two.work_orders!{|work| expect(work.first['headers']['sender']).to eq('number_two'); done}
52
53
  end
53
- end
54
- end
54
+ end
55
+ end
55
56
  end
56
57
 
57
58
  it "should release its last lock when it asks for its next work order from another sender" do
@@ -94,13 +95,13 @@ module WorkerRoulette
94
95
  end
95
96
  end
96
97
  end
97
- end
98
98
 
99
- def evented_readlock_preconditions(&spec_block)
100
- foreman.enqueue_work_order(work_orders) do
101
- subject.work_orders! do |work|
102
- expect(work).to eq([work_orders_with_headers])
103
- spec_block.call
99
+ def evented_readlock_preconditions(&spec_block)
100
+ foreman.enqueue_work_order(work_orders) do
101
+ subject.work_orders! do |work|
102
+ expect(work).to eq([work_orders_with_headers])
103
+ spec_block.call
104
+ end
104
105
  end
105
106
  end
106
107
  end
@@ -2,23 +2,21 @@ require 'spec_helper'
2
2
  module WorkerRoulette
3
3
  describe Lua do
4
4
  include EventedSpec::EMSpec
5
- let(:redis) {Redis.new(WorkerRoulette.redis_config)}
6
-
7
- em_before do
8
- WorkerRoulette.start(evented: true)
9
- end
5
+ let(:worker_roulette) {WorkerRoulette.start(evented: true)}
6
+ let(:lua) { Lua.new(worker_roulette.tradesman_connection_pool) }
7
+ let(:redis) {Redis.new(worker_roulette.redis_config)}
10
8
 
11
9
  before do
12
- Lua.clear_cache!
10
+ lua.clear_cache!
13
11
  redis.script(:flush)
14
12
  redis.flushdb
15
13
  end
16
14
 
17
15
  it "should load and call a lua script" do
18
16
  lua_script = 'return redis.call("SET", KEYS[1], ARGV[1])'
19
- Lua.call(lua_script, ['foo'], ['daddy']) do |result|
20
- expect(Lua.cache.keys.first).to eq(lua_script)
21
- expect(Lua.cache.values.first).to eq(Digest::SHA1.hexdigest(lua_script))
17
+ lua.call(lua_script, ['foo'], ['daddy']) do |result|
18
+ expect(lua.cache.keys.first).to eq(lua_script)
19
+ expect(lua.cache.values.first).to eq(Digest::SHA1.hexdigest(lua_script))
22
20
  expect(result).to eq("OK")
23
21
  done
24
22
  end
@@ -26,12 +24,12 @@ module WorkerRoulette
26
24
 
27
25
  it "should send a sha instead of a script once the script has been cached" do
28
26
  lua_script = 'return KEYS'
29
- expect(Lua).to receive(:eval).and_call_original
27
+ expect(lua).to receive(:eval).and_call_original
30
28
 
31
- Lua.call(lua_script) do |result|
32
- expect(Lua).not_to receive(:eval)
29
+ lua.call(lua_script) do |result|
30
+ expect(lua).not_to receive(:eval)
33
31
 
34
- Lua.call(lua_script) do |inner_result|
32
+ lua.call(lua_script) do |inner_result|
35
33
  expect(inner_result).to be_empty
36
34
  done
37
35
  end
@@ -40,7 +38,7 @@ module WorkerRoulette
40
38
 
41
39
  it "should raise an error to the caller if the script fails in redis" do
42
40
  lua_script = 'this is junk'
43
- # Lua.call(lua_script)
41
+ # lua.call(lua_script)
44
42
  # rspec cannot test this bc of the callbacks, but if you have doubts,
45
43
  # uncomment the line above and watch it fail
46
44
  done
@@ -1,21 +1,22 @@
1
1
  require 'spec_helper'
2
2
  module WorkerRoulette
3
3
  describe "Read Lock" do
4
- let(:redis) {Redis.new(WorkerRoulette.redis_config)}
4
+ let(:worker_roulette) {WorkerRoulette.start(evented: false)}
5
+ let(:redis) {Redis.new(worker_roulette.redis_config)}
5
6
  let(:sender) {'katie_80'}
6
7
  let(:work_orders) {"hellot"}
7
8
  let(:lock_key) {"L*:#{sender}"}
8
9
  let(:default_headers) {Hash['headers' => {'sender' => sender}]}
9
10
  let(:work_orders_with_headers) {default_headers.merge({'payload' => work_orders})}
10
11
  let(:jsonized_work_orders_with_headers) {[WorkerRoulette.dump(work_orders_with_headers)]}
11
- let(:foreman) {WorkerRoulette.foreman(sender)}
12
- let(:number_two) {WorkerRoulette.foreman('number_two')}
13
- let(:subject) {WorkerRoulette.tradesman}
14
- let(:subject_two) {WorkerRoulette.tradesman}
12
+ let(:foreman) {worker_roulette.foreman(sender)}
13
+ let(:number_two) {worker_roulette.foreman('number_two')}
14
+ let(:subject) {worker_roulette.tradesman}
15
+ let(:subject_two) {worker_roulette.tradesman}
16
+ let(:lua) { Lua.new(worker_roulette.tradesman_connection_pool) }
15
17
 
16
18
  before do
17
- WorkerRoulette.start(evented: false)
18
- Lua.clear_cache!
19
+ lua.clear_cache!
19
20
  redis.script(:flush)
20
21
  redis.flushdb
21
22
  foreman.enqueue_work_order(work_orders)
@@ -26,8 +27,8 @@ module WorkerRoulette
26
27
  expect(redis.get(lock_key)).not_to be_nil
27
28
  end
28
29
 
29
- it "should set the lock to expire in 1 second" do
30
- expect(redis.ttl(lock_key)).to eq(1)
30
+ it "should set the lock to expire in 3 second" do
31
+ expect(redis.ttl(lock_key)).to eq(3)
31
32
  end
32
33
 
33
34
  it "should not read a locked queue" do
@@ -66,7 +67,5 @@ module WorkerRoulette
66
67
  expect(subject.work_orders!).to be_empty
67
68
  expect(redis.get(lock_key)).to be_nil
68
69
  end
69
-
70
- pending "pubsub should clean up one contention or remove the lock on the same sender queue automaticly"
71
70
  end
72
71
  end
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency 'em-hiredis', '~> 0.2.1'
24
24
  spec.add_dependency 'connection_pool'
25
25
  spec.add_dependency 'eventmachine', '~> 1.0.3'
26
+ spec.add_dependency 'timers', '~> 3.0.1'
26
27
 
27
28
  spec.add_development_dependency 'bundler'
28
29
  spec.add_development_dependency 'rake'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: worker_roulette
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Saieg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-09 00:00:00.000000000 Z
11
+ date: 2014-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.0.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: timers
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.1
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: bundler
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -236,11 +250,11 @@ files:
236
250
  - README.md
237
251
  - Rakefile
238
252
  - lib/worker_roulette.rb
239
- - lib/worker_roulette/a_tradesman.rb
240
253
  - lib/worker_roulette/foreman.rb
241
254
  - lib/worker_roulette/lua.rb
242
255
  - lib/worker_roulette/tradesman.rb
243
256
  - lib/worker_roulette/version.rb
257
+ - spec/benchmark/irb_demo_runner.rb
244
258
  - spec/benchmark/perf_test.rb
245
259
  - spec/helpers/.gitkeep
246
260
  - spec/integration/evented_worker_roulette_spec.rb
@@ -249,7 +263,6 @@ files:
249
263
  - spec/unit/evented_readlock_spec.rb
250
264
  - spec/unit/lua_spec.rb
251
265
  - spec/unit/readlock_spec.rb
252
- - spec/unit/worker_roulette_spec.rb
253
266
  - worker_roulette.gemspec
254
267
  homepage: https://github.com/nexiahome/worker_roulette
255
268
  licenses: []
@@ -275,6 +288,7 @@ signing_key:
275
288
  specification_version: 4
276
289
  summary: Pub Sub Queue for Redis that ensures ordered processing
277
290
  test_files:
291
+ - spec/benchmark/irb_demo_runner.rb
278
292
  - spec/benchmark/perf_test.rb
279
293
  - spec/helpers/.gitkeep
280
294
  - spec/integration/evented_worker_roulette_spec.rb
@@ -283,4 +297,3 @@ test_files:
283
297
  - spec/unit/evented_readlock_spec.rb
284
298
  - spec/unit/lua_spec.rb
285
299
  - spec/unit/readlock_spec.rb
286
- - spec/unit/worker_roulette_spec.rb
@@ -1,46 +0,0 @@
1
- require_relative './tradesman'
2
- module WorkerRoulette
3
- class ATradesman < Tradesman
4
- attr_reader :timer
5
-
6
- def wait_for_work_orders(on_subscribe_callback = nil, &on_message_callback)
7
- @redis_pubsub ||= WorkerRoulette.new_redis_pubsub #cannot use connection pool bc redis expects each obj to own its own pubsub connection for the life of the subscription
8
- @redis_pubsub.on(:subscribe) {|channel, subscription_count| on_subscribe_callback.call(channel, subscription_count) if on_subscribe_callback}
9
- @redis_pubsub.on(:message) {|channel, message| get_messages(message, channel, on_message_callback)}
10
- set_timer(on_message_callback);
11
- @redis_pubsub.subscribe(@channel)
12
- end
13
-
14
- def unsubscribe(&callback)
15
- deferable = @redis_pubsub.unsubscribe(@channel)
16
- deferable.callback do
17
- @redis_pubsub.close_connection
18
- @redis_pubsub = nil
19
- callback.call
20
- end
21
- deferable.errback do
22
- @redis_pubsub.close_connection
23
- @redis_pubsub = nil
24
- callback.call
25
- end
26
- end
27
-
28
- private
29
-
30
- def get_messages(message, channel, on_message_callback)
31
- return unless on_message_callback
32
- work_orders! do |work_orders_1|
33
- work_orders! do |work_orders|
34
- on_message_callback.call(work_orders_1 + work_orders, message, channel)
35
- end
36
- end
37
- end
38
-
39
- def set_timer(on_message_callback)
40
- return if (@timer || !on_message_callback)
41
- @timer = EM::PeriodicTimer.new(rand(20..25)) do
42
- work_orders! {|work_orders| on_message_callback.call(work_orders, nil, nil)}
43
- end
44
- end
45
- end
46
- end