beaneater 0.3.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/beanstalkd/beaneater.png)](http://travis-ci.org/beanstalkd/beaneater)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/beanstalkd/beaneater/badge.png?branch=master)](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
|