beaneater 0.1.0 → 0.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.
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # CHANGELOG for Beaneater
2
+
3
+ ## 0.1.2 (Unreleased)
4
+
5
+ ## 0.1.1 (Nov 4 2012)
6
+
7
+ * Add `Jobs#find_all` to fix #10
8
+ * Fixed issue with `tubes-list` by merging results
9
+ * Add `Job#ttr`, `Job#pri`, `Job#delay`
10
+ * Improved yardocs coverage and accuracy
11
+
12
+ ## 0.1.0 (Nov 1 2012)
13
+
14
+ * Initial release!
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Beaneater is the best way to interact with beanstalkd from within Ruby.
4
4
  [Beanstalkd](http://kr.github.com/beanstalkd/) is a simple, fast work queue. Its interface is generic, but was
5
5
  originally designed for reducing the latency of page views in high-volume web applications by
6
- running time-consuming tasks asynchronously. Read the
6
+ running time-consuming tasks asynchronously. Read the [yardocs](http://rdoc.info/github/beanstalkd/beaneater) and/or the
7
7
  [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.md) for more details.
8
8
 
9
9
 
@@ -13,32 +13,35 @@ Illya has an excellent blog post
13
13
  [Scalable Work Queues with Beanstalk](http://www.igvita.com/2010/05/20/scalable-work-queues-with-beanstalk/) and
14
14
  Adam Wiggins posted [an excellent comparison](http://adam.heroku.com/past/2010/4/24/beanstalk_a_simple_and_fast_queueing_backend/).
15
15
 
16
- You will quickly see that **beanstalkd** is an underrated but incredible project that is extremely well-suited as a job queue.
17
- Significantly better suited for this task than Redis or a database. Beanstalk is a simple,
18
- and a very fast work queue service rolled into a single binary - it is the memcached of work queues.
19
- Originally built to power the backend for the 'Causes' Facebook app, it is a mature and production ready open source project.
20
- [PostRank](http://www.postrank.com) uses beanstalk to reliably process millions of jobs a day.
16
+ You will find that **beanstalkd** is an underrated but incredibly
17
+ powerful project that is extremely well-suited as a job or messaging queue.
18
+ Significantly better suited for this task than Redis or a traditional RDBMS. Beanstalk is a simple,
19
+ and fast work queue service rolled into a single binary - it is the memcached of work queues.
20
+ Originally built to power the backend for the 'Causes' Facebook app,
21
+ it is a mature and production ready open source project.
22
+ [PostRank](http://www.postrank.com) has used beanstalk to reliably process millions of jobs a day.
21
23
 
22
24
  A single instance of Beanstalk is perfectly capable of handling thousands of jobs a second (or more, depending on your job size)
23
25
  because it is an in-memory, event-driven system. Powered by libevent under the hood,
24
- it requires zero setup (launch and forget, à la memcached), optional log based persistence, an easily parsed ASCII protocol,
25
- and a rich set of tools for job management that go well beyond a simple FIFO work queue.
26
+ it requires zero setup (launch and forget, à la memcached), optional log based persistence,
27
+ an easily parsed ASCII protocol, and a rich set of tools for job management
28
+ that go well beyond a simple FIFO work queue.
26
29
 
27
30
  Beanstalkd supports the following features out of the box:
28
31
 
29
32
  | Feature | Description |
30
33
  | ------- | ------------------------------- |
31
- | **Parallel Queues** | Supports multiple work queues created on demand. |
34
+ | **Parallelized** | Supports multiple work queues created on demand. |
32
35
  | **Reliable** | Beanstalk’s reserve, work, delete cycle ensures reliable processing. |
33
36
  | **Scheduling** | Delay enqueuing jobs by a specified interval to schedule processing later |
34
- | **Fast** | Processes thousands of jobs per second; **significantly** faster than alternatives. |
37
+ | **Fast** | Processes thousands of jobs per second without breaking a sweat. |
35
38
  | **Priorities** | Specify priority so important jobs can be processed quickly. |
36
39
  | **Persistence** | Jobs are stored in memory for speed, but logged to disk for safe keeping. |
37
40
  | **Federation** | Horizontal scalability provided through federation by the client. |
38
41
  | **Error Handling** | Bury any job which causes an error for later debugging and inspection.|
39
42
 
40
- Keep in mind that these features are supported out of the box with beanstalk and require no special code within this gem to support.
41
- In the end, **beanstalk is the ideal job queue** while also being ridiculously easy to install and setup.
43
+ Keep in mind that these features are supported out of the box with beanstalk and requires no special ruby specific logic.
44
+ In the end, **beanstalk is the ideal job queue** and has the added benefit of being easy to setup and configure.
42
45
 
43
46
  ## Installation
44
47
 
@@ -47,7 +50,6 @@ Install beanstalkd:
47
50
  Mac OS
48
51
 
49
52
  ```
50
- brew update
51
53
  brew install beanstalkd
52
54
  beanstalkd -p 11300
53
55
  ```
@@ -74,6 +76,29 @@ gem 'beaneater'
74
76
 
75
77
  and run `bundle install` to install the dependency.
76
78
 
79
+ ## Quick Overview:
80
+
81
+ The concise summary of how to use beaneater:
82
+
83
+ ```ruby
84
+ # Connect to pool
85
+ @beanstalk = Beaneater::Pool.new(['localhost:11300'])
86
+ # Enqueue jobs to tube
87
+ @tube = @beanstalk.tubes["my-tube"]
88
+ @tube.put '{ "key" : "foo" }', :pri => 5
89
+ @tube.put '{ "key" : "bar" }', :delay => 3
90
+ # Process jobs from tube
91
+ while @tube.peek(:ready)
92
+ job = @tube.reserve
93
+ puts "job value is #{job.body["key"]}!"
94
+ job.delete
95
+ end
96
+ # Disconnect the pool
97
+ @beanstalk.close
98
+ ```
99
+
100
+ For a more detailed rundown, check out the __Usage__ section below.
101
+
77
102
  ## Usage
78
103
 
79
104
  ### Connection
@@ -82,6 +107,11 @@ To interact with a beanstalk queue, first establish a connection by providing a
82
107
 
83
108
  ```ruby
84
109
  @beanstalk = Beaneater::Pool.new(['10.0.1.5:11300'])
110
+
111
+ # Or if ENV['BEANSTALKD_URL] == 'localhost:11300,127.0.0.1:11300'
112
+ @beanstalk = Beaneater::Pool.new
113
+ @beanstalk.connections.first # => localhost:11300
114
+ @beanstalk.connections.last # => 127.0.0.1:11300
85
115
  ```
86
116
 
87
117
  You can conversely close and dispose of a pool at any time with:
@@ -277,6 +307,13 @@ inspected using the 'peek' commands. To find and peek at a particular job based
277
307
  # => <Beaneater::Job id=123 body="foo">
278
308
  ```
279
309
 
310
+ You can also `find_all` jobs across all connections:
311
+
312
+ ```ruby
313
+ @beanstalk.jobs.find_all(123)
314
+ # => [<Beaneater::Job id=123 body="foo">, <Beaneater::Job id=123 body="bar">]
315
+ ```
316
+
280
317
  or you can peek at jobs within a tube:
281
318
 
282
319
  ```ruby
@@ -346,6 +383,7 @@ are listed below:
346
383
  | Beaneater::InvalidTubeName | Specified tube name for use or watch is not valid. |
347
384
  | Beaneater::NotFoundError | Specified job or tube could not be found. |
348
385
  | Beaneater::TimedOutError | Job could not be reserved within time specified. |
386
+ | Beaneater::JobNotReserved | Job has not been reserved and action cannot be taken. |
349
387
 
350
388
  There are other exceptions that are less common such as `OutOfMemoryError`, `DrainingError`,
351
389
  `DeadlineSoonError`, `InternalError`, `BadFormatError`, `UnknownCommandError`,
@@ -389,11 +427,15 @@ more details about the stats commands.
389
427
 
390
428
  There are other resources helpful when learning about beanstalk:
391
429
 
430
+ * [Beaneater Yardocs](http://rdoc.info/github/beanstalkd/beaneater)
431
+ * [Beaneater on Rubygems](https://rubygems.org/gems/beaneater)
392
432
  * [Beanstalkd homepage](http://kr.github.com/beanstalkd/)
393
433
  * [beanstalk on github](https://github.com/kr/beanstalkd)
394
434
  * [beanstalk protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.md)
435
+ * [Backburner](https://github.com/nesquena/backburner) - Ruby job queue for Rails/Sinatra
395
436
 
396
437
  ## Contributors
397
438
 
398
439
  - [Nico Taing](https://github.com/Nico-Taing) - Creator and co-maintainer
399
- - [Nathan Esquenazi](https://github.com/nesquena) - Contributor and co-maintainer
440
+ - [Nathan Esquenazi](https://github.com/nesquena) - Contributor and co-maintainer
441
+ - [Keith Rarick](https://github.com/kr) - Much code inspired and adapted from beanstalk-client
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ require 'rake/testtask'
3
3
  require 'yard'
4
4
  require 'redcarpet'
5
5
 
6
+ # rake test
6
7
  Rake::TestTask.new do |t|
7
8
  t.libs.push "lib"
8
9
  t.test_files = FileList[File.expand_path('../test/**/*_test.rb', __FILE__)] -
@@ -10,6 +11,13 @@ Rake::TestTask.new do |t|
10
11
  t.verbose = true
11
12
  end
12
13
 
14
+ # rake test:integration
15
+ Rake::TestTask.new("test:integration") do |t|
16
+ t.libs.push "lib"
17
+ t.test_files = FileList[File.expand_path('../test/**/beaneater_test.rb', __FILE__)]
18
+ t.verbose = true
19
+ end
20
+
13
21
  # rake test:full
14
22
  Rake::TestTask.new("test:full") do |t|
15
23
  t.libs.push "lib"
data/TODO CHANGED
@@ -1,2 +1 @@
1
- - Add YARD docs for all classes (see REF file)
2
1
  - Remove connection from pool if it's not responding and be able to add more connections and reattempt later
@@ -1,42 +1,50 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Beaneater
4
- # Represents a connection to beanstalkd server
4
+ # Represents a connection to a beanstalkd instance.
5
5
  class Connection
6
6
 
7
- # @!attribute telnet_connection
8
- # @return [Net::Telnet] returns Telnet connection object
9
7
  # @!attribute address
10
8
  # @return [String] returns Beanstalkd server address
9
+ # @example
10
+ # @conn.address # => "localhost:11300"
11
11
  # @!attribute host
12
12
  # @return [String] returns Beanstalkd server host
13
+ # @example
14
+ # @conn.host # => "localhost"
13
15
  # @!attribute port
14
16
  # @return [Integer] returns Beanstalkd server port
15
- attr_reader :telnet_connection, :address, :host, :port
17
+ # @example
18
+ # @conn.port # => "11300"
19
+ # @!attribute telnet_connection
20
+ # @return [Net::Telnet] returns Telnet connection object
21
+ attr_reader :address, :host, :port, :telnet_connection
16
22
 
17
- # Default port value
23
+ # Default port value for beanstalk connection
18
24
  DEFAULT_PORT = 11300
19
25
 
20
- # Initialize new connection
26
+ # Initializes new connection.
21
27
  #
22
- # @param [String] address beanstalkd address
28
+ # @param [String] address beanstalkd instance address.
23
29
  # @example
24
30
  # Beaneater::Connection.new('localhost')
25
31
  # Beaneater::Connection.new('localhost:11300')
32
+ #
26
33
  def initialize(address)
27
34
  @address = address
28
35
  @telnet_connection = establish_connection
29
36
  @mutex = Mutex.new
30
37
  end
31
38
 
32
- # Send commands to beanstalkd server via telnet_connection
39
+ # Send commands to beanstalkd server via telnet_connection.
33
40
  #
34
41
  # @param [String] command Beanstalkd command
35
- # @param [Hash] options Settings for telnet
42
+ # @param [Hash{Symbol => String,Boolean}] options Settings for telnet
36
43
  # @option options [Boolean] FailEOF raises EOF Exeception
37
- #
44
+ # @return [Array<Hash{String => String, Number}>] Beanstalkd command response
38
45
  # @example
39
- # @beaneater_connection.transmit('bury 123')
46
+ # @conn.transmit('bury 123')
47
+ #
40
48
  def transmit(command, options={}, &block)
41
49
  @mutex.lock
42
50
  if telnet_connection
@@ -49,19 +57,21 @@ module Beaneater
49
57
  @mutex.unlock
50
58
  end
51
59
 
52
- # Close connection with beanstalkd server
60
+ # Close connection with beanstalkd server.
53
61
  #
54
62
  # @example
55
- # @beaneater_connection.close
63
+ # @conn.close
64
+ #
56
65
  def close
57
66
  @telnet_connection.close
58
67
  @telnet_connection = nil
59
68
  end
60
69
 
61
- # Returns string representation of job
70
+ # Returns string representation of job.
62
71
  #
63
72
  # @example
64
- # @beaneater_connection.inspect
73
+ # @conn.inspect
74
+ #
65
75
  def to_s
66
76
  "#<Beaneater::Connection host=#{host.inspect} port=#{port.inspect}>"
67
77
  end
@@ -90,7 +100,7 @@ module Beaneater
90
100
  #
91
101
  # @param [String] cmd Beanstalk command transmitted
92
102
  # @param [String] res Telnet command response
93
- # @return [Hash] Beanstalk command response with `status`, `id`, `body`, and `connection`
103
+ # @return [Array<Hash{String => String, Number}>] Beanstalk response with `status`, `id`, `body`, and `connection`
94
104
  # @raise [Beaneater::UnexpectedResponse] Response from beanstalk command was an error status
95
105
  # @example
96
106
  # parse_response("delete 56", "DELETED 56\nFOO")
@@ -1,5 +1,5 @@
1
1
  module Beaneater
2
- # Raises when the beanstalkd instance cannot be accessed
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.
5
5
  class InvalidTubeName < RuntimeError; end
@@ -15,13 +15,15 @@ module Beaneater
15
15
 
16
16
  # @!attribute status
17
17
  # @return [String] returns beanstalkd response status
18
+ # @example @ex.status # => "NOT_FOUND"
18
19
  # @!attribute cmd
19
20
  # @return [String] returns beanstalkd request command
21
+ # @example @ex.cmd # => "stats-job 23"
20
22
  attr_reader :status, :cmd
21
23
 
22
24
  # Initialize unexpected response error
23
25
  #
24
- # @param [UnexpectedResponse] status Unexpected response object
26
+ # @param [Beaneater::UnexpectedResponse] status Unexpected response object
25
27
  # @param [String] cmd Beanstalkd request command
26
28
  #
27
29
  # @example
@@ -37,6 +39,7 @@ module Beaneater
37
39
  # @param [String] status Beanstalkd error status
38
40
  # @param [String] cmd Beanstalkd request command
39
41
  #
42
+ # @return [Beaneater::UnexpectedResponse] Exception for the status provided
40
43
  # @example
41
44
  # Beaneater::UnexpectedResponse.new('NOT_FOUND', 'bury 123')
42
45
  #
@@ -1,30 +1,29 @@
1
1
  module Beaneater
2
- # Exception to stop processing jobs
2
+ # Exception to stop processing jobs during a `process!` loop.
3
+ # Simply `raise AbortProcessingError` in any job process handler to stop the processing loop.
3
4
  class AbortProcessingError < RuntimeError; end
4
5
 
5
- # Represents collection of jobs related commands.
6
+ # Represents collection of job-related commands.
6
7
  class Jobs < PoolCommand
7
8
 
8
9
  # @!attribute processors
9
10
  # @return [Array<Proc>] returns Collection of proc to handle beanstalkd jobs
10
11
  attr_reader :processors
11
12
 
12
- # Number of retries to process a job
13
+ # Number of retries to process a job.
13
14
  MAX_RETRIES = 3
14
15
 
15
- # Delay in seconds before to make job ready again
16
+ # Delay in seconds before to make job ready again.
16
17
  RELEASE_DELAY = 1
17
18
 
18
- # Peek (or find) a job across all beanstalkd servers from pool
19
- #
20
- # @param [Integer] id Job id
21
- #
22
- # @raise [Beaneater::NotFoundError] Job not found
19
+ # Peek (or find) first job from beanstalkd pool.
23
20
  #
21
+ # @param [Integer] id Job id to find
22
+ # @return [Beaneater::Job] Job matching given id
24
23
  # @example
24
+ # @beaneater_pool.jobs[123] # => <Beaneater::Job>
25
25
  # @beaneater_pool.jobs.find(123) # => <Beaneater::Job>
26
26
  # @beaneater_pool.jobs.peek(123) # => <Beaneater::Job>
27
- # @beaneater_pool.jobs.find[123] # => <Beaneater::Job>
28
27
  #
29
28
  # @api public
30
29
  def find(id)
@@ -36,13 +35,28 @@ module Beaneater
36
35
  alias_method :peek, :find
37
36
  alias_method :[], :find
38
37
 
39
- # Add processor to handle beanstalkd job
38
+ # Find all jobs with specified id fromm all beanstalkd servers in pool.
39
+ #
40
+ # @param [Integer] id Job id to find
41
+ # @return [Array<Beaneater::Job>] Jobs matching given id
42
+ # @example
43
+ # @beaneater_pool.jobs.find_all(123) # => [<Beaneater::Job>, <Beaneater::Job>]
44
+ #
45
+ # @api public
46
+ def find_all(id)
47
+ res = transmit_to_all("peek #{id}")
48
+ res.compact.map { |r| Job.new(r) }
49
+ rescue Beaneater::NotFoundError => ex
50
+ []
51
+ end
52
+
53
+ # Register a processor to handle beanstalkd job on particular tube.
40
54
  #
41
55
  # @param [String] tube_name Tube name
42
- # @param [Hash] options settings for processor
56
+ # @param [Hash{String=>RuntimeError}] options settings for processor
57
+ # @param [Proc] block Process beanstalkd job
43
58
  # @option options [Integer] max_retries Number of retries to process a job
44
59
  # @option options [Array<RuntimeError>] retry_on Collection of errors to rescue and re-run processor
45
- # @param [Proc] block Process beanstalkd job
46
60
  #
47
61
  # @example
48
62
  # @beanstalk.jobs.register('some-tube', :retry_on => [SomeError]) do |job|
@@ -61,10 +75,10 @@ module Beaneater
61
75
  @processors[tube_name.to_s] = { :block => block, :retry_on => retry_on, :max_retries => max_retries }
62
76
  end
63
77
 
64
- # Watch, reserve, process and delete or bury or release jobs
78
+ # Watch, reserve, process and delete or bury or release jobs.
65
79
  #
66
- # @param [Hash] options Settings for processing
67
- # @option options [Integer] Delay in seconds before to make job ready again
80
+ # @param [Hash{String => Integer}] options Settings for processing
81
+ # @option options [Integer] release_delay Delay in seconds before to make job ready again
68
82
  #
69
83
  # @api public
70
84
  def process!(options={})
@@ -3,19 +3,20 @@ module Beaneater
3
3
  class Job
4
4
 
5
5
  # @!attribute id
6
- # @return [Integer] returns Job id
6
+ # @return [Integer] id for the job.
7
7
  # @!attribute body
8
- # @return [String] returns Job body
8
+ # @return [String] the job's body.
9
9
  # @!attribute connection
10
- # @return [Beaneater::Connection] returns Connection which has retrieved job
10
+ # @return [Beaneater::Connection] connection which has retrieved job.
11
11
  # @!attribute reserved
12
- # @return [Boolean] returns If job is being reserved
12
+ # @return [Boolean] whether the job has been reserved.
13
13
  attr_reader :id, :body, :connection, :reserved
14
14
 
15
15
 
16
- # Initialize new connection
16
+ # Initializes a new job object.
17
+ #
18
+ # @param [Hash{Symbol => String,Number}] res Result from beanstalkd response
17
19
  #
18
- # @param [Hash] res result from beanstalkd response
19
20
  def initialize(res)
20
21
  @id = res[:id]
21
22
  @body = res[:body]
@@ -23,9 +24,9 @@ module Beaneater
23
24
  @reserved = res[:status] == 'RESERVED'
24
25
  end
25
26
 
26
- # Send command to bury job
27
+ # Sends command to bury a reserved job.
27
28
  #
28
- # @param [Hash] options Settings to bury job
29
+ # @param [Hash{Symbol => Integer}] options Settings to bury job
29
30
  # @option options [Integer] pri Assign new priority to job
30
31
  #
31
32
  # @example
@@ -39,12 +40,11 @@ module Beaneater
39
40
  end
40
41
  end
41
42
 
42
- # Send command to release job
43
+ # Sends command to release a job back to ready state.
43
44
  #
44
- # @param [Hash] options Settings to release job
45
+ # @param [Hash{String => Integer}] options Settings to release job
45
46
  # @option options [Integer] pri Assign new priority to job
46
- # @option options [Integer] pri Assign new delay to job
47
- #
47
+ # @option options [Integer] delay Assign new delay to job
48
48
  # @example
49
49
  # @beaneater_connection.jobs.find(123).release(:pri => 10, :delay => 5)
50
50
  #
@@ -56,7 +56,7 @@ module Beaneater
56
56
  end
57
57
  end
58
58
 
59
- # Send command to touch job
59
+ # Sends command to touch job which extends the ttr.
60
60
  #
61
61
  # @example
62
62
  # @beaneater_connection.jobs.find(123).touch
@@ -66,7 +66,7 @@ module Beaneater
66
66
  with_reserved("touch #{id}")
67
67
  end
68
68
 
69
- # Send command to delete job
69
+ # Sends command to delete a job.
70
70
  #
71
71
  # @example
72
72
  # @beaneater_connection.jobs.find(123).delete
@@ -76,7 +76,7 @@ module Beaneater
76
76
  transmit("delete #{id}") { @reserved = false }
77
77
  end
78
78
 
79
- # Send command to kick job
79
+ # Sends command to kick a buried job.
80
80
  #
81
81
  # @example
82
82
  # @beaneater_connection.jobs.find(123).kick
@@ -86,10 +86,12 @@ module Beaneater
86
86
  transmit("kick-job #{id}")
87
87
  end
88
88
 
89
- # Send command to get stats about job
89
+ # Sends command to get stats about job.
90
90
  #
91
+ # @return [Beaneater::StatStruct] struct filled with relevant job stats
91
92
  # @example
92
93
  # @beaneater_connection.jobs.find(123).stats
94
+ # @job.stats.tube # => "some-tube"
93
95
  #
94
96
  # @api public
95
97
  def stats
@@ -97,8 +99,9 @@ module Beaneater
97
99
  StatStruct.from_hash(res[:body])
98
100
  end
99
101
 
100
- # Check if job is being reserved
102
+ # Check if job is currently in a reserved state.
101
103
  #
104
+ # @return [Boolean] Returns true if the job is in a reserved state
102
105
  # @example
103
106
  # @beaneater_connection.jobs.find(123).reserved?
104
107
  #
@@ -107,35 +110,70 @@ module Beaneater
107
110
  @reserved || self.stats.state == "reserved"
108
111
  end
109
112
 
110
- # Check if job exists
113
+ # Check if the job still exists.
111
114
  #
115
+ # @return [Boolean] Returns true if the job still exists
112
116
  # @example
113
117
  # @beaneater_connection.jobs.find(123).exists?
114
118
  #
115
119
  # @api public
116
120
  def exists?
117
- !!self.stats
121
+ !self.stats.nil?
118
122
  rescue Beaneater::NotFoundError
119
123
  false
120
124
  end
121
125
 
122
126
  # Returns the name of the tube this job is in
123
127
  #
128
+ # @return [String] The name of the tube for this job
124
129
  # @example
125
130
  # @beaneater_connection.jobs.find(123).tube
131
+ # # => "some-tube"
126
132
  #
127
- # @api public
128
133
  def tube
129
134
  self.stats && self.stats.tube
130
135
  end
131
136
 
137
+ # Returns the ttr of this job
138
+ #
139
+ # @return [String] The ttr of this job
140
+ # @example
141
+ # @beaneater_connection.jobs.find(123).ttr
142
+ # # => 123
143
+ #
144
+ def ttr
145
+ self.stats && self.stats.ttr
146
+ end
147
+
148
+ # Returns the pri of this job
149
+ #
150
+ # @return [String] The pri of this job
151
+ # @example
152
+ # @beaneater_connection.jobs.find(123).pri
153
+ # # => 1
154
+ #
155
+ def pri
156
+ self.stats && self.stats.pri
157
+ end
158
+
159
+ # Returns the delay of this job
160
+ #
161
+ # @return [String] The delay of this job
162
+ # @example
163
+ # @beaneater_connection.jobs.find(123).delay
164
+ # # => 5
165
+ #
166
+ def delay
167
+ self.stats && self.stats.delay
168
+ end
169
+
132
170
  # Returns string representation of job
133
171
  #
172
+ # @return [String] string representation
134
173
  # @example
135
174
  # @beaneater_connection.jobs.find(123).to_s
136
175
  # @beaneater_connection.jobs.find(123).inspect
137
176
  #
138
- # @api public
139
177
  def to_s
140
178
  "#<Beaneater::Job id=#{id} body=#{body.inspect}>"
141
179
  end
@@ -146,7 +184,7 @@ module Beaneater
146
184
  # Transmit command to beanstalkd instances and fetch response.
147
185
  #
148
186
  # @param [String] cmd Beanstalkd command to send.
149
- # @return [Hash] Beanstalkd response for the command.
187
+ # @return [Hash{Symbol => String,Number}] Beanstalkd response for the command.
150
188
  # @example
151
189
  # transmit('stats')
152
190
  # transmit('stats') { 'success' }
@@ -160,7 +198,7 @@ module Beaneater
160
198
  # Transmits a command which requires the job to be reserved.
161
199
  #
162
200
  # @param [String] cmd Beanstalkd command to send.
163
- # @return [Hash] Beanstalkd response for the command.
201
+ # @return [Hash{Symbol => String,Number}] Beanstalkd response for the command.
164
202
  # @raise [Beaneater::JobNotReserved] Command cannot execute since job is not reserved.
165
203
  # @example
166
204
  # with_reserved("bury 26") { @reserved = false }
@@ -1,6 +1,6 @@
1
- # Simple ruby client for beanstalkd.
1
+ # Simple ruby client for interacting with beanstalkd.
2
2
  module Beaneater
3
- # Represents collection of connections.
3
+ # Represents collection of beanstalkd connections.
4
4
  class Pool
5
5
  # Default number of retries to send a command to a connection
6
6
  MAX_RETRIES = 3
@@ -11,8 +11,7 @@ module Beaneater
11
11
 
12
12
  # Initialize new connection
13
13
  #
14
- # @param [Array] hosts Array of beanstalkd server host
15
- #
14
+ # @param [Array<String>] addresses Array of beanstalkd server addresses
16
15
  # @example
17
16
  # Beaneater::Pool.new(['localhost:11300', '127.0.0.1:11300'])
18
17
  #
@@ -20,54 +19,92 @@ module Beaneater
20
19
  # @bp = Beaneater::Pool.new
21
20
  # @bp.connections.first.host # => 'localhost'
22
21
  # @bp.connections.last.host # => '127.0.0.1'
23
- def initialize(hosts=nil)
24
- hosts = hosts || host_from_env
25
- @connections = Array(hosts).map { |h| Connection.new(h) }
22
+ #
23
+ def initialize(addresses=nil)
24
+ addresses = addresses || host_from_env
25
+ @connections = Array(addresses).map { |a| Connection.new(a) }
26
26
  end
27
27
 
28
- # Returns Beaneater::Stats object
28
+ # Returns Beaneater::Stats object for accessing beanstalk stats.
29
29
  #
30
+ # @return [Beaneater::Stats] stats object
30
31
  # @api public
31
32
  def stats
32
33
  @stats ||= Stats.new(self)
33
34
  end
34
35
 
35
- # Returns Beaneater::Jobs object
36
+ # Returns Beaneater::Jobs object for accessing job related functions.
36
37
  #
38
+ # @return [Beaneater::Jobs] jobs object
37
39
  # @api public
38
40
  def jobs
39
41
  @jobs ||= Jobs.new(self)
40
42
  end
41
43
 
42
- # Returns Beaneater::Tubes object
44
+ # Returns Beaneater::Tubes object for accessing tube related functions.
43
45
  #
46
+ # @return [Beaneater::Tubes] tubes object
44
47
  # @api public
45
48
  def tubes
46
49
  @tubes ||= Tubes.new(self)
47
50
  end
48
51
 
49
- # Send command to every beanstalkd servers set in pool
52
+ # Sends command to every beanstalkd server set in the pool.
50
53
  #
51
54
  # @param [String] command Beanstalkd command
52
- # @param [Hash] options telnet connections options
53
- # @param [Proc] block Block passed in telnet connection object
54
- #
55
+ # @param [Hash{String => String, Boolean}] options telnet connections options
56
+ # @param [Proc] block Block passed to telnet connection during transmit
57
+ # @return [Array<Hash{String => String, Number}>] Beanstalkd command response from each instance
55
58
  # @example
56
59
  # @pool.transmit_to_all("stats")
60
+ #
57
61
  def transmit_to_all(command, options={}, &block)
58
- connections.map do |conn|
59
- safe_transmit { conn.transmit(command, options, &block) }
60
- end
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
61
73
  end
62
74
 
63
- # Send command to a random beanstalkd servers set in pool
75
+ # Send command to each beanstalkd servers until getting response expected
64
76
  #
65
77
  # @param [String] command Beanstalkd command
66
- # @param [Hash] options telnet connections options
78
+ # @param [Hash{String => String, Boolean}] options telnet connections options
67
79
  # @param [Proc] block Block passed in telnet 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.
68
100
  #
101
+ # @param [String] command Beanstalkd command
102
+ # @param [Hash{String => String,Boolean}] options telnet connections options
103
+ # @param [Proc] block Block passed in telnet connection object
104
+ # @return [Array<Hash{String => String, Number}>] Beanstalkd command response from the instance
69
105
  # @example
70
106
  # @pool.transmit_to_rand("stats", :match => /\n/)
107
+ #
71
108
  def transmit_to_rand(command, options={}, &block)
72
109
  safe_transmit do
73
110
  conn = connections.respond_to?(:sample) ? connections.sample : connections.choice
@@ -75,23 +112,11 @@ module Beaneater
75
112
  end
76
113
  end
77
114
 
78
- # Send command to each beanstalkd servers until getting response expected
79
- #
80
- # @param [String] command Beanstalkd command
81
- # @param [Hash] options telnet connections options
82
- # @param [Proc] block Block passed in telnet connection object
115
+ # Closes all connections within the pool.
83
116
  #
84
117
  # @example
85
- # @pool.transmit_until_res('peek-ready', :status => "FOUND", &block)
86
- def transmit_until_res(command, options={}, &block)
87
- status_expected = options.delete(:status)
88
- connections.each do |conn|
89
- res = safe_transmit { conn.transmit(command, options, &block) }
90
- return res if res[:status] == status_expected
91
- end && nil
92
- end
93
-
94
- # Closes all connections within pool
118
+ # @pool.close
119
+ #
95
120
  def close
96
121
  while @connections.any?
97
122
  conn = @connections.pop
@@ -14,20 +14,21 @@ module Beaneater
14
14
  @pool = pool
15
15
  end
16
16
 
17
- # Delegate to Pool#transmit_to_all and if needed will merge responses from beanstalkd
17
+ # Delegate to Pool#transmit_to_all and if needed will merge responses from beanstalkd.
18
18
  #
19
19
  # @param [String] body Beanstalkd command
20
- # @param [Hash] options telnet connections options
20
+ # @param [Hash{String => String, Boolean}] options telnet connections options
21
21
  # @option options [Boolean] merge Ask for merging responses or not
22
22
  # @param [Proc] block Block passed in telnet connection object
23
- #
24
23
  # @example
25
24
  # @pool.transmit_to_all("stats")
25
+ #
26
26
  def transmit_to_all(body, options={}, &block)
27
27
  merge = options.delete(:merge)
28
28
  res = pool.transmit_to_all(body, options, &block)
29
- if merge
30
- res = { :status => res.first[:status], :body => sum_hashes(res.map { |r| r[:body] }) }
29
+ first = res.find { |r| r && r[:status] }
30
+ if first && merge
31
+ res = { :status => first[:status], :body => sum_items(res.map { |r| r[:body] }) }
31
32
  end
32
33
  res
33
34
  end
@@ -44,17 +45,24 @@ module Beaneater
44
45
 
45
46
  protected
46
47
 
47
- # Selects hashes from collection and then merges the individual key values
48
+ # Selects items from collection and then merges the individual values
49
+ # Supports array of hashes or array of arrays
48
50
  #
49
- # @param [Array<Hash>] hs Collection of hash responses returned from beanstalkd
50
- # @return [Hash] Merged responses combining values from all the hash bodies
51
+ # @param [Array<Hash, Array>] hs Collection of responses returned from beanstalkd
52
+ # @return [Hash{Symbol => String}] Merged responses combining values from all the hash bodies
51
53
  # @example
52
- # self.sum_hashes([{ :foo => 1, :bar => 5 }, { :foo => 2, :bar => 3 }])
54
+ # self.sum_items([{ :foo => 1, :bar => 5 }, { :foo => 2, :bar => 3 }])
53
55
  # => { :foo => 3, :bar => 8 }
56
+ # self.sum_items([['foo', 'bar'], ['foo', 'bar', 'baz']])
57
+ # => ['foo', 'bar', 'baz']
54
58
  #
55
- def sum_hashes(hs)
56
- hs.select { |h| h.is_a?(Hash) }.
57
- inject({}) { |a,b| a.merge(b) { |k,o,n| combine_stats(k, o, n) } }
59
+ def sum_items(items)
60
+ if items.first.is_a?(Hash)
61
+ items.select { |h| h.is_a?(Hash) }.
62
+ inject({}) { |a,b| a.merge(b) { |k,o,n| combine_stats(k, o, n) } }
63
+ elsif items.first.is_a?(Array)
64
+ items.flatten.uniq
65
+ end
58
66
  end
59
67
 
60
68
  # Combine two values for given key
@@ -3,7 +3,7 @@ module Beaneater
3
3
  class StatStruct < FasterOpenStruct
4
4
  # Convert a stats hash into a struct.
5
5
  #
6
- # @param [Hash(String => String)] hash Hash Stats hash to convert to struct
6
+ # @param [Hash{String => String}] hash Hash Stats hash to convert to struct
7
7
  # @return [Beaneater::StatStruct, nil] Stats struct from hash
8
8
  # @example
9
9
  # s = StatStruct.from_hash(:foo => "bar")
@@ -18,7 +18,7 @@ module Beaneater
18
18
  # Access value for stat with specified key.
19
19
  #
20
20
  # @param [String] key Key to fetch from stats.
21
- # @return [String,Integer] Value for specified stat key.
21
+ # @return [String, Integer] Value for specified stat key.
22
22
  # @example
23
23
  # @stats['foo'] # => "bar"
24
24
  #
@@ -10,6 +10,7 @@ module Beaneater
10
10
  # @example
11
11
  # @bp.stats.keys # => ["version", "total_connections"]
12
12
  #
13
+ # @api public
13
14
  def keys
14
15
  data.keys
15
16
  end
@@ -22,6 +22,7 @@ module Beaneater
22
22
  # @pool.tubes['tube2']
23
23
  # # => <Beaneater::Tube name="tube2">
24
24
  #
25
+ # @api public
25
26
  def find(tube_name)
26
27
  Tube.new(self.pool, tube_name)
27
28
  end
@@ -37,6 +38,7 @@ module Beaneater
37
38
  # @conn.tubes.reserve { |job| process(job) }
38
39
  # # => <Beaneater::Job id=5 body="foo">
39
40
  #
41
+ # @api public
40
42
  def reserve(timeout=nil, &block)
41
43
  res = transmit_to_rand(timeout ? "reserve-with-timeout #{timeout}" : 'reserve')
42
44
  job = Job.new(res)
@@ -44,20 +46,6 @@ module Beaneater
44
46
  job
45
47
  end
46
48
 
47
- # Set specified tube as used.
48
- #
49
- # @param [String] tube Tube to be used.
50
- # @example
51
- # @conn.tubes.use("some-tube")
52
- #
53
- def use(tube)
54
- return tube if @last_used == tube
55
- res = transmit_to_all("use #{tube}")
56
- @last_used = tube
57
- rescue BadFormatError
58
- raise InvalidTubeName, "Tube cannot be named '#{tube}'"
59
- end
60
-
61
49
  # List of all known beanstalk tubes.
62
50
  #
63
51
  # @return [Array<Beaneater::Tube>] List of all beanstalk tubes.
@@ -65,8 +53,9 @@ module Beaneater
65
53
  # @pool.tubes.all
66
54
  # # => [<Beaneater::Tube name="tube2">, <Beaneater::Tube name="tube3">]
67
55
  #
56
+ # @api public
68
57
  def all
69
- transmit_to_rand('list-tubes')[:body].map { |tube_name| Tube.new(self.pool, tube_name) }
58
+ transmit_to_all('list-tubes', :merge => true)[:body].map { |tube_name| Tube.new(self.pool, tube_name) }
70
59
  end
71
60
 
72
61
  # List of watched beanstalk tubes.
@@ -76,8 +65,9 @@ module Beaneater
76
65
  # @pool.tubes.watched
77
66
  # # => [<Beaneater::Tube name="tube2">, <Beaneater::Tube name="tube3">]
78
67
  #
68
+ # @api public
79
69
  def watched
80
- transmit_to_rand('list-tubes-watched')[:body].map { |tube_name| Tube.new(self.pool, tube_name) }
70
+ transmit_to_all('list-tubes-watched', :merge => true)[:body].map { |tube_name| Tube.new(self.pool, tube_name) }
81
71
  end
82
72
 
83
73
  # Currently used beanstalk tube.
@@ -87,6 +77,7 @@ module Beaneater
87
77
  # @pool.tubes.used
88
78
  # # => <Beaneater::Tube name="tube2">
89
79
  #
80
+ # @api public
90
81
  def used
91
82
  Tube.new(self.pool, transmit_to_rand('list-tube-used')[:id])
92
83
  end
@@ -98,6 +89,7 @@ module Beaneater
98
89
  # @example
99
90
  # @pool.tubes.watch('foo', 'bar')
100
91
  #
92
+ # @api public
101
93
  def watch(*names)
102
94
  names.each do |t|
103
95
  transmit_to_all "watch #{t}"
@@ -113,6 +105,7 @@ module Beaneater
113
105
  # @example
114
106
  # @pool.tubes.watch!('foo', 'bar')
115
107
  #
108
+ # @api public
116
109
  def watch!(*names)
117
110
  old_tubes = watched.map(&:name) - names.map(&:to_s)
118
111
  watch(*names)
@@ -125,10 +118,25 @@ module Beaneater
125
118
  # @example
126
119
  # @pool.tubes.ignore('foo', 'bar')
127
120
  #
121
+ # @api public
128
122
  def ignore(*names)
129
123
  names.each do |w|
130
124
  transmit_to_all "ignore #{w}"
131
125
  end
132
126
  end
127
+
128
+ # Set specified tube as used.
129
+ #
130
+ # @param [String] tube Tube to be used.
131
+ # @example
132
+ # @conn.tubes.use("some-tube")
133
+ #
134
+ def use(tube)
135
+ return tube if @last_used == tube
136
+ res = transmit_to_all("use #{tube}")
137
+ @last_used = tube
138
+ rescue BadFormatError
139
+ raise InvalidTubeName, "Tube cannot be named '#{tube}'"
140
+ end
133
141
  end # Tubes
134
142
  end # Beaneater
@@ -28,11 +28,11 @@ module Beaneater
28
28
  # Inserts job with specified body onto tube.
29
29
  #
30
30
  # @param [String] body The data to store with this job.
31
- # @param [Hash] options The settings associated with this job.
31
+ # @param [Hash{String => Integer}] options The settings associated with this job.
32
32
  # @option options [Integer] pri priority for this job
33
33
  # @option options [Integer] ttr time to respond for this job
34
34
  # @option options [Integer] delay delay for this job
35
- # @return [Hash] beanstalkd command response
35
+ # @return [Hash{String => String, Number}] beanstalkd command response
36
36
  # @example
37
37
  # @tube.put "data", :pri => 1000, :ttr => 10, :delay => 5
38
38
  #
@@ -71,6 +71,7 @@ module Beaneater
71
71
  # @example
72
72
  # @tube.reserve # => <Beaneater::Job id=5 body=foo>
73
73
  #
74
+ # @api public
74
75
  def reserve(timeout=nil, &block)
75
76
  pool.tubes.watch!(self.name)
76
77
  pool.tubes.reserve(timeout, &block)
@@ -79,10 +80,11 @@ module Beaneater
79
80
  # Kick specified number of jobs from buried to ready state.
80
81
  #
81
82
  # @param [Integer] bounds The number of jobs to kick.
82
- # @return [Hash] Beanstalkd command response
83
+ # @return [Hash{String => String, Number}] Beanstalkd command response
83
84
  # @example
84
85
  # @tube.kick(5)
85
86
  #
87
+ # @api public
86
88
  def kick(bounds=1)
87
89
  safe_use { transmit_to_rand("kick #{bounds}") }
88
90
  end
@@ -93,6 +95,7 @@ module Beaneater
93
95
  # @example
94
96
  # @tube.stats.delayed # => 24
95
97
  #
98
+ # @api public
96
99
  def stats
97
100
  res = transmit_to_all("stats-tube #{name}", :merge => true)
98
101
  StatStruct.from_hash(res[:body])
@@ -101,10 +104,11 @@ module Beaneater
101
104
  # Pause the execution of this tube for specified `delay`.
102
105
  #
103
106
  # @param [Integer] delay Number of seconds to delay tube execution
104
- # @return [Hash] Beanstalkd command response
107
+ # @return [Array<Hash{String => String, Number}>] Beanstalkd command response
105
108
  # @example
106
109
  # @tube.pause(10)
107
110
  #
111
+ # @api public
108
112
  def pause(delay)
109
113
  transmit_to_all("pause-tube #{name} #{delay}")
110
114
  end
@@ -1,4 +1,4 @@
1
1
  module Beaneater
2
2
  # Current version of gem.
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
data/lib/beaneater.rb CHANGED
@@ -4,7 +4,6 @@ require 'net/telnet'
4
4
  require "beaneater/#{f}"
5
5
  end
6
6
 
7
- # Simple ruby client for beanstalkd.
8
7
  module Beaneater
9
-
8
+ # Simple ruby client for beanstalkd.
10
9
  end
@@ -3,6 +3,7 @@ require File.expand_path('../test_helper', __FILE__)
3
3
  describe "beanstalk-client" do
4
4
  before do
5
5
  @beanstalk = Beaneater::Pool.new(['127.0.0.1:11300'])
6
+ # @beanstalk = Beaneater::Pool.new(['127.0.0.1:11300', '127.0.0.1:11301'])
6
7
  @tubes = ['one', 'two', 'three']
7
8
 
8
9
  # Put something on each tube so they exist
data/test/job_test.rb CHANGED
@@ -207,6 +207,44 @@ describe Beaneater::Job do
207
207
  end
208
208
  end # tube
209
209
 
210
+ describe "for #pri" do
211
+ before do
212
+ @tube.put 'bar', :pri => 1
213
+ @job = @tube.peek(:ready)
214
+ end
215
+
216
+ it("should return pri") do
217
+ job = @tube.reserve
218
+ assert_equal 1, job.pri
219
+ job.release
220
+ end
221
+ end # tube
222
+
223
+
224
+ describe "for #ttr" do
225
+ before do
226
+ @tube.put 'bar', :ttr => 5
227
+ @job = @tube.peek(:ready)
228
+ end
229
+
230
+ it("should return ttr") do
231
+ job = @tube.reserve
232
+ assert_equal 5, job.ttr
233
+ job.release
234
+ end
235
+ end # tube
236
+
237
+ describe "for #delay" do
238
+ before do
239
+ @tube.put 'bar', :delay => 5
240
+ @job = @tube.peek(:delayed)
241
+ end
242
+
243
+ it("should return delay") do
244
+ assert_equal 5, @job.delay
245
+ end
246
+ end # tube
247
+
210
248
  after do
211
249
  cleanup_tubes!(['tube'])
212
250
  end
data/test/jobs_test.rb CHANGED
@@ -33,6 +33,30 @@ describe Beaneater::Jobs do
33
33
  end
34
34
  end # find
35
35
 
36
+ describe "for #find_all" do
37
+ before do
38
+ @time = Time.now.to_i
39
+ @tube.put("foo find #{@time}")
40
+ @job = @tube.peek(:ready)
41
+ end
42
+
43
+ it "should return job from id" do
44
+ assert_equal "foo find #{@time}", @jobs.find_all(@job.id).first.body
45
+ end
46
+
47
+ it "should return job using peek" do
48
+ assert_equal "foo find #{@time}", @jobs.find_all(@job.id).first.body
49
+ end
50
+
51
+ it "should return job using hash syntax" do
52
+ assert_equal "foo find #{@time}", @jobs.find_all(@job.id).first.body
53
+ end
54
+
55
+ it "should return nil for invalid id" do
56
+ assert_equal [], @jobs.find_all(-1)
57
+ end
58
+ end # find_all
59
+
36
60
  describe "for #register!" do
37
61
  before do
38
62
  $foo = 0
@@ -18,27 +18,49 @@ describe Beaneater::PoolCommand do
18
18
  describe 'for #transmit_to_all' do
19
19
  describe 'for regular command' do
20
20
  before do
21
- @pool = stub(:transmit_to_all => "OK")
21
+ @pool = stub(:transmit_to_all => [{ :body => "foo", :status => "OK" }])
22
22
  @command = Beaneater::PoolCommand.new(@pool)
23
23
  end
24
24
 
25
25
  it "can run regular command" do
26
- assert_equal "OK", @command.transmit_to_all("foo")
26
+ res = @command.transmit_to_all("foo")
27
+ assert_equal "OK", res[0][:status]
28
+ assert_equal "foo", res[0][:body]
27
29
  end
28
30
  end # regular command
29
31
 
30
- describe 'for merged command' do
32
+ describe 'for merge command with hashes' do
31
33
  before do
32
- @pool = stub(:transmit_to_all => [{ :body => { 'x' => 1, 'version' => 1.1 }}, {:body => { 'x' => 3,'version' => 1.2 }}])
34
+ @pool = stub(:transmit_to_all => [
35
+ { :body => { 'x' => 1, 'version' => 1.1 }, :status => "OK"},
36
+ { :body => { 'x' => 3,'version' => 1.2 }, :status => "OK" }
37
+ ])
33
38
  @command = Beaneater::PoolCommand.new(@pool)
34
39
  end
35
40
 
36
- it "can run merge command" do
41
+ it "can run merge command " do
37
42
  cmd = @command.transmit_to_all("bar", :merge => true)
43
+ assert_equal "OK", cmd[:status]
38
44
  assert_equal 4, cmd[:body]['x']
39
45
  assert_equal Set[1.1, 1.2], cmd[:body]['version']
40
46
  end
41
47
  end # merged command
48
+
49
+ describe 'for merge command with arrays' do
50
+ before do
51
+ @pool = stub(:transmit_to_all => [
52
+ { :body => ['foo', 'bar'], :status => "OK"},
53
+ { :body => ['foo', 'bar', 'baz'], :status => "OK" }
54
+ ])
55
+ @command = Beaneater::PoolCommand.new(@pool)
56
+ end
57
+
58
+ it "can run merge command " do
59
+ cmd = @command.transmit_to_all("bar", :merge => true)
60
+ assert_equal "OK", cmd[:status]
61
+ assert_equal ['foo', 'bar', 'baz'].sort, cmd[:body].sort
62
+ end
63
+ end # merged command
42
64
  end # transmit_to_all
43
65
 
44
66
  describe 'for #method_missing' do
data/test/stats_test.rb CHANGED
@@ -4,7 +4,8 @@ require File.expand_path('../test_helper', __FILE__)
4
4
 
5
5
  describe Beaneater::Stats do
6
6
  before do
7
- @pool = stub(:transmit_to_all => [{ :body => { 'uptime' => 1, 'cmd-use' => 2 }}, {:body => { 'uptime' => 3,'cmd-use' => 4 }}])
7
+ @pool = stub(:transmit_to_all => [{ :body => { 'uptime' => 1, 'cmd-use' => 2 }, :status => "OK"},
8
+ {:body => { 'uptime' => 3,'cmd-use' => 4 }, :status => "OK" }])
8
9
  @stats = Beaneater::Stats.new(@pool)
9
10
  end
10
11
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beaneater
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
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-11-02 00:00:00.000000000 Z
12
+ date: 2012-11-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -100,10 +100,10 @@ extra_rdoc_files: []
100
100
  files:
101
101
  - .gitignore
102
102
  - .yardopts
103
+ - CHANGELOG.md
103
104
  - Gemfile
104
105
  - LICENSE.txt
105
106
  - README.md
106
- - REF
107
107
  - Rakefile
108
108
  - TODO
109
109
  - beaneater.gemspec
@@ -147,18 +147,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
147
  - - ! '>='
148
148
  - !ruby/object:Gem::Version
149
149
  version: '0'
150
- segments:
151
- - 0
152
- hash: -2674763772608009517
153
150
  required_rubygems_version: !ruby/object:Gem::Requirement
154
151
  none: false
155
152
  requirements:
156
153
  - - ! '>='
157
154
  - !ruby/object:Gem::Version
158
155
  version: '0'
159
- segments:
160
- - 0
161
- hash: -2674763772608009517
162
156
  requirements: []
163
157
  rubyforge_project:
164
158
  rubygems_version: 1.8.24
data/REF DELETED
@@ -1,23 +0,0 @@
1
- # Summary of what this does
2
- #
3
- # @!attribute [r] count
4
- # @param [type] Name description
5
- # @option name [Types] option_key (default_value) description
6
- # @yield [a, b, c] Gives 3 random numbers to the block
7
- # @return [type] description
8
- # @raise [Types] description
9
- # @example
10
- # something.foo # => "test"
11
- #
12
-
13
-
14
- # Summary of what this does
15
- #
16
- # @param [type] Name description
17
- # @option name [Types] option_key (default_value) description
18
- # @yield [a, b, c] Gives 3 random numbers to the block
19
- # @return [type] description
20
- # @raise [Types] description
21
- # @example
22
- # something.foo # => "test"
23
- #