beaneater 0.3.0 → 1.1.1
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.
- checksums.yaml +7 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +36 -1
- data/Gemfile +5 -1
- data/README.md +50 -26
- data/Rakefile +3 -1
- data/beaneater.gemspec +1 -1
- data/examples/demo.rb +1 -2
- data/lib/beaneater/configuration.rb +3 -1
- data/lib/beaneater/connection.rb +135 -30
- data/lib/beaneater/errors.rb +4 -4
- data/lib/beaneater/job/collection.rb +67 -37
- data/lib/beaneater/job/record.rb +42 -30
- data/lib/beaneater/stats/fast_struct.rb +1 -1
- data/lib/beaneater/stats/stat_struct.rb +8 -2
- data/lib/beaneater/stats.rb +28 -5
- data/lib/beaneater/tube/collection.rb +67 -26
- data/lib/beaneater/tube/record.rb +45 -27
- data/lib/beaneater/version.rb +2 -2
- data/lib/beaneater.rb +57 -4
- data/test/beaneater_test.rb +5 -11
- data/test/connection_test.rb +55 -1
- data/test/errors_test.rb +9 -2
- data/test/job_test.rb +8 -12
- data/test/jobs_test.rb +15 -43
- data/test/prompt_regexp_test.rb +14 -2
- data/test/stat_struct_test.rb +12 -2
- data/test/stats_test.rb +9 -9
- data/test/test_helper.rb +34 -10
- data/test/tube_test.rb +12 -23
- data/test/tubes_test.rb +61 -56
- metadata +25 -65
- data/lib/beaneater/pool.rb +0 -166
- data/lib/beaneater/pool_command.rb +0 -79
- data/test/pool_command_test.rb +0 -90
- data/test/pool_test.rb +0 -180
data/test/tube_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# test/
|
1
|
+
# test/tube_test.rb
|
2
2
|
|
3
3
|
require File.expand_path('../test_helper', __FILE__)
|
4
4
|
|
5
5
|
describe Beaneater::Tube do
|
6
6
|
before do
|
7
|
-
@
|
8
|
-
@tube = Beaneater::Tube.new(@
|
7
|
+
@beanstalk = Beaneater.new('localhost')
|
8
|
+
@tube = Beaneater::Tube.new(@beanstalk, 'baz')
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "for #put" do
|
@@ -26,22 +26,15 @@ describe Beaneater::Tube do
|
|
26
26
|
assert_equal "delayed put #{@time}", @tube.peek(:delayed).body
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should
|
30
|
-
Beaneater
|
31
|
-
|
32
|
-
|
33
|
-
assert_equal 'foo', @tube.put("bar put #{@time}")
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should try to put 3 times before to raise" do
|
37
|
-
Beaneater::Connection.any_instance.expects(:transmit).once.with(includes('use baz'), {})
|
38
|
-
Beaneater::Connection.any_instance.expects(:transmit).with(includes("bar put #{@time}"), {}).
|
39
|
-
times(3).raises(Beaneater::DrainingError.new(nil, nil))
|
40
|
-
assert_raises(Beaneater::DrainingError) { @tube.put "bar put #{@time}" }
|
29
|
+
it "should support custom serializer" do
|
30
|
+
Beaneater.configure.job_serializer = lambda { |b| JSON.dump(b) }
|
31
|
+
@tube.put({ foo: "bar"})
|
32
|
+
assert_equal '{"foo":"bar"}', @tube.peek(:ready).body
|
41
33
|
end
|
42
34
|
|
43
35
|
after do
|
44
36
|
Beaneater::Connection.any_instance.unstub(:transmit)
|
37
|
+
Beaneater.configure.job_serializer = lambda { |b| b }
|
45
38
|
end
|
46
39
|
end # put
|
47
40
|
|
@@ -140,7 +133,7 @@ describe Beaneater::Tube do
|
|
140
133
|
describe "for #pause" do
|
141
134
|
before do
|
142
135
|
@time = Time.now.to_i
|
143
|
-
@tube = Beaneater::Tube.new(@
|
136
|
+
@tube = Beaneater::Tube.new(@beanstalk, 'bam')
|
144
137
|
@tube.put "foo pause #{@time}"
|
145
138
|
end
|
146
139
|
|
@@ -164,7 +157,7 @@ describe Beaneater::Tube do
|
|
164
157
|
end
|
165
158
|
|
166
159
|
it "should raise error for empty tube" do
|
167
|
-
assert_raises(Beaneater::NotFoundError) { @
|
160
|
+
assert_raises(Beaneater::NotFoundError) { @beanstalk.tubes.find('fake_tube').stats }
|
168
161
|
end
|
169
162
|
end # stats
|
170
163
|
|
@@ -198,12 +191,8 @@ describe Beaneater::Tube do
|
|
198
191
|
tube_counts = lambda { %w(ready buried delayed).map { |s| @tube.stats["current_jobs_#{s}"] } }
|
199
192
|
assert_equal [2, 2, 2], tube_counts.call
|
200
193
|
@tube.clear
|
201
|
-
|
194
|
+
@tube.stats
|
202
195
|
assert_equal [0, 0, 0], tube_counts.call
|
203
196
|
end
|
204
197
|
end # clear
|
205
|
-
|
206
|
-
after do
|
207
|
-
cleanup_tubes!(['baz'])
|
208
|
-
end
|
209
|
-
end # Beaneater::Tubes
|
198
|
+
end # Beaneater::Tube
|
data/test/tubes_test.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
# test/
|
1
|
+
# test/tubes_test.rb
|
2
2
|
|
3
3
|
require File.expand_path('../test_helper', __FILE__)
|
4
4
|
|
5
5
|
describe Beaneater::Tubes do
|
6
6
|
describe "for #find" do
|
7
7
|
before do
|
8
|
-
@
|
9
|
-
@tubes = Beaneater::Tubes.new(@
|
8
|
+
@beanstalk = stub
|
9
|
+
@tubes = Beaneater::Tubes.new(@beanstalk)
|
10
10
|
end
|
11
11
|
|
12
12
|
it("should return Tube obj") { assert_kind_of Beaneater::Tube, @tubes.find(:foo) }
|
@@ -16,143 +16,148 @@ describe Beaneater::Tubes do
|
|
16
16
|
|
17
17
|
describe "for #use" do
|
18
18
|
before do
|
19
|
-
@
|
19
|
+
@beanstalk = Beaneater.new('localhost')
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should switch to used tube for valid name" do
|
23
|
-
|
24
|
-
@
|
25
|
-
assert_equal 'some_name', @
|
23
|
+
Beaneater::Tube.new(@beanstalk, 'some_name')
|
24
|
+
@beanstalk.tubes.use('some_name')
|
25
|
+
assert_equal 'some_name', @beanstalk.tubes.used.name
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should raise for invalid tube name" do
|
29
|
-
assert_raises(Beaneater::InvalidTubeName) { @
|
29
|
+
assert_raises(Beaneater::InvalidTubeName) { @beanstalk.tubes.use('; ') }
|
30
30
|
end
|
31
31
|
end # use
|
32
32
|
|
33
33
|
describe "for #watch & #watched" do
|
34
34
|
before do
|
35
|
-
@
|
35
|
+
@beanstalk = Beaneater.new('localhost')
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'should watch specified tubes' do
|
39
|
-
@
|
40
|
-
@
|
41
|
-
assert_equal ['default', 'foo', 'bar'].sort, @
|
39
|
+
@beanstalk.tubes.watch('foo')
|
40
|
+
@beanstalk.tubes.watch('bar')
|
41
|
+
assert_equal ['default', 'foo', 'bar'].sort, @beanstalk.tubes.watched.map(&:name).sort
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'should raise invalid name for bad tube' do
|
45
|
-
assert_raises(Beaneater::InvalidTubeName) { @
|
45
|
+
assert_raises(Beaneater::InvalidTubeName) { @beanstalk.tubes.watch('; ') }
|
46
46
|
end
|
47
47
|
end # watch! & watched
|
48
48
|
|
49
49
|
describe "for #all" do
|
50
50
|
before do
|
51
|
-
@
|
52
|
-
@
|
53
|
-
@
|
51
|
+
@beanstalk = Beaneater.new('localhost')
|
52
|
+
@beanstalk.tubes.find('foo').put 'bar'
|
53
|
+
@beanstalk.tubes.find('bar').put 'foo'
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should retrieve all tubes' do
|
57
57
|
['default', 'foo', 'bar'].each do |t|
|
58
|
-
assert @
|
58
|
+
assert @beanstalk.tubes.all.map(&:name).include?(t)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end # all
|
62
62
|
|
63
|
+
describe "for Enumerable" do
|
64
|
+
before do
|
65
|
+
@beanstalk = Beaneater.new('localhost')
|
66
|
+
@beanstalk.tubes.find('foo').put 'bar'
|
67
|
+
@beanstalk.tubes.find('bar').put 'foo'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should map tubes' do
|
71
|
+
['default', 'foo', 'bar'].each do |t|
|
72
|
+
assert @beanstalk.tubes.map(&:name).include?(t)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
63
77
|
describe "for #used" do
|
64
78
|
before do
|
65
|
-
@
|
66
|
-
@
|
67
|
-
@
|
79
|
+
@beanstalk = Beaneater.new('localhost')
|
80
|
+
@beanstalk.tubes.find('foo').put 'bar'
|
81
|
+
@beanstalk.tubes.find('bar').put 'foo'
|
68
82
|
end
|
69
83
|
|
70
84
|
it 'should retrieve used tube' do
|
71
|
-
assert_equal 'bar', @
|
85
|
+
assert_equal 'bar', @beanstalk.tubes.used.name
|
72
86
|
end
|
73
87
|
|
74
88
|
it 'should support dashed tubes' do
|
75
|
-
@
|
76
|
-
assert_equal 'der-bam', @
|
89
|
+
@beanstalk.tubes.find('der-bam').put 'foo'
|
90
|
+
assert_equal 'der-bam', @beanstalk.tubes.used.name
|
77
91
|
end
|
78
92
|
end # used
|
79
93
|
|
80
94
|
describe "for #watch!" do
|
81
95
|
before do
|
82
|
-
@
|
96
|
+
@beanstalk = Beaneater.new('localhost')
|
83
97
|
end
|
84
98
|
|
85
99
|
it 'should watch specified tubes' do
|
86
|
-
@
|
87
|
-
@
|
88
|
-
assert_equal ['bar'].sort, @
|
100
|
+
@beanstalk.tubes.watch!(:foo)
|
101
|
+
@beanstalk.tubes.watch!('bar')
|
102
|
+
assert_equal ['bar'].sort, @beanstalk.tubes.watched.map(&:name).sort
|
89
103
|
end
|
90
104
|
end # watch!
|
91
105
|
|
92
106
|
describe "for #ignore" do
|
93
107
|
before do
|
94
|
-
@
|
108
|
+
@beanstalk = Beaneater.new('localhost')
|
95
109
|
end
|
96
110
|
|
97
111
|
it 'should ignore specified tubes' do
|
98
|
-
@
|
99
|
-
@
|
100
|
-
@
|
101
|
-
assert_equal ['default', 'bar'].sort, @
|
112
|
+
@beanstalk.tubes.watch('foo')
|
113
|
+
@beanstalk.tubes.watch('bar')
|
114
|
+
@beanstalk.tubes.ignore('foo')
|
115
|
+
assert_equal ['default', 'bar'].sort, @beanstalk.tubes.watched.map(&:name).sort
|
102
116
|
end
|
103
117
|
end # ignore
|
104
118
|
|
105
119
|
describe "for #reserve" do
|
106
120
|
before do
|
107
|
-
@
|
108
|
-
@tube = @
|
121
|
+
@beanstalk = Beaneater.new('localhost')
|
122
|
+
@tube = @beanstalk.tubes.find 'tube'
|
109
123
|
@time = Time.now.to_i
|
110
124
|
@tube.put "foo reserve #{@time}"
|
111
125
|
end
|
112
126
|
|
113
127
|
it("should reserve job") do
|
114
|
-
@
|
115
|
-
job = @
|
128
|
+
@beanstalk.tubes.watch 'tube'
|
129
|
+
job = @beanstalk.tubes.reserve
|
116
130
|
assert_equal "foo reserve #{@time}", job.body
|
117
131
|
job.delete
|
118
132
|
end
|
119
133
|
|
120
134
|
it("should reserve job with block") do
|
121
|
-
@
|
135
|
+
@beanstalk.tubes.watch 'tube'
|
122
136
|
job = nil
|
123
|
-
@
|
137
|
+
@beanstalk.tubes.reserve { |j| job = j; job.delete }
|
124
138
|
assert_equal "foo reserve #{@time}", job.body
|
125
139
|
end
|
126
140
|
|
127
141
|
it("should reserve job with block and timeout") do
|
128
|
-
@
|
142
|
+
@beanstalk.tubes.watch 'tube'
|
129
143
|
job = nil
|
130
|
-
|
144
|
+
@beanstalk.tubes.reserve(0) { |j| job = j; job.delete }
|
131
145
|
assert_equal "foo reserve #{@time}", job.body
|
132
146
|
end
|
133
147
|
|
134
148
|
it "should raise TimedOutError with timeout" do
|
135
|
-
@
|
136
|
-
@
|
137
|
-
assert_raises(Beaneater::TimedOutError) { @
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should raise TimedOutError no delete, with timeout" do
|
141
|
-
@pool.tubes.watch 'tube'
|
142
|
-
@pool.tubes.reserve(0) { |j| job = j; job.delete }
|
143
|
-
assert_raises(Beaneater::TimedOutError) { @pool.tubes.reserve(0) }
|
149
|
+
@beanstalk.tubes.watch 'tube'
|
150
|
+
@beanstalk.tubes.reserve(0) { |j| job = j; job.delete }
|
151
|
+
assert_raises(Beaneater::TimedOutError) { @beanstalk.tubes.reserve(0) }
|
144
152
|
end
|
145
153
|
|
146
154
|
it "should raise DeadlineSoonError with ttr 1" do
|
147
155
|
@tube.reserve.delete
|
148
156
|
@tube.put "foo reserve #{@time}", :ttr => 1
|
149
|
-
@
|
150
|
-
@
|
151
|
-
assert_raises(Beaneater::DeadlineSoonError) { @
|
157
|
+
@beanstalk.tubes.watch 'tube'
|
158
|
+
@beanstalk.tubes.reserve
|
159
|
+
assert_raises(Beaneater::DeadlineSoonError) { @beanstalk.tubes.reserve(0) }
|
152
160
|
end
|
153
161
|
|
154
|
-
after do
|
155
|
-
cleanup_tubes!(['foo', 'tube'])
|
156
|
-
end
|
157
162
|
end # reserve
|
158
|
-
end # Beaneater::Tubes
|
163
|
+
end # Beaneater::Tubes
|
metadata
CHANGED
@@ -1,110 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beaneater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Nico Taing
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2021-04-27 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: minitest
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 4.1.0
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 4.1.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: mocha
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: fakeweb
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ! '>='
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
52
|
+
- - ">="
|
76
53
|
- !ruby/object:Gem::Version
|
77
54
|
version: '0'
|
78
55
|
- !ruby/object:Gem::Dependency
|
79
56
|
name: term-ansicolor
|
80
57
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
58
|
requirements:
|
83
|
-
- -
|
59
|
+
- - ">="
|
84
60
|
- !ruby/object:Gem::Version
|
85
61
|
version: '0'
|
86
62
|
type: :development
|
87
63
|
prerelease: false
|
88
64
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
65
|
requirements:
|
91
|
-
- -
|
66
|
+
- - ">="
|
92
67
|
- !ruby/object:Gem::Version
|
93
68
|
version: '0'
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
70
|
name: json
|
96
71
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
72
|
requirements:
|
99
|
-
- -
|
73
|
+
- - ">="
|
100
74
|
- !ruby/object:Gem::Version
|
101
75
|
version: '0'
|
102
76
|
type: :development
|
103
77
|
prerelease: false
|
104
78
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
79
|
requirements:
|
107
|
-
- -
|
80
|
+
- - ">="
|
108
81
|
- !ruby/object:Gem::Version
|
109
82
|
version: '0'
|
110
83
|
description: Simple beanstalkd client for ruby
|
@@ -114,8 +87,9 @@ executables: []
|
|
114
87
|
extensions: []
|
115
88
|
extra_rdoc_files: []
|
116
89
|
files:
|
117
|
-
- .gitignore
|
118
|
-
- .
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
|
+
- ".yardopts"
|
119
93
|
- CHANGELOG.md
|
120
94
|
- Gemfile
|
121
95
|
- LICENSE.txt
|
@@ -131,8 +105,6 @@ files:
|
|
131
105
|
- lib/beaneater/job.rb
|
132
106
|
- lib/beaneater/job/collection.rb
|
133
107
|
- lib/beaneater/job/record.rb
|
134
|
-
- lib/beaneater/pool.rb
|
135
|
-
- lib/beaneater/pool_command.rb
|
136
108
|
- lib/beaneater/stats.rb
|
137
109
|
- lib/beaneater/stats/fast_struct.rb
|
138
110
|
- lib/beaneater/stats/stat_struct.rb
|
@@ -145,8 +117,6 @@ files:
|
|
145
117
|
- test/errors_test.rb
|
146
118
|
- test/job_test.rb
|
147
119
|
- test/jobs_test.rb
|
148
|
-
- test/pool_command_test.rb
|
149
|
-
- test/pool_test.rb
|
150
120
|
- test/prompt_regexp_test.rb
|
151
121
|
- test/stat_struct_test.rb
|
152
122
|
- test/stats_test.rb
|
@@ -154,34 +124,27 @@ files:
|
|
154
124
|
- test/tube_test.rb
|
155
125
|
- test/tubes_test.rb
|
156
126
|
homepage: ''
|
157
|
-
licenses:
|
158
|
-
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata: {}
|
130
|
+
post_install_message:
|
159
131
|
rdoc_options: []
|
160
132
|
require_paths:
|
161
133
|
- lib
|
162
134
|
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
-
none: false
|
164
135
|
requirements:
|
165
|
-
- -
|
136
|
+
- - ">="
|
166
137
|
- !ruby/object:Gem::Version
|
167
138
|
version: '0'
|
168
|
-
segments:
|
169
|
-
- 0
|
170
|
-
hash: -394754542791428871
|
171
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
-
none: false
|
173
140
|
requirements:
|
174
|
-
- -
|
141
|
+
- - ">="
|
175
142
|
- !ruby/object:Gem::Version
|
176
143
|
version: '0'
|
177
|
-
segments:
|
178
|
-
- 0
|
179
|
-
hash: -394754542791428871
|
180
144
|
requirements: []
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
specification_version: 3
|
145
|
+
rubygems_version: 3.0.8
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
185
148
|
summary: Simple beanstalkd client for ruby.
|
186
149
|
test_files:
|
187
150
|
- test/beaneater_test.rb
|
@@ -189,12 +152,9 @@ test_files:
|
|
189
152
|
- test/errors_test.rb
|
190
153
|
- test/job_test.rb
|
191
154
|
- test/jobs_test.rb
|
192
|
-
- test/pool_command_test.rb
|
193
|
-
- test/pool_test.rb
|
194
155
|
- test/prompt_regexp_test.rb
|
195
156
|
- test/stat_struct_test.rb
|
196
157
|
- test/stats_test.rb
|
197
158
|
- test/test_helper.rb
|
198
159
|
- test/tube_test.rb
|
199
160
|
- test/tubes_test.rb
|
200
|
-
has_rdoc:
|
data/lib/beaneater/pool.rb
DELETED
@@ -1,166 +0,0 @@
|
|
1
|
-
# Simple ruby client for interacting with beanstalkd.
|
2
|
-
module Beaneater
|
3
|
-
# Represents collection of beanstalkd connections.
|
4
|
-
class Pool
|
5
|
-
# Default number of retries to send a command to a connection
|
6
|
-
MAX_RETRIES = 3
|
7
|
-
|
8
|
-
# @!attribute connections
|
9
|
-
# @return [Array<Beaneater::Connection>] returns Collection of connections
|
10
|
-
attr_reader :connections
|
11
|
-
|
12
|
-
# Initialize new connection
|
13
|
-
#
|
14
|
-
# @param [Array<String>] addresses Array of beanstalkd server addresses
|
15
|
-
# @example
|
16
|
-
# Beaneater::Pool.new(['localhost:11300', '127.0.0.1:11300'])
|
17
|
-
#
|
18
|
-
# ENV['BEANSTALKD_URL'] = 'localhost:11300,127.0.0.1:11300'
|
19
|
-
# @bp = Beaneater::Pool.new
|
20
|
-
# @bp.connections.first.host # => 'localhost'
|
21
|
-
# @bp.connections.last.host # => '127.0.0.1'
|
22
|
-
#
|
23
|
-
def initialize(addresses=nil)
|
24
|
-
addresses = addresses || host_from_env || Beaneater.configuration.beanstalkd_url
|
25
|
-
@connections = Array(addresses).map { |a| Connection.new(a) }
|
26
|
-
end
|
27
|
-
|
28
|
-
# Returns Beaneater::Stats object for accessing beanstalk stats.
|
29
|
-
#
|
30
|
-
# @return [Beaneater::Stats] stats object
|
31
|
-
# @api public
|
32
|
-
def stats
|
33
|
-
@stats ||= Stats.new(self)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Returns Beaneater::Jobs object for accessing job related functions.
|
37
|
-
#
|
38
|
-
# @return [Beaneater::Jobs] jobs object
|
39
|
-
# @api public
|
40
|
-
def jobs
|
41
|
-
@jobs ||= Jobs.new(self)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Returns Beaneater::Tubes object for accessing tube related functions.
|
45
|
-
#
|
46
|
-
# @return [Beaneater::Tubes] tubes object
|
47
|
-
# @api public
|
48
|
-
def tubes
|
49
|
-
@tubes ||= Tubes.new(self)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Sends command to every beanstalkd server set in the pool.
|
53
|
-
#
|
54
|
-
# @param [String] command Beanstalkd command
|
55
|
-
# @param [Hash{String => String, Boolean}] options socket connections options
|
56
|
-
# @param [Proc] block Block passed to socket connection during transmit
|
57
|
-
# @return [Array<Hash{String => String, Number}>] Beanstalkd command response from each instance
|
58
|
-
# @example
|
59
|
-
# @pool.transmit_to_all("stats")
|
60
|
-
#
|
61
|
-
def transmit_to_all(command, options={}, &block)
|
62
|
-
res_exception = nil
|
63
|
-
res = connections.map { |conn|
|
64
|
-
begin
|
65
|
-
safe_transmit { conn.transmit(command, options, &block) }
|
66
|
-
rescue UnexpectedResponse => ex # not the correct status
|
67
|
-
res_exception = ex
|
68
|
-
nil
|
69
|
-
end
|
70
|
-
}.compact
|
71
|
-
raise res_exception if res.none? && res_exception
|
72
|
-
res
|
73
|
-
end
|
74
|
-
|
75
|
-
# Send command to each beanstalkd servers until getting response expected
|
76
|
-
#
|
77
|
-
# @param [String] command Beanstalkd command
|
78
|
-
# @param [Hash{String => String, Boolean}] options socket connections options
|
79
|
-
# @param [Proc] block Block passed in socket connection object
|
80
|
-
# @return [Array<Hash{String => String, Number}>] Beanstalkd command response from the instance
|
81
|
-
# @example
|
82
|
-
# @pool.transmit_until_res('peek-ready', :status => "FOUND", &block)
|
83
|
-
#
|
84
|
-
def transmit_until_res(command, options={}, &block)
|
85
|
-
status_expected = options.delete(:status)
|
86
|
-
res_exception = nil
|
87
|
-
connections.each do |conn|
|
88
|
-
begin
|
89
|
-
res = safe_transmit { conn.transmit(command, options, &block) }
|
90
|
-
return res if res[:status] == status_expected
|
91
|
-
rescue UnexpectedResponse => ex # not the correct status
|
92
|
-
res_exception = ex
|
93
|
-
next
|
94
|
-
end
|
95
|
-
end
|
96
|
-
raise res_exception if res_exception
|
97
|
-
end
|
98
|
-
|
99
|
-
# Sends command to a random beanstalkd server in the pool.
|
100
|
-
#
|
101
|
-
# @param [String] command Beanstalkd command
|
102
|
-
# @param [Hash{String => String,Boolean}] options socket connections options
|
103
|
-
# @param [Proc] block Block passed in socket connection object
|
104
|
-
# @return [Array<Hash{String => String, Number}>] Beanstalkd command response from the instance
|
105
|
-
# @example
|
106
|
-
# @pool.transmit_to_rand("stats", :match => /\n/)
|
107
|
-
#
|
108
|
-
def transmit_to_rand(command, options={}, &block)
|
109
|
-
safe_transmit do
|
110
|
-
conn = connections.respond_to?(:sample) ? connections.sample : connections.choice
|
111
|
-
conn.transmit(command, options, &block)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Closes all connections within the pool.
|
116
|
-
#
|
117
|
-
# @example
|
118
|
-
# @pool.close
|
119
|
-
#
|
120
|
-
def close
|
121
|
-
while @connections.any?
|
122
|
-
conn = @connections.pop
|
123
|
-
conn.close
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
protected
|
128
|
-
|
129
|
-
# Transmit command to beanstalk connections safely handling failed connections
|
130
|
-
#
|
131
|
-
# @param [Proc] block The command to execute.
|
132
|
-
# @return [Object] Result of the block passed
|
133
|
-
# @raise [Beaneater::DrainingError,Beaneater::NotConnected] Could not connect to Beanstalk client
|
134
|
-
# @example
|
135
|
-
# safe_transmit { conn.transmit('foo') }
|
136
|
-
# # => "result of foo command from beanstalk"
|
137
|
-
#
|
138
|
-
def safe_transmit(&block)
|
139
|
-
retries = 1
|
140
|
-
begin
|
141
|
-
yield
|
142
|
-
rescue DrainingError, EOFError, Errno::ECONNRESET, Errno::EPIPE => ex
|
143
|
-
# TODO remove faulty connections from pool?
|
144
|
-
# https://github.com/kr/beanstalk-client-ruby/blob/master/lib/beanstalk-client/connection.rb#L405-410
|
145
|
-
if retries < MAX_RETRIES
|
146
|
-
retries += 1
|
147
|
-
retry
|
148
|
-
else # finished retrying, fail out
|
149
|
-
ex.is_a?(DrainingError) ? raise(ex) : raise(NotConnected, "Could not connect!")
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end # transmit_call
|
153
|
-
|
154
|
-
# The hosts provided by BEANSTALKD_URL environment variable, if available.
|
155
|
-
#
|
156
|
-
# @return [Array] Set of beanstalkd host addresses
|
157
|
-
# @example
|
158
|
-
# ENV['BEANSTALKD_URL'] = "localhost:1212,localhost:2424"
|
159
|
-
# # => ['localhost:1212', 'localhost:2424']
|
160
|
-
#
|
161
|
-
def host_from_env
|
162
|
-
ENV['BEANSTALKD_URL'].respond_to?(:length) && ENV['BEANSTALKD_URL'].length > 0 && ENV['BEANSTALKD_URL'].split(',').map(&:strip)
|
163
|
-
end
|
164
|
-
|
165
|
-
end # Pool
|
166
|
-
end # Beaneater
|