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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 60e34aa7bfb6dc0a66ce540b609fa2ed112af52a7defcb3d7148efdbf9a8d213
|
4
|
+
data.tar.gz: 36c9c9cf9a1d2330243f4f8dbd664318bda4b702ecc1c160e9a288255b211764
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e447f52b2790b98867e613009d7a31b3cc2af0c116656fe209514000f0a023d662a850328a3242609590f1a2fdfd9f006936f24aaf9b04d86d44f2a7b40a2dd4
|
7
|
+
data.tar.gz: 90eca2d3c5db4c0c96a0bfccc774d894c2d942f9ea52979f15a0a5f6b0bb39990299896a994e56f7c60537e015fc152b7fa030293c980498b545e8f5c52cb411
|
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.5
|
4
|
+
- 2.6
|
5
|
+
- 2.7
|
6
|
+
- 3.0
|
7
|
+
before_install:
|
8
|
+
- curl -L https://github.com/kr/beanstalkd/archive/v1.9.tar.gz | tar xz -C /tmp
|
9
|
+
- cd /tmp/beanstalkd-1.9/
|
10
|
+
- make
|
11
|
+
- ./beanstalkd &
|
12
|
+
- cd $TRAVIS_BUILD_DIR
|
13
|
+
script:
|
14
|
+
- bundle install
|
15
|
+
- bundle exec rake test:full
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,41 @@
|
|
1
1
|
# CHANGELOG for Beaneater
|
2
2
|
|
3
|
-
##
|
3
|
+
## 1.1.1 (April 27th 2021)
|
4
|
+
|
5
|
+
* Support Ruby 3 keyword arguments (@yahonda)
|
6
|
+
* Add CI for Ruby 3 (@yahonda)
|
7
|
+
|
8
|
+
## 1.1.0 (April 25th 2021)
|
9
|
+
|
10
|
+
* 'clear' behavior was failing unexpectedly, swallow issues during delete as well (@bfolkens)
|
11
|
+
* Fix assigned but unused variables (@utilum)
|
12
|
+
* Fix last_used tube not stored (@albb0920)
|
13
|
+
* Fix deprecation warning in ruby 2.7 (@albb0920)
|
14
|
+
* Fix watched tubes not restored after reconnect (@albb0920)
|
15
|
+
* Fix keyword arguemnt warning (@albb0920)
|
16
|
+
|
17
|
+
## 1.0.0 (April 26th 2015)
|
18
|
+
|
19
|
+
* Beginning from version 1.0.0 the support for `Beaneater::Pool` has been dropped (@alup)
|
20
|
+
* `Jobs#find_all` method has been removed, since it is no longer necessary after removing pool (@alup)
|
21
|
+
* `Tubes` is now an enumerable allowing `tubes` to be handled as a collection (@Aethelflaed)
|
22
|
+
|
23
|
+
## 0.3.3 (August 16th 2014)
|
24
|
+
|
25
|
+
* Fix failure when job is not defined and fix exception handling for jobs (@nicholasorenrawlings)
|
26
|
+
* Add reserve_timeout option to job processing (@nicholasorenrawlings)
|
27
|
+
* Add travis-ci badge (@tdg5)
|
28
|
+
* Fix tests to run more reliably (@tdg5)
|
29
|
+
|
30
|
+
## 0.3.2 (Sept 15 2013)
|
31
|
+
|
32
|
+
* Fix #29 ExpectedCrlfError name and invocation (@tdg5)
|
33
|
+
|
34
|
+
## 0.3.1 (Jun 28 2013)
|
35
|
+
|
36
|
+
* Fixes issue with "chomp" nil exception when losing connection (Thanks @simao)
|
37
|
+
* Better handling of unknown or invalid commands during transmit
|
38
|
+
* Raise proper CRLF exception (Thanks @carlosmoutinho)
|
4
39
|
|
5
40
|
## 0.3.0 (Jan 23 2013)
|
6
41
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# Beaneater
|
2
|
+
[](http://travis-ci.org/beanstalkd/beaneater)
|
3
|
+
[](https://coveralls.io/r/beanstalkd/beaneater)
|
2
4
|
|
3
5
|
Beaneater is the best way to interact with beanstalkd from within Ruby.
|
4
6
|
[Beanstalkd](http://kr.github.com/beanstalkd/) is a simple, fast work queue. Its interface is generic, but was
|
5
7
|
originally designed for reducing the latency of page views in high-volume web applications by
|
6
8
|
running time-consuming tasks asynchronously. Read the [yardocs](http://rdoc.info/github/beanstalkd/beaneater) and/or the
|
7
|
-
[beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.
|
9
|
+
[beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt) for more details.
|
8
10
|
|
11
|
+
**Important Note**: This README is **for branch 1.0.x which is under development**. Please switch to latest `0.x` branch for stable version.
|
9
12
|
|
10
13
|
## Why Beanstalk?
|
11
14
|
|
@@ -81,13 +84,25 @@ gem 'beaneater'
|
|
81
84
|
|
82
85
|
and run `bundle install` to install the dependency.
|
83
86
|
|
87
|
+
## Breaking Changes since 1.0!
|
88
|
+
|
89
|
+
Starting in 1.0, we removed the concept of the `Beaneater::Pool` which introduced considerable complexity into this gem.
|
90
|
+
|
91
|
+
* Beginning from version 1.0.0 the support for `Beaneater::Pool` has been dropped.
|
92
|
+
The specific feature may be supported again in the next versions as separate module
|
93
|
+
or through a separate gem. If you want to use the pool feature you should switch to
|
94
|
+
0.x stable branches instead.
|
95
|
+
* `Jobs#find_all` method has been removed, since it is no longer necessary.
|
96
|
+
|
97
|
+
To manage a pool of beanstalkd instances, we'd prefer to leave the handling to the developer or other higher-level libraries.
|
98
|
+
|
84
99
|
## Quick Overview:
|
85
100
|
|
86
101
|
The concise summary of how to use beaneater:
|
87
102
|
|
88
103
|
```ruby
|
89
104
|
# Connect to pool
|
90
|
-
@beanstalk = Beaneater
|
105
|
+
@beanstalk = Beaneater.new('localhost:11300')
|
91
106
|
# Enqueue jobs to tube
|
92
107
|
@tube = @beanstalk.tubes["my-tube"]
|
93
108
|
@tube.put '{ "key" : "foo" }', :pri => 5
|
@@ -95,7 +110,7 @@ The concise summary of how to use beaneater:
|
|
95
110
|
# Process jobs from tube
|
96
111
|
while @tube.peek(:ready)
|
97
112
|
job = @tube.reserve
|
98
|
-
puts "job value is #{job.body["key"]}!"
|
113
|
+
puts "job value is #{JSON.parse(job.body)["key"]}!"
|
99
114
|
job.delete
|
100
115
|
end
|
101
116
|
# Disconnect the pool
|
@@ -116,7 +131,8 @@ Beaneater.configure do |config|
|
|
116
131
|
# config.default_put_pri = 65536
|
117
132
|
# config.default_put_ttr = 120
|
118
133
|
# config.job_parser = lambda { |body| body }
|
119
|
-
# config.
|
134
|
+
# config.job_serializer = lambda { |body| body }
|
135
|
+
# config.beanstalkd_url = 'localhost:11300'
|
120
136
|
end
|
121
137
|
```
|
122
138
|
|
@@ -124,18 +140,17 @@ The above options are all defaults, so only include a configuration block if you
|
|
124
140
|
|
125
141
|
### Connection
|
126
142
|
|
127
|
-
To interact with a beanstalk queue, first establish a connection by providing
|
143
|
+
To interact with a beanstalk queue, first establish a connection by providing an address:
|
128
144
|
|
129
145
|
```ruby
|
130
|
-
@beanstalk = Beaneater
|
146
|
+
@beanstalk = Beaneater.new('10.0.1.5:11300')
|
131
147
|
|
132
|
-
# Or if ENV['BEANSTALKD_URL] == '
|
133
|
-
@beanstalk = Beaneater
|
134
|
-
@beanstalk.
|
135
|
-
@beanstalk.connections.last # => 127.0.0.1:11300
|
148
|
+
# Or if ENV['BEANSTALKD_URL'] == '127.0.0.1:11300'
|
149
|
+
@beanstalk = Beaneater.new
|
150
|
+
@beanstalk.connection # => localhost:11300
|
136
151
|
```
|
137
152
|
|
138
|
-
You can conversely close and dispose of a
|
153
|
+
You can conversely close and dispose of a connection at any time with:
|
139
154
|
|
140
155
|
```ruby
|
141
156
|
@beanstalk.close
|
@@ -246,6 +261,16 @@ Beanstalkd can only stores strings as job bodies, but you can easily encode your
|
|
246
261
|
@tube.put({:foo => 'bar'}.to_json)
|
247
262
|
```
|
248
263
|
|
264
|
+
Moreover, you can provide a default job serializer by setting the corresponding configuration
|
265
|
+
option (`job_serializer`), in order to apply the encoding on each job body which
|
266
|
+
is going to be send using the `put` command. For example, to encode a ruby object to JSON format:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
Beaneater.configure do |config|
|
270
|
+
config.job_serializer = lambda { |body| JSON.dump(body) }
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
249
274
|
Each job has various metadata associated such as `priority`, `delay`, and `ttr` which can be
|
250
275
|
specified as part of the `put` command:
|
251
276
|
|
@@ -264,7 +289,7 @@ In order to process jobs, the client should first specify the intended tubes to
|
|
264
289
|
this will default to watching just the `default` tube.
|
265
290
|
|
266
291
|
```ruby
|
267
|
-
@beanstalk = Beaneater
|
292
|
+
@beanstalk = Beaneater.new('10.0.1.5:11300')
|
268
293
|
@beanstalk.tubes.watch!('tube-name', 'other-tube')
|
269
294
|
```
|
270
295
|
|
@@ -328,13 +353,6 @@ inspected using the 'peek' commands. To find and peek at a particular job based
|
|
328
353
|
# => <Beaneater::Job id=123 body="foo">
|
329
354
|
```
|
330
355
|
|
331
|
-
You can also `find_all` jobs across all connections:
|
332
|
-
|
333
|
-
```ruby
|
334
|
-
@beanstalk.jobs.find_all(123)
|
335
|
-
# => [<Beaneater::Job id=123 body="foo">, <Beaneater::Job id=123 body="bar">]
|
336
|
-
```
|
337
|
-
|
338
356
|
or you can peek at jobs within a tube:
|
339
357
|
|
340
358
|
```ruby
|
@@ -390,7 +408,9 @@ Processing runs the following steps:
|
|
390
408
|
1. If other exception occurs, call 'bury' (error)
|
391
409
|
1. Repeat steps 2-5
|
392
410
|
|
393
|
-
The `process
|
411
|
+
The `process!` command is ideally suited for a beanstalk job processing daemon.
|
412
|
+
Even though `process!` is intended to be a long-running process, you can stop the loop at any time
|
413
|
+
by raising `AbortProcessingError` while processing is running.
|
394
414
|
|
395
415
|
### Handling Errors
|
396
416
|
|
@@ -409,7 +429,7 @@ are listed below:
|
|
409
429
|
There are other exceptions that are less common such as `OutOfMemoryError`, `DrainingError`,
|
410
430
|
`DeadlineSoonError`, `InternalError`, `BadFormatError`, `UnknownCommandError`,
|
411
431
|
`ExpectedCRLFError`, `JobTooBigError`, `NotIgnoredError`. Be sure to check the
|
412
|
-
[beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.
|
432
|
+
[beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt) for more information.
|
413
433
|
|
414
434
|
|
415
435
|
### Stats
|
@@ -420,8 +440,9 @@ beanstalk overall:
|
|
420
440
|
```ruby
|
421
441
|
# Get overall stats about the job processing that has occurred
|
422
442
|
print @beanstalk.stats
|
423
|
-
# =>
|
424
|
-
|
443
|
+
# => #<Beaneater::StatStruct current_jobs_urgent=0, current_jobs_ready=0, current_jobs_reserved=0, current_jobs_delayed=0, current_jobs_buried=0, ...
|
444
|
+
|
445
|
+
print @beanstalk.stats.current_tubes
|
425
446
|
# => 1
|
426
447
|
```
|
427
448
|
|
@@ -441,7 +462,7 @@ print @beanstalk.jobs[some_job_id].stats
|
|
441
462
|
# => {'age': 0, 'id': 2, 'state': 'reserved', 'tube': 'default', ... }
|
442
463
|
```
|
443
464
|
|
444
|
-
Be sure to check the [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.
|
465
|
+
Be sure to check the [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt) for
|
445
466
|
more details about the stats commands.
|
446
467
|
|
447
468
|
## Resources
|
@@ -452,11 +473,14 @@ There are other resources helpful when learning about beanstalk:
|
|
452
473
|
* [Beaneater on Rubygems](https://rubygems.org/gems/beaneater)
|
453
474
|
* [Beanstalkd homepage](http://kr.github.com/beanstalkd/)
|
454
475
|
* [beanstalk on github](https://github.com/kr/beanstalkd)
|
455
|
-
* [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.
|
476
|
+
* [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.txt)
|
456
477
|
* [Backburner](https://github.com/nesquena/backburner) - Ruby job queue for Rails/Sinatra
|
478
|
+
* [BeanCounter](https://github.com/gemeraldbeanstalk/bean_counter) - TestUnit/MiniTest assertions and RSpec matchers for testing code that relies on Beaneater
|
457
479
|
|
458
480
|
## Contributors
|
459
481
|
|
460
482
|
- [Nico Taing](https://github.com/Nico-Taing) - Creator and co-maintainer
|
461
483
|
- [Nathan Esquenazi](https://github.com/nesquena) - Contributor and co-maintainer
|
462
|
-
- [Keith Rarick](https://github.com/kr) - Much code inspired and adapted from beanstalk-client
|
484
|
+
- [Keith Rarick](https://github.com/kr) - Much code inspired and adapted from beanstalk-client
|
485
|
+
- [Vidar Hokstad](https://github.com/vidarh) - Replaced telnet with correct TCP socket handling
|
486
|
+
- [Andreas Loupasakis](https://github.com/alup) - Improve test coverage, improve job configuration
|
data/Rakefile
CHANGED
data/beaneater.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.description = %q{Simple beanstalkd client for ruby}
|
12
12
|
gem.summary = %q{Simple beanstalkd client for ruby.}
|
13
13
|
gem.homepage = ""
|
14
|
+
gem.license = 'MIT'
|
14
15
|
|
15
16
|
gem.files = `git ls-files`.split($/)
|
16
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -19,7 +20,6 @@ Gem::Specification.new do |gem|
|
|
19
20
|
gem.add_development_dependency 'minitest', "~> 4.1.0"
|
20
21
|
gem.add_development_dependency 'rake'
|
21
22
|
gem.add_development_dependency 'mocha'
|
22
|
-
gem.add_development_dependency 'fakeweb'
|
23
23
|
gem.add_development_dependency 'term-ansicolor'
|
24
24
|
gem.add_development_dependency 'json'
|
25
25
|
end
|
data/examples/demo.rb
CHANGED
@@ -6,8 +6,7 @@ require 'beaneater'
|
|
6
6
|
|
7
7
|
# Establish a pool of beanstalks
|
8
8
|
puts step("Connecting to Beanstalk")
|
9
|
-
bc = Beaneater
|
10
|
-
# bc = Beaneater::Pool.new(['localhost', 'localhost:11301', 'localhost:11302'])
|
9
|
+
bc = Beaneater.new('localhost')
|
11
10
|
puts bc
|
12
11
|
|
13
12
|
# Print out key stats
|
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
class Beaneater
|
2
2
|
class Configuration
|
3
3
|
attr_accessor :default_put_delay # default delay value to put a job
|
4
4
|
attr_accessor :default_put_pri # default priority value to put a job
|
5
5
|
attr_accessor :default_put_ttr # default ttr value to put a job
|
6
6
|
attr_accessor :job_parser # default job_parser to parse job body
|
7
|
+
attr_accessor :job_serializer # default serializer for job body
|
7
8
|
attr_accessor :beanstalkd_url # default beanstalkd url
|
8
9
|
|
9
10
|
def initialize
|
@@ -11,6 +12,7 @@ module Beaneater
|
|
11
12
|
@default_put_pri = 65536
|
12
13
|
@default_put_ttr = 120
|
13
14
|
@job_parser = lambda { |body| body }
|
15
|
+
@job_serializer = lambda { |body| body }
|
14
16
|
@beanstalkd_url = nil
|
15
17
|
end
|
16
18
|
end # Configuration
|
data/lib/beaneater/connection.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'socket'
|
3
3
|
|
4
|
-
|
4
|
+
class Beaneater
|
5
5
|
# Represents a connection to a beanstalkd instance.
|
6
6
|
class Connection
|
7
7
|
|
8
|
+
# Default number of retries to send a command to a connection
|
9
|
+
MAX_RETRIES = 3
|
10
|
+
|
11
|
+
# Default retry interval
|
12
|
+
DEFAULT_RETRY_INTERVAL = 1
|
13
|
+
|
8
14
|
# @!attribute address
|
9
15
|
# @return [String] returns Beanstalkd server address
|
10
16
|
# @example
|
@@ -21,6 +27,12 @@ module Beaneater
|
|
21
27
|
# @return [Net::TCPSocket] returns connection object
|
22
28
|
attr_reader :address, :host, :port, :connection
|
23
29
|
|
30
|
+
# @!attribute tubes_watched
|
31
|
+
# @returns [Array<String>] returns currently watched tube names
|
32
|
+
# @!attribute tube_used
|
33
|
+
# @returns [String] returns currently used tube name
|
34
|
+
attr_accessor :tubes_watched, :tube_used
|
35
|
+
|
24
36
|
# Default port value for beanstalk connection
|
25
37
|
DEFAULT_PORT = 11300
|
26
38
|
|
@@ -28,13 +40,23 @@ module Beaneater
|
|
28
40
|
#
|
29
41
|
# @param [String] address beanstalkd instance address.
|
30
42
|
# @example
|
31
|
-
# Beaneater::Connection.new('
|
32
|
-
# Beaneater::Connection.new('
|
43
|
+
# Beaneater::Connection.new('127.0.0.1')
|
44
|
+
# Beaneater::Connection.new('127.0.0.1:11300')
|
45
|
+
#
|
46
|
+
# ENV['BEANSTALKD_URL'] = '127.0.0.1:11300'
|
47
|
+
# @b = Beaneater.new
|
48
|
+
# @b.connection.host # => '127.0.0.1'
|
49
|
+
# @b.connection.port # => '11300'
|
33
50
|
#
|
34
51
|
def initialize(address)
|
35
|
-
@address = address
|
36
|
-
@connection = establish_connection
|
52
|
+
@address = address || _host_from_env || Beaneater.configuration.beanstalkd_url
|
37
53
|
@mutex = Mutex.new
|
54
|
+
@tube_used = 'default'
|
55
|
+
@tubes_watched = ['default']
|
56
|
+
|
57
|
+
establish_connection
|
58
|
+
rescue
|
59
|
+
_raise_not_connected!
|
38
60
|
end
|
39
61
|
|
40
62
|
# Send commands to beanstalkd server via connection.
|
@@ -43,19 +65,21 @@ module Beaneater
|
|
43
65
|
# @param [String] command Beanstalkd command
|
44
66
|
# @return [Array<Hash{String => String, Number}>] Beanstalkd command response
|
45
67
|
# @example
|
68
|
+
# @conn = Beaneater::Connection.new
|
46
69
|
# @conn.transmit('bury 123')
|
70
|
+
# @conn.transmit('stats')
|
47
71
|
#
|
48
|
-
def transmit(command, options
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
72
|
+
def transmit(command, **options)
|
73
|
+
_with_retry(**options.slice(:retry_interval, :init)) do
|
74
|
+
@mutex.synchronize do
|
75
|
+
_raise_not_connected! unless connection
|
76
|
+
|
77
|
+
command = command.force_encoding('ASCII-8BIT') if command.respond_to?(:force_encoding)
|
78
|
+
connection.write(command.to_s + "\r\n")
|
79
|
+
res = connection.readline
|
80
|
+
parse_response(command, res)
|
81
|
+
end
|
56
82
|
end
|
57
|
-
ensure
|
58
|
-
@mutex.unlock
|
59
83
|
end
|
60
84
|
|
61
85
|
# Close connection with beanstalkd server.
|
@@ -64,8 +88,10 @@ module Beaneater
|
|
64
88
|
# @conn.close
|
65
89
|
#
|
66
90
|
def close
|
67
|
-
@connection
|
68
|
-
|
91
|
+
if @connection
|
92
|
+
@connection.close
|
93
|
+
@connection = nil
|
94
|
+
end
|
69
95
|
end
|
70
96
|
|
71
97
|
# Returns string representation of job.
|
@@ -78,23 +104,30 @@ module Beaneater
|
|
78
104
|
end
|
79
105
|
alias :inspect :to_s
|
80
106
|
|
107
|
+
def add_to_watched(tube_name)
|
108
|
+
@tubes_watched << tube_name
|
109
|
+
@tubes_watched.uniq
|
110
|
+
end
|
111
|
+
|
112
|
+
def remove_from_watched(tube_name)
|
113
|
+
@tubes_watched.delete(tube_name)
|
114
|
+
end
|
115
|
+
|
81
116
|
protected
|
82
117
|
|
83
118
|
# Establish a connection based on beanstalk address.
|
84
119
|
#
|
85
120
|
# @return [Net::TCPSocket] connection for specified address.
|
86
|
-
# @raise [
|
121
|
+
# @raise [Beaneater::NotConnected] Could not connect to specified beanstalkd instance.
|
87
122
|
# @example
|
88
123
|
# establish_connection('localhost:3005')
|
89
124
|
#
|
90
125
|
def establish_connection
|
91
|
-
@
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
rescue Exception => ex
|
97
|
-
raise NotConnected, "#{ex.class}: #{ex}"
|
126
|
+
@address = address.first if address.is_a?(Array)
|
127
|
+
match = address.split(':')
|
128
|
+
@host, @port = match[0], Integer(match[1] || DEFAULT_PORT)
|
129
|
+
|
130
|
+
@connection = TCPSocket.new @host, @port
|
98
131
|
end
|
99
132
|
|
100
133
|
# Parses the response and returns the useful beanstalk response.
|
@@ -102,11 +135,11 @@ module Beaneater
|
|
102
135
|
#
|
103
136
|
# @param [String] cmd Beanstalk command transmitted
|
104
137
|
# @param [String] res Telnet command response
|
105
|
-
# @return [Array<Hash{String => String, Number}>] Beanstalk response with `status`, `id`, `body
|
138
|
+
# @return [Array<Hash{String => String, Number}>] Beanstalk response with `status`, `id`, `body`
|
106
139
|
# @raise [Beaneater::UnexpectedResponse] Response from beanstalk command was an error status
|
107
140
|
# @example
|
108
141
|
# parse_response("delete 56", "DELETED 56\nFOO")
|
109
|
-
# # => { :body => "FOO", :status => "DELETED", :id => 56
|
142
|
+
# # => { :body => "FOO", :status => "DELETED", :id => 56 }
|
110
143
|
#
|
111
144
|
def parse_response(cmd, res)
|
112
145
|
status = res.chomp
|
@@ -119,12 +152,12 @@ module Beaneater
|
|
119
152
|
raw_body = connection.read(bytes_size)
|
120
153
|
body = status == 'OK' ? YAML.load(raw_body) : config.job_parser.call(raw_body)
|
121
154
|
crlf = connection.read(2) # \r\n
|
122
|
-
raise
|
155
|
+
raise ExpectedCrlfError.new('EXPECTED_CRLF', cmd) if crlf != "\r\n"
|
123
156
|
end
|
124
157
|
id = body_values[1]
|
125
|
-
response = { :status => status
|
158
|
+
response = { :status => status }
|
126
159
|
response[:id] = id if id
|
127
|
-
response[:
|
160
|
+
response[:body] = body if body
|
128
161
|
response
|
129
162
|
end
|
130
163
|
|
@@ -135,5 +168,77 @@ module Beaneater
|
|
135
168
|
Beaneater.configuration
|
136
169
|
end
|
137
170
|
|
171
|
+
private
|
172
|
+
|
173
|
+
def _initialize_tubes
|
174
|
+
if @tubes_watched != ['default']
|
175
|
+
tubes_watched.each do |t|
|
176
|
+
transmit("watch #{t}", init: false)
|
177
|
+
end
|
178
|
+
|
179
|
+
transmit("ignore default", init: false)
|
180
|
+
end
|
181
|
+
|
182
|
+
transmit("use #{tube_used}", init: false) if @tube_used != 'default'
|
183
|
+
end
|
184
|
+
|
185
|
+
# Wrapper method for capturing certain failures and retry the payload block
|
186
|
+
#
|
187
|
+
# @param [Proc] block The command to execute.
|
188
|
+
# @param [Integer] retry_interval The time to wait before the next retry
|
189
|
+
# @param [Integer] tries The maximum number of tries in draining mode
|
190
|
+
# @return [Object] Result of the block passed
|
191
|
+
#
|
192
|
+
def _with_retry(retry_interval: DEFAULT_RETRY_INTERVAL, init: true, tries: MAX_RETRIES, &block)
|
193
|
+
yield
|
194
|
+
rescue EOFError, Errno::ECONNRESET, Errno::EPIPE,
|
195
|
+
Errno::ECONNREFUSED => ex
|
196
|
+
_reconnect(ex, retry_interval)
|
197
|
+
_initialize_tubes if init
|
198
|
+
retry
|
199
|
+
rescue Beaneater::DrainingError
|
200
|
+
tries -= 1
|
201
|
+
if tries.zero?
|
202
|
+
close
|
203
|
+
raise
|
204
|
+
end
|
205
|
+
sleep(retry_interval)
|
206
|
+
retry
|
207
|
+
end
|
208
|
+
|
209
|
+
# Tries to re-establish connection to the beanstalkd
|
210
|
+
#
|
211
|
+
# @param [Exception] original_exception The exception caused the retry
|
212
|
+
# @param [Integer] retry_interval The time to wait before the next reconnect
|
213
|
+
# @param [Integer] tries The maximum number of attempts to reconnect
|
214
|
+
def _reconnect(original_exception, retry_interval, tries=MAX_RETRIES)
|
215
|
+
close
|
216
|
+
establish_connection
|
217
|
+
rescue Errno::ECONNREFUSED
|
218
|
+
tries -= 1
|
219
|
+
if tries.zero?
|
220
|
+
_raise_not_connected!
|
221
|
+
end
|
222
|
+
sleep(retry_interval || DEFAULT_RETRY_INTERVAL)
|
223
|
+
retry
|
224
|
+
end
|
225
|
+
|
226
|
+
# The host provided by BEANSTALKD_URL environment variable, if available.
|
227
|
+
#
|
228
|
+
# @return [String] A beanstalkd host address
|
229
|
+
# @example
|
230
|
+
# ENV['BEANSTALKD_URL'] = "localhost:1212"
|
231
|
+
# # => 'localhost:1212'
|
232
|
+
#
|
233
|
+
def _host_from_env
|
234
|
+
ENV['BEANSTALKD_URL'].respond_to?(:length) && ENV['BEANSTALKD_URL'].length > 0 && ENV['BEANSTALKD_URL'].strip
|
235
|
+
end
|
236
|
+
|
237
|
+
# Raises an error to be triggered when the connection has failed
|
238
|
+
# @raise [Beaneater::NotConnected] Beanstalkd is no longer connected
|
239
|
+
def _raise_not_connected!
|
240
|
+
raise Beaneater::NotConnected, "Connection to beanstalk '#{@host}:#{@port}' is closed!"
|
241
|
+
end
|
242
|
+
|
138
243
|
end # Connection
|
139
244
|
end # Beaneater
|
data/lib/beaneater/errors.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
class Beaneater
|
2
2
|
# Raises when a beanstalkd instance is no longer accessible.
|
3
3
|
class NotConnected < RuntimeError; end
|
4
4
|
# Raises when the tube name specified is invalid.
|
@@ -66,11 +66,11 @@ module Beaneater
|
|
66
66
|
# Raises when a command was sent that is unknown.
|
67
67
|
class UnknownCommandError < UnexpectedResponse; end
|
68
68
|
# Raises when command does not have proper CRLF suffix.
|
69
|
-
class
|
69
|
+
class ExpectedCrlfError < UnexpectedResponse; end
|
70
70
|
# Raises when the body of a job was too large.
|
71
71
|
class JobTooBigError < UnexpectedResponse; end
|
72
|
-
# Raises when a job was attempted to be reserved but the timeout
|
72
|
+
# Raises when a job was attempted to be reserved but the timeout occurred.
|
73
73
|
class TimedOutError < UnexpectedResponse; end
|
74
74
|
# Raises when a tube could not be ignored because it is the last watched tube.
|
75
75
|
class NotIgnoredError < UnexpectedResponse; end
|
76
|
-
end
|
76
|
+
end
|