refilling_queue 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/Readme.md +4 -2
- data/lib/refilling_queue.rb +10 -9
- data/lib/refilling_queue/version.rb +1 -1
- data/spec/refilling_queue_spec.rb +16 -6
- metadata +4 -4
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -14,8 +14,8 @@ Usage
|
|
14
14
|
|
15
15
|
begin
|
16
16
|
queue.pop
|
17
|
-
rescue
|
18
|
-
|
17
|
+
rescue RefillingQueue::Locked
|
18
|
+
# queue was empty, refilling failed because other process is already trying it
|
19
19
|
end
|
20
20
|
|
21
21
|
queue.pop -> return id
|
@@ -23,6 +23,8 @@ Usage
|
|
23
23
|
queue.pop -> run block -> store new ids -> return id
|
24
24
|
... # 30 seconds elapsed (global expires_at stored in reque_client) ?
|
25
25
|
queue.pop -> run block -> store new ids -> return id
|
26
|
+
...
|
27
|
+
queue.pop -> run block -> empty result -> return nil
|
26
28
|
|
27
29
|
Author
|
28
30
|
======
|
data/lib/refilling_queue.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'refilling_queue/version'
|
2
2
|
|
3
3
|
class RefillingQueue
|
4
|
-
class
|
4
|
+
class Locked < RuntimeError
|
5
5
|
end
|
6
6
|
|
7
7
|
DEFAULT_OPTIONS = {
|
@@ -16,20 +16,23 @@ class RefillingQueue
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def pop
|
19
|
-
item =
|
19
|
+
item = _pop
|
20
20
|
return item unless item.nil?
|
21
|
-
|
22
21
|
refill
|
22
|
+
_pop
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
return item unless item.nil?
|
25
|
+
private
|
26
26
|
|
27
|
-
|
27
|
+
def _pop
|
28
|
+
@client.lpop @name
|
28
29
|
end
|
29
30
|
|
30
31
|
def refill
|
31
32
|
lock do
|
32
33
|
results = @block.call
|
34
|
+
return if results.empty?
|
35
|
+
|
33
36
|
@client.pipelined do
|
34
37
|
@client.del @name
|
35
38
|
results.each{ |r| @client.rpush @name, r } # TODO https://github.com/redis/redis-rb/issues/253
|
@@ -42,11 +45,9 @@ class RefillingQueue
|
|
42
45
|
@client.llen(@name) == 0
|
43
46
|
end
|
44
47
|
|
45
|
-
private
|
46
|
-
|
47
48
|
def lock
|
48
49
|
lock = "#{@name}_lock"
|
49
|
-
|
50
|
+
raise RefillingQueue::Locked unless @client.setnx lock, "1"
|
50
51
|
@client.expire lock, @options[:lock_timeout]
|
51
52
|
begin
|
52
53
|
yield
|
@@ -32,12 +32,9 @@ describe RefillingQueue do
|
|
32
32
|
queue.pop.should == 3
|
33
33
|
end
|
34
34
|
|
35
|
-
it "only tries to refill once
|
35
|
+
it "only tries to refill once" do
|
36
36
|
calls = []
|
37
|
-
|
38
|
-
expect{
|
39
|
-
queue.pop
|
40
|
-
}.to raise_error(RefillingQueue::EmptyRefill)
|
37
|
+
RefillingQueue.new(client, "x"){ calls << 1; [] }.pop.should == nil
|
41
38
|
calls.should == [1]
|
42
39
|
end
|
43
40
|
|
@@ -67,14 +64,27 @@ describe RefillingQueue do
|
|
67
64
|
context "with multiple actors" do
|
68
65
|
it "only refills once" do
|
69
66
|
called = []
|
67
|
+
|
68
|
+
# lock-blocker
|
70
69
|
Thread.new do
|
71
70
|
RefillingQueue.new(client, "x"){ sleep 0.2; called << 1; [] }.pop
|
72
71
|
end
|
72
|
+
sleep 0.1
|
73
|
+
|
74
|
+
# blocked
|
75
|
+
locked = false
|
73
76
|
Thread.new do
|
74
|
-
RefillingQueue.new(client, "x"){ sleep 0.2; called << 1; [] }
|
77
|
+
queue = RefillingQueue.new(client, "x"){ sleep 0.2; called << 1; [] }
|
78
|
+
begin
|
79
|
+
queue.pop
|
80
|
+
rescue RefillingQueue::Locked
|
81
|
+
locked = true
|
82
|
+
end
|
75
83
|
end
|
76
84
|
sleep 0.3
|
85
|
+
|
77
86
|
called.should == [1]
|
87
|
+
locked.should == true
|
78
88
|
end
|
79
89
|
|
80
90
|
it "can refill after refill is complete" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: refilling_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-13 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: michael@grosser.it
|
@@ -42,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
42
|
version: '0'
|
43
43
|
segments:
|
44
44
|
- 0
|
45
|
-
hash:
|
45
|
+
hash: 2863148755919563971
|
46
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
47
|
none: false
|
48
48
|
requirements:
|
@@ -51,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
51
|
version: '0'
|
52
52
|
segments:
|
53
53
|
- 0
|
54
|
-
hash:
|
54
|
+
hash: 2863148755919563971
|
55
55
|
requirements: []
|
56
56
|
rubyforge_project:
|
57
57
|
rubygems_version: 1.8.24
|