infopark-politics 0.8.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/infopark-politics.gemspec +1 -1
- data/lib/politics/static_queue_worker.rb +36 -33
- data/spec/static_queue_worker_spec.rb +30 -30
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZTc2ZjhmOTAwNTNjNTNlYWExZjAwM2Y5ZDY0ZDQ4NmViOGVmNjNkZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OGEyNjc2N2IwYjcyZjU3NDFiYWE4ZDY2N2Q4NDhjYzIxZDRlMDc1Ng==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZmQ0YjM2NzU1YzY0ZjQ3ZWZlOWY5MjE0ZDg1ZTIwMTE1ZjE4OTVjNTE5NmYw
|
10
|
+
ZWQ1ODZiOWFiOWE0NTE3M2RiZjgxYzJhMThiMDJiYzQxZjU5NTQwYWM3OTVi
|
11
|
+
MzlmYTEzODM2Yzg0ZjljMTFlNTc5NWViZTUxZmZiZDkxOGQ1OTY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
M2JlY2ExN2NiMmZhYWU3MjI0ZjYyMWRiMDljOWY5ZmQ5ZWRhYTBiNmZiNGRk
|
14
|
+
NzZjMTAyMmRiYTYyNGI5ZTJlODNiZjdmNjMzNzU5NjE1Zjc1NzZiYmFlYWMz
|
15
|
+
YTk0YmIzY2E1OWJlMTFlNzM2YWNmMTViMjJkNjhhN2UzNmZhMWQ=
|
data/infopark-politics.gemspec
CHANGED
@@ -6,7 +6,7 @@ end
|
|
6
6
|
|
7
7
|
Gem::Specification.new do |gem|
|
8
8
|
gem.name = "infopark-politics"
|
9
|
-
gem.version = "0.
|
9
|
+
gem.version = "0.9.0"
|
10
10
|
gem.summary = "Algorithms and Tools for Distributed Computing in Ruby."
|
11
11
|
gem.description = ""
|
12
12
|
gem.authors = ["Mike Perham", "Tilo Prütz"]
|
@@ -19,7 +19,7 @@ module Politics
|
|
19
19
|
|
20
20
|
@group_name = name
|
21
21
|
@iteration_length = options[:iteration_length]
|
22
|
-
@
|
22
|
+
@memcache_config = Array(options[:servers])
|
23
23
|
@dictatorship_length = options[:dictatorship_length]
|
24
24
|
|
25
25
|
@buckets = []
|
@@ -30,7 +30,7 @@ module Politics
|
|
30
30
|
log.progname = uri
|
31
31
|
log.info { "Registered in group #{group_name} at #{uri}" }
|
32
32
|
at_exit do
|
33
|
-
internal_cleanup
|
33
|
+
internal_cleanup(client_for(memcache_config))
|
34
34
|
cleanup
|
35
35
|
end
|
36
36
|
end
|
@@ -39,10 +39,11 @@ module Politics
|
|
39
39
|
def process_bucket(&block)
|
40
40
|
log.debug "start bucket processing"
|
41
41
|
raise ArgumentError, "process_bucket requires a block!" unless block_given?
|
42
|
-
unless
|
42
|
+
unless memcache_config
|
43
43
|
raise ArgumentError, "You must call register_worker before processing!"
|
44
44
|
end
|
45
45
|
|
46
|
+
worker_memcache_client = client_for(memcache_config)
|
46
47
|
begin
|
47
48
|
begin
|
48
49
|
raise "self is not alive via drb" unless DRbObject.new(nil, uri).alive?
|
@@ -50,20 +51,21 @@ module Politics
|
|
50
51
|
raise "cannot reach self via drb: #{e.message}"
|
51
52
|
end
|
52
53
|
begin
|
53
|
-
nominate
|
54
|
+
nominate(worker_memcache_client)
|
54
55
|
|
55
|
-
if leader? && !(@leader_thread && @leader_thread.alive?)
|
56
|
+
if leader?(worker_memcache_client) && !(@leader_thread && @leader_thread.alive?)
|
56
57
|
unless (@leader_thread && @leader_thread.alive?)
|
57
58
|
@leader_thread = Thread.new do
|
58
|
-
|
59
|
+
leader_memcache_client = client_for(memcache_config)
|
60
|
+
perform_leader_duties(leader_memcache_client)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
65
|
# Get a bucket from the leader and process it
|
64
66
|
begin
|
65
|
-
log.debug "getting bucket request from leader (#{leader_uri}) and processing it"
|
66
|
-
bucket_process(*leader.bucket_request(uri, bucket_request_context), &block)
|
67
|
+
log.debug "getting bucket request from leader (#{leader_uri(worker_memcache_client)}) and processing it"
|
68
|
+
bucket_process(*leader(worker_memcache_client).bucket_request(uri, bucket_request_context), &block)
|
67
69
|
rescue DRb::DRbError => dre
|
68
70
|
log.error { "Error talking to leader: #{dre.message}" }
|
69
71
|
relax until_next_iteration
|
@@ -75,44 +77,44 @@ module Politics
|
|
75
77
|
end while loop?
|
76
78
|
end
|
77
79
|
|
78
|
-
def as_dictator(&block)
|
80
|
+
def as_dictator(memcache_client, &block)
|
79
81
|
duration = dictatorship_length || (iteration_length * 10)
|
80
82
|
log.debug { "become dictator for up to #{duration} seconds" }
|
81
|
-
seize_leadership duration
|
83
|
+
seize_leadership(memcache_client, duration)
|
82
84
|
yield
|
83
|
-
raise "lost leadership while being dictator for #{duration} seconds" unless leader?
|
84
|
-
seize_leadership
|
85
|
+
raise "lost leadership while being dictator for #{duration} seconds" unless leader?(memcache_client)
|
86
|
+
seize_leadership(memcache_client)
|
85
87
|
end
|
86
88
|
|
87
|
-
def seize_leadership(*args)
|
89
|
+
def seize_leadership(memcache_client, *args)
|
88
90
|
start_iteration(*args) {|duration| memcache_client.set(token, uri, duration) }
|
89
91
|
end
|
90
92
|
|
91
|
-
def perform_leader_duties
|
93
|
+
def perform_leader_duties(memcache_client)
|
92
94
|
with_errors_logged('leader duties') do
|
93
95
|
# The DRb thread handles the requests to the leader.
|
94
96
|
# This method performs the bucket managing.
|
95
97
|
log.info { "has been elected leader" }
|
96
98
|
before_perform_leader_duties
|
97
99
|
# keeping leader state as long as buckets are being initialized
|
98
|
-
as_dictator { initialize_buckets }
|
100
|
+
as_dictator(memcache_client) { initialize_buckets }
|
99
101
|
|
100
102
|
while !buckets.empty?
|
101
103
|
# keeping leader state as long as buckets are available by renominating before
|
102
104
|
# nomination times out
|
103
|
-
as_dictator { update_buckets } unless restart_wanted?
|
105
|
+
as_dictator(memcache_client) { update_buckets } unless restart_wanted?(memcache_client)
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
107
109
|
with_errors_logged('termination handling') do
|
108
|
-
if restart_wanted?
|
110
|
+
if restart_wanted?(memcache_client)
|
109
111
|
log.info "restart triggered"
|
110
|
-
as_dictator { populate_followers_to_stop }
|
112
|
+
as_dictator(memcache_client) { populate_followers_to_stop }
|
111
113
|
# keeping leader state as long as there are followers to stop
|
112
114
|
while !followers_to_stop.empty?
|
113
115
|
log.info "waiting fo workers to stop: #{followers_to_stop}"
|
114
116
|
relax(until_next_iteration / 2)
|
115
|
-
seize_leadership
|
117
|
+
seize_leadership(memcache_client)
|
116
118
|
end
|
117
119
|
log.info "leader exiting due to trigger"
|
118
120
|
exit 0
|
@@ -129,7 +131,8 @@ module Politics
|
|
129
131
|
end
|
130
132
|
|
131
133
|
def bucket_request(requestor_uri, context)
|
132
|
-
|
134
|
+
memcache_client = client_for(memcache_config)
|
135
|
+
if leader?(memcache_client)
|
133
136
|
log.debug "delivering bucket request"
|
134
137
|
bucket_spec = next_bucket(requestor_uri, context)
|
135
138
|
if !bucket_spec[0] && @followers_to_stop.include?(requestor_uri)
|
@@ -162,27 +165,27 @@ module Politics
|
|
162
165
|
true
|
163
166
|
end
|
164
167
|
|
165
|
-
def leader
|
168
|
+
def leader(memcache_client)
|
166
169
|
2.times do
|
167
|
-
break if leader_uri
|
170
|
+
break if leader_uri(memcache_client)
|
168
171
|
log.debug "could not determine leader - relaxing until next iteration"
|
169
172
|
relax until_next_iteration
|
170
173
|
end
|
171
|
-
raise "cannot determine leader" unless leader_uri
|
172
|
-
DRbObject.new(nil, leader_uri)
|
174
|
+
raise "cannot determine leader" unless leader_uri(memcache_client)
|
175
|
+
DRbObject.new(nil, leader_uri(memcache_client))
|
173
176
|
end
|
174
177
|
|
175
178
|
def find_workers
|
176
179
|
raise "Please provide a method ”find_workers” returning a list of all other worker URIs"
|
177
180
|
end
|
178
181
|
|
179
|
-
def restart_wanted?
|
182
|
+
def restart_wanted?(memcache_client)
|
180
183
|
memcache_client.get(restart_flag)
|
181
184
|
end
|
182
185
|
|
183
186
|
private
|
184
187
|
|
185
|
-
attr_reader :iteration_end, :
|
188
|
+
attr_reader :iteration_end, :memcache_config
|
186
189
|
|
187
190
|
def with_errors_logged(task)
|
188
191
|
yield
|
@@ -243,9 +246,9 @@ module Politics
|
|
243
246
|
"#{group_name}_restart"
|
244
247
|
end
|
245
248
|
|
246
|
-
def internal_cleanup
|
247
|
-
log.debug("uri: #{uri}, leader_uri: #{leader_uri}, until_next_iteration: #{until_next_iteration}")
|
248
|
-
if leader?
|
249
|
+
def internal_cleanup(memcache_client)
|
250
|
+
log.debug("uri: #{uri}, leader_uri: #{leader_uri(memcache_client)}, until_next_iteration: #{until_next_iteration}")
|
251
|
+
if leader?(memcache_client)
|
249
252
|
memcache_client.delete(token)
|
250
253
|
memcache_client.delete(restart_flag)
|
251
254
|
end
|
@@ -261,7 +264,7 @@ module Politics
|
|
261
264
|
|
262
265
|
# Nominate ourself as leader by contacting the memcached server
|
263
266
|
# and attempting to add the token with our name attached.
|
264
|
-
def nominate
|
267
|
+
def nominate(memcache_client)
|
265
268
|
log.debug("try to nominate")
|
266
269
|
start_iteration {|duration| memcache_client.add(token, uri, duration) }
|
267
270
|
end
|
@@ -272,14 +275,14 @@ module Politics
|
|
272
275
|
@leader_uri = nil
|
273
276
|
end
|
274
277
|
|
275
|
-
def leader_uri
|
278
|
+
def leader_uri(memcache_client)
|
276
279
|
@leader_uri ||= memcache_client.get(token)
|
277
280
|
end
|
278
281
|
|
279
282
|
# Check to see if we are leader by looking at the process name
|
280
283
|
# associated with the token.
|
281
|
-
def leader?
|
282
|
-
until_next_iteration > 0 && uri == leader_uri
|
284
|
+
def leader?(memcache_client)
|
285
|
+
until_next_iteration > 0 && uri == leader_uri(memcache_client)
|
283
286
|
end
|
284
287
|
|
285
288
|
# Easy to mock or monkey-patch if another MemCache client is preferred.
|
@@ -268,14 +268,14 @@ describe Worker do
|
|
268
268
|
describe "when determining if restart is wanted" do
|
269
269
|
it "should return true if the restart flag is set in memcache" do
|
270
270
|
expect(memcache_client).to receive(:get).with('worker_restart').and_return true
|
271
|
-
expect(worker).to be_restart_wanted
|
271
|
+
expect(worker).to be_restart_wanted(memcache_client)
|
272
272
|
end
|
273
273
|
|
274
274
|
it "should return false if the restart flag is not set in memcache" do
|
275
275
|
expect(memcache_client).to receive(:get).with('worker_restart').and_return false
|
276
|
-
expect(worker).not_to be_restart_wanted
|
276
|
+
expect(worker).not_to be_restart_wanted(memcache_client)
|
277
277
|
expect(memcache_client).to receive(:get).with('worker_restart').and_return nil
|
278
|
-
expect(worker).not_to be_restart_wanted
|
278
|
+
expect(worker).not_to be_restart_wanted(memcache_client)
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
@@ -291,7 +291,7 @@ describe Worker do
|
|
291
291
|
|
292
292
|
it "performs before_perform_leader_duties callback" do
|
293
293
|
expect(worker).to receive(:before_perform_leader_duties)
|
294
|
-
worker.perform_leader_duties
|
294
|
+
worker.perform_leader_duties(memcache_client)
|
295
295
|
end
|
296
296
|
|
297
297
|
it "has a before_perform_leader_duties callback" do
|
@@ -299,10 +299,10 @@ describe Worker do
|
|
299
299
|
end
|
300
300
|
|
301
301
|
it "should initialize buckets as dictator" do
|
302
|
-
expect(worker).to receive(:seize_leadership).with(666).ordered
|
302
|
+
expect(worker).to receive(:seize_leadership).with(memcache_client, 666).ordered
|
303
303
|
expect(worker).to receive(:initialize_buckets).ordered
|
304
304
|
expect(worker).to receive(:seize_leadership).ordered
|
305
|
-
worker.perform_leader_duties
|
305
|
+
worker.perform_leader_duties(memcache_client)
|
306
306
|
end
|
307
307
|
|
308
308
|
describe "as long as there are buckets" do
|
@@ -313,32 +313,32 @@ describe Worker do
|
|
313
313
|
|
314
314
|
it "should update buckets periodically" do
|
315
315
|
expect(worker).to receive(:update_buckets).exactly(4).times
|
316
|
-
worker.perform_leader_duties
|
316
|
+
worker.perform_leader_duties(memcache_client)
|
317
317
|
end
|
318
318
|
|
319
319
|
it "should relax half of the time to the next iteration" do
|
320
320
|
allow(worker).to receive(:until_next_iteration).and_return(6)
|
321
321
|
expect(worker).to receive(:relax).with(3).exactly(4).times
|
322
|
-
worker.perform_leader_duties
|
322
|
+
worker.perform_leader_duties(memcache_client)
|
323
323
|
end
|
324
324
|
|
325
325
|
it "should seize the leadership periodically" do
|
326
326
|
expect(worker).to receive(:seize_leadership).at_least(4).times
|
327
|
-
worker.perform_leader_duties
|
327
|
+
worker.perform_leader_duties(memcache_client)
|
328
328
|
end
|
329
329
|
|
330
330
|
it "should seize the leadership periodically even if restart is wanted" do
|
331
331
|
allow(worker).to receive(:restart_wanted?).and_return true
|
332
332
|
allow(worker).to receive(:exit)
|
333
333
|
expect(worker).to receive(:seize_leadership).at_least(4).times
|
334
|
-
worker.perform_leader_duties
|
334
|
+
worker.perform_leader_duties(memcache_client)
|
335
335
|
end
|
336
336
|
|
337
337
|
it "should not update buckets if restart is wanted" do
|
338
338
|
allow(worker).to receive(:restart_wanted?).and_return true
|
339
339
|
allow(worker).to receive(:exit)
|
340
340
|
expect(worker).not_to receive(:update_buckets)
|
341
|
-
worker.perform_leader_duties
|
341
|
+
worker.perform_leader_duties(memcache_client)
|
342
342
|
end
|
343
343
|
end
|
344
344
|
|
@@ -356,7 +356,7 @@ describe Worker do
|
|
356
356
|
it "populates the followers_to_stop list before evaluating it" do
|
357
357
|
expect(worker).to receive(:populate_followers_to_stop).ordered.once
|
358
358
|
expect(worker).to receive(:followers_to_stop).ordered.and_return []
|
359
|
-
worker.perform_leader_duties
|
359
|
+
worker.perform_leader_duties(memcache_client)
|
360
360
|
end
|
361
361
|
|
362
362
|
context "as long as there are followers to stop" do
|
@@ -369,12 +369,12 @@ describe Worker do
|
|
369
369
|
it "relaxes half of the time to the next iteration" do
|
370
370
|
allow(worker).to receive(:until_next_iteration).and_return(6)
|
371
371
|
expect(worker).to receive(:relax).with(3).exactly(2).times
|
372
|
-
worker.perform_leader_duties
|
372
|
+
worker.perform_leader_duties(memcache_client)
|
373
373
|
end
|
374
374
|
|
375
375
|
it "seizes the leadership periodically" do
|
376
376
|
expect(worker).to receive(:seize_leadership).at_least(2).times
|
377
|
-
worker.perform_leader_duties
|
377
|
+
worker.perform_leader_duties(memcache_client)
|
378
378
|
end
|
379
379
|
end
|
380
380
|
|
@@ -385,7 +385,7 @@ describe Worker do
|
|
385
385
|
|
386
386
|
it "exits" do
|
387
387
|
expect(worker).to receive(:exit).with(0)
|
388
|
-
worker.perform_leader_duties
|
388
|
+
worker.perform_leader_duties(memcache_client)
|
389
389
|
end
|
390
390
|
end
|
391
391
|
end
|
@@ -398,7 +398,7 @@ describe Worker do
|
|
398
398
|
it "does not populate the followers_to_stop list if restart is not wanted" do
|
399
399
|
allow(worker).to receive(:restart_wanted?).and_return false
|
400
400
|
expect(worker).not_to receive(:populate_followers_to_stop)
|
401
|
-
worker.perform_leader_duties
|
401
|
+
worker.perform_leader_duties(memcache_client)
|
402
402
|
end
|
403
403
|
end
|
404
404
|
end
|
@@ -413,22 +413,22 @@ describe Worker do
|
|
413
413
|
|
414
414
|
it "should set itself to leader" do
|
415
415
|
expect(memcache_client).to receive(:set).with(anything(), 'myself', anything())
|
416
|
-
worker.seize_leadership
|
416
|
+
worker.seize_leadership(memcache_client)
|
417
417
|
end
|
418
418
|
|
419
419
|
it "should seize the leadership for the amount of seconds given" do
|
420
420
|
expect(memcache_client).to receive(:set).with(anything(), anything(), 666)
|
421
|
-
worker.seize_leadership 666
|
421
|
+
worker.seize_leadership memcache_client, 666
|
422
422
|
end
|
423
423
|
|
424
424
|
it "should seize the leadership for iteration_length if no duration is given" do
|
425
425
|
expect(memcache_client).to receive(:set).with(anything(), anything(), 123)
|
426
|
-
worker.seize_leadership
|
426
|
+
worker.seize_leadership(memcache_client)
|
427
427
|
end
|
428
428
|
|
429
429
|
it "should seize the leadership for the worker's group" do
|
430
430
|
expect(memcache_client).to receive(:set).with('dcc-group', anything(), anything())
|
431
|
-
worker.seize_leadership
|
431
|
+
worker.seize_leadership(memcache_client)
|
432
432
|
end
|
433
433
|
|
434
434
|
it "should have the next iteration exactly when the seized leadership ends" do
|
@@ -436,13 +436,13 @@ describe Worker do
|
|
436
436
|
allow(Time).to receive(:now).and_return now
|
437
437
|
end_of_leadership = now + 666
|
438
438
|
|
439
|
-
worker.seize_leadership 666
|
439
|
+
worker.seize_leadership memcache_client, 666
|
440
440
|
expect(worker.until_next_iteration).to eq(666)
|
441
441
|
|
442
|
-
worker.seize_leadership
|
442
|
+
worker.seize_leadership(memcache_client)
|
443
443
|
expect(worker.until_next_iteration).to eq(123)
|
444
444
|
|
445
|
-
worker.seize_leadership 6
|
445
|
+
worker.seize_leadership memcache_client, 6
|
446
446
|
expect(worker.until_next_iteration).to eq(6)
|
447
447
|
end
|
448
448
|
end
|
@@ -483,24 +483,24 @@ describe Worker do
|
|
483
483
|
it "should return a drb object with the leader uri" do
|
484
484
|
allow(worker).to receive(:leader_uri).and_return("leader's uri")
|
485
485
|
expect(DRbObject).to receive(:new).with(nil, "leader's uri").and_return "leader"
|
486
|
-
expect(worker.leader).to eq("leader")
|
486
|
+
expect(worker.leader(memcache_client)).to eq("leader")
|
487
487
|
end
|
488
488
|
|
489
489
|
it "should try three times to get the leader on anarchy (no leader)" do
|
490
490
|
expect(worker).to receive(:leader_uri).at_least(3).times.and_return nil
|
491
|
-
worker.leader rescue nil
|
491
|
+
worker.leader(memcache_client) rescue nil
|
492
492
|
end
|
493
493
|
|
494
494
|
it "should raise an error when leader cannot be determined during anarchy" do
|
495
495
|
allow(worker).to receive(:leader_uri).and_return nil
|
496
|
-
expect {worker.leader}.to raise_error(/cannot determine leader/)
|
496
|
+
expect {worker.leader(memcache_client)}.to raise_error(/cannot determine leader/)
|
497
497
|
end
|
498
498
|
|
499
499
|
it "should sleep until next iteration before retrying to get leader" do
|
500
500
|
allow(worker).to receive(:leader_uri).and_return nil
|
501
501
|
allow(worker).to receive(:until_next_iteration).and_return 666
|
502
502
|
expect(worker).to receive(:relax).with(666).exactly(2).times
|
503
|
-
worker.leader rescue nil
|
503
|
+
worker.leader(memcache_client) rescue nil
|
504
504
|
end
|
505
505
|
end
|
506
506
|
|
@@ -517,12 +517,12 @@ describe Worker do
|
|
517
517
|
|
518
518
|
it "should remove the leadership token from memcache" do
|
519
519
|
expect(memcache_client).to receive(:delete).with('the group_token')
|
520
|
-
worker.send(:internal_cleanup)
|
520
|
+
worker.send(:internal_cleanup, memcache_client)
|
521
521
|
end
|
522
522
|
|
523
523
|
it "should remove the restart wanted flag from memcache" do
|
524
524
|
expect(memcache_client).to receive(:delete).with('the group_restart')
|
525
|
-
worker.send(:internal_cleanup)
|
525
|
+
worker.send(:internal_cleanup, memcache_client)
|
526
526
|
end
|
527
527
|
end
|
528
528
|
|
@@ -533,7 +533,7 @@ describe Worker do
|
|
533
533
|
|
534
534
|
it "should not remove anything from memcache" do
|
535
535
|
expect(memcache_client).not_to receive(:delete)
|
536
|
-
worker.send(:internal_cleanup)
|
536
|
+
worker.send(:internal_cleanup, memcache_client)
|
537
537
|
end
|
538
538
|
end
|
539
539
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: infopark-politics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-04-
|
12
|
+
date: 2015-04-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|