beaneater 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,11 @@
1
1
  # CHANGELOG for Beaneater
2
2
 
3
- ## 0.1.3 (Unreleased)
3
+ ## 0.2.1 (Unreleased)
4
+
5
+ ## 0.2.0 (Nov 12 2012)
6
+ * Fix 1.8.7 compatibility issues
7
+ * Add configuration block to beaneater and better job parsing
8
+ * BREAKING: json jobs now return as string by default not hashes
4
9
 
5
10
  ## 0.1.2 (Nov 7 2012)
6
11
 
data/README.md CHANGED
@@ -101,6 +101,20 @@ For a more detailed rundown, check out the __Usage__ section below.
101
101
 
102
102
  ## Usage
103
103
 
104
+ ### Configuration
105
+
106
+ To setup advanced options for beaneater
107
+
108
+ ```ruby
109
+ Beaneater.configure do |config|
110
+ # config.default_put_delay = 0
111
+ # config.default_put_pri = 65536
112
+ # config.default_put_ttr = 120
113
+ # config.job_parser = lambda { |body| body }
114
+ # config.beanstalkd_url = ['localhost:11300']
115
+ end
116
+ ```
117
+
104
118
  ### Connection
105
119
 
106
120
  To interact with a beanstalk queue, first establish a connection by providing a set of addresses:
@@ -21,4 +21,5 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency 'mocha'
22
22
  gem.add_development_dependency 'fakeweb'
23
23
  gem.add_development_dependency 'term-ansicolor'
24
+ gem.add_development_dependency 'json'
24
25
  end
@@ -1,9 +1,33 @@
1
1
  require 'net/telnet'
2
+ require 'thread' unless defined?(Mutex)
2
3
 
3
- %w(version errors pool_command pool connection stats tube job).each do |f|
4
+ %w(version configuration errors pool_command pool connection stats tube job).each do |f|
4
5
  require "beaneater/#{f}"
5
6
  end
6
7
 
7
8
  module Beaneater
8
9
  # Simple ruby client for beanstalkd.
9
- end
10
+
11
+ class << self
12
+ # Yields a configuration block
13
+ #
14
+ # @example
15
+ # Beaneater.configure do |config|
16
+ # config.job_parser = lamda { |body| Yaml.load(body)}
17
+ # end
18
+ #
19
+ def configure(&block)
20
+ yield(configuration) if block_given?
21
+ configuration
22
+ end
23
+
24
+ # Returns the configuration options set for Backburner
25
+ #
26
+ # @example
27
+ # Beaneater.configuration.default_put_ttr => 120
28
+ #
29
+ def configuration
30
+ @_configuration ||= Configuration.new
31
+ end
32
+ end
33
+ end # Beaneater
@@ -0,0 +1,17 @@
1
+ module Beaneater
2
+ class Configuration
3
+ attr_accessor :default_put_delay # default delay value to put a job
4
+ attr_accessor :default_put_pri # default priority value to put a job
5
+ attr_accessor :default_put_ttr # default ttr value to put a job
6
+ attr_accessor :job_parser # default job_parser to parse job body
7
+ attr_accessor :beanstalkd_url # default beanstalkd url
8
+
9
+ def initialize
10
+ @default_put_delay = 0
11
+ @default_put_pri = 65536
12
+ @default_put_ttr = 120
13
+ @job_parser = lambda { |body| body }
14
+ @beanstalkd_url = nil
15
+ end
16
+ end # Configuration
17
+ end # Beaneater
@@ -112,10 +112,19 @@ module Beaneater
112
112
  status = res_lines.first
113
113
  status, id = status.scan(/\w+/)
114
114
  raise UnexpectedResponse.from_status(status, cmd) if UnexpectedResponse::ERROR_STATES.include?(status)
115
- response = { :status => status, :body => YAML.load(res_lines[1..-1].join("\n")) }
115
+ raw_body = res_lines[1..-1].join("\n")
116
+ body = ['FOUND', 'RESERVED'].include?(status) ? config.job_parser.call(raw_body) : YAML.load(raw_body)
117
+ response = { :status => status, :body => body }
116
118
  response[:id] = id if id
117
119
  response[:connection] = self
118
120
  response
119
121
  end
122
+
123
+ # Returns configuration options for beaneater
124
+ #
125
+ # @return [Beaneater::Configuration] configuration object
126
+ def config
127
+ Beaneater.configuration
128
+ end
120
129
  end # Connection
121
130
  end # Beaneater
@@ -21,7 +21,7 @@ module Beaneater
21
21
  # @bp.connections.last.host # => '127.0.0.1'
22
22
  #
23
23
  def initialize(addresses=nil)
24
- addresses = addresses || host_from_env
24
+ addresses = addresses || host_from_env || Beaneater.configuration.beanstalkd_url
25
25
  @connections = Array(addresses).map { |a| Connection.new(a) }
26
26
  end
27
27
 
@@ -1,12 +1,6 @@
1
1
  module Beaneater
2
2
  # Beanstalk tube which contains jobs which can be inserted, reserved, et al.
3
3
  class Tube < PoolCommand
4
- # The default delay for inserted jobs.
5
- DEFAULT_DELAY = 0
6
- # Default priority for inserted jobs, 0 is the highest.
7
- DEFAULT_PRIORITY = 65536
8
- # Default time to respond for inserted jobs.
9
- DEFAULT_TTR = 120
10
4
 
11
5
  # @!attribute name
12
6
  # @return [String] name of the tube
@@ -39,7 +33,8 @@ module Beaneater
39
33
  # @api public
40
34
  def put(body, options={})
41
35
  safe_use do
42
- options = { :pri => DEFAULT_PRIORITY, :delay => DEFAULT_DELAY, :ttr => DEFAULT_TTR }.merge(options)
36
+ options = { :pri => config.default_put_pri, :delay => config.default_put_delay,
37
+ :ttr => config.default_put_ttr }.merge(options)
43
38
  cmd_options = "#{options[:pri]} #{options[:delay]} #{options[:ttr]} #{body.bytesize}"
44
39
  transmit_to_rand("put #{cmd_options}\n#{body}")
45
40
  end
@@ -60,6 +55,7 @@ module Beaneater
60
55
  end
61
56
  rescue Beaneater::NotFoundError => ex
62
57
  # Return nil if not found
58
+ nil
63
59
  end
64
60
 
65
61
  # Reserves the next job from tube.
@@ -158,5 +154,13 @@ module Beaneater
158
154
  ensure
159
155
  @mutex.unlock
160
156
  end
157
+
158
+ # Returns configuration options for beaneater
159
+ #
160
+ # @return [Beaneater::Configuration] configuration object
161
+ def config
162
+ Beaneater.configuration
163
+ end
164
+
161
165
  end # Tube
162
166
  end # Beaneater
@@ -1,4 +1,4 @@
1
1
  module Beaneater
2
2
  # Current version of gem.
3
- VERSION = "0.1.2"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -64,6 +64,33 @@ describe Beaneater::Pool do
64
64
  assert_equal '127.0.0.1', bc2.host
65
65
  assert_equal 11300, bc2.port
66
66
  end
67
+
68
+ after do
69
+ ENV['BEANSTALKD_URL'] = nil
70
+ end
71
+ end
72
+
73
+ describe "by configuring via Beaneater.configure" do
74
+ before do
75
+ Beaneater.configure.beanstalkd_url = ['0.0.0.0:11300', '127.0.0.1:11300']
76
+ end
77
+
78
+ it "should create 1 connection" do
79
+ bp = Beaneater::Pool.new
80
+ bc = bp.connections.first
81
+ bc2 = bp.connections.last
82
+
83
+ assert_equal 2, bp.connections.size
84
+ assert_equal '0.0.0.0', bc.host
85
+ assert_equal 11300, bc.port
86
+
87
+ assert_equal '127.0.0.1', bc2.host
88
+ assert_equal 11300, bc2.port
89
+ end
90
+
91
+ after do
92
+ Beaneater.configure.beanstalkd_url = ['0.0.0.0:11300']
93
+ end
67
94
  end
68
95
  end # new
69
96
 
@@ -35,7 +35,7 @@ describe Beaneater::StatStruct do
35
35
  end
36
36
 
37
37
  it "should return expected keys" do
38
- assert_equal ['foo', 'bar', 'baz', 'under_score'], @struct.keys
38
+ assert_equal ['foo', 'bar', 'baz', 'under_score'].sort, @struct.keys.sort
39
39
  end
40
40
  end # keys
41
41
  end
@@ -5,6 +5,7 @@ $:.unshift File.expand_path("../../lib")
5
5
  require 'beaneater'
6
6
  require 'fakeweb'
7
7
  require 'mocha'
8
+ require 'json'
8
9
 
9
10
  FakeWeb.allow_net_connect = false
10
11
 
@@ -16,6 +16,9 @@ describe Beaneater::Tube do
16
16
  it "should insert a job" do
17
17
  @tube.put "bar put #{@time}"
18
18
  assert_equal "bar put #{@time}", @tube.peek(:ready).body
19
+ assert_equal 120, @tube.peek(:ready).ttr
20
+ assert_equal 65536, @tube.peek(:ready).pri
21
+ assert_equal 0, @tube.peek(:ready).delay
19
22
  end
20
23
 
21
24
  it "should insert a delayed job" do
@@ -37,12 +40,6 @@ describe Beaneater::Tube do
37
40
  assert_raises(Beaneater::DrainingError) { @tube.put "bar put #{@time}" }
38
41
  end
39
42
 
40
- it "supports JSON" do
41
- json = "{ 'foo' : 'bar' }"
42
- @tube.put(json)
43
- assert_equal 'bar', @tube.peek(:ready).body['foo']
44
- end
45
-
46
43
  after do
47
44
  Beaneater::Connection.any_instance.unstub(:transmit)
48
45
  end
@@ -73,22 +70,59 @@ describe Beaneater::Tube do
73
70
  it "should return nil for empty peek" do
74
71
  assert_nil @tube.peek(:buried)
75
72
  end
73
+
74
+ it "supports valid JSON" do
75
+ json = '{ "foo" : "bar" }'
76
+ @tube.put(json)
77
+ assert_equal 'bar', JSON.parse(@tube.peek(:ready).body)['foo']
78
+ end
79
+
80
+ it "supports non valid JSON" do
81
+ json = '{"message":"hi"}'
82
+ @tube.put(json)
83
+ assert_equal 'hi', JSON.parse(@tube.peek(:ready).body)['message']
84
+ end
85
+
86
+ it "should support custom parser" do
87
+ Beaneater.configure.job_parser = lambda { |b| JSON.parse(b) }
88
+ json = '{"message":"hi"}'
89
+ @tube.put(json)
90
+ assert_equal 'hi', @tube.peek(:ready).body['message']
91
+ end
92
+
93
+ after do
94
+ Beaneater.configure.job_parser = lambda { |b| b }
95
+ end
76
96
  end # peek
77
97
 
78
98
  describe "for #reserve" do
79
99
  before do
80
100
  @time = Time.now.to_i
81
- @tube.put "foo reserve #{@time}"
101
+ @json = %Q&{ "foo" : "#{@time} bar" }&
102
+ @tube.put @json
82
103
  end
83
104
 
84
105
  it "should reserve job" do
85
- assert_equal "foo reserve #{@time}", @tube.reserve.body
106
+ @job = @tube.reserve
107
+ assert_equal "#{@time} bar", JSON.parse(@job.body)['foo']
108
+ @job.delete
86
109
  end
87
110
 
88
111
  it "should reserve job with block" do
89
112
  job = nil
90
113
  @tube.reserve { |j| job = j; job.delete }
91
- assert_equal "foo reserve #{@time}", job.body
114
+ assert_equal "#{@time} bar", JSON.parse(job.body)['foo']
115
+ end
116
+
117
+ it "should support custom parser" do
118
+ Beaneater.configure.job_parser = lambda { |b| JSON.parse(b) }
119
+ @job = @tube.reserve
120
+ assert_equal "#{@time} bar", @job.body['foo']
121
+ @job.delete
122
+ end
123
+
124
+ after do
125
+ Beaneater.configure.job_parser = lambda { |b| b }
92
126
  end
93
127
  end # reserve
94
128
 
@@ -134,7 +134,7 @@ describe Beaneater::Tubes do
134
134
 
135
135
  it "should raise TimedOutError no delete, with timeout" do
136
136
  @pool.tubes.watch 'tube'
137
- @pool.tubes.reserve(0)
137
+ @pool.tubes.reserve(0) { |j| job = j; job.delete }
138
138
  assert_raises(Beaneater::TimedOutError) { @pool.tubes.reserve(0) }
139
139
  end
140
140
 
metadata CHANGED
@@ -1,103 +1,118 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: beaneater
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Nico Taing
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-11-07 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-11-13 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: minitest
16
- requirement: !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
17
23
  none: false
18
- requirements:
24
+ requirements:
19
25
  - - ~>
20
- - !ruby/object:Gem::Version
26
+ - !ruby/object:Gem::Version
27
+ hash: 59
28
+ segments:
29
+ - 4
30
+ - 1
31
+ - 0
21
32
  version: 4.1.0
22
33
  type: :development
34
+ requirement: *id001
23
35
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 4.1.0
30
- - !ruby/object:Gem::Dependency
36
+ - !ruby/object:Gem::Dependency
31
37
  name: rake
32
- requirement: !ruby/object:Gem::Requirement
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
33
39
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
38
47
  type: :development
48
+ requirement: *id002
39
49
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
50
+ - !ruby/object:Gem::Dependency
47
51
  name: mocha
48
- requirement: !ruby/object:Gem::Requirement
52
+ version_requirements: &id003 !ruby/object:Gem::Requirement
49
53
  none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
54
61
  type: :development
62
+ requirement: *id003
55
63
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
64
+ - !ruby/object:Gem::Dependency
63
65
  name: fakeweb
64
- requirement: !ruby/object:Gem::Requirement
66
+ version_requirements: &id004 !ruby/object:Gem::Requirement
65
67
  none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
70
75
  type: :development
76
+ requirement: *id004
71
77
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- - !ruby/object:Gem::Dependency
78
+ - !ruby/object:Gem::Dependency
79
79
  name: term-ansicolor
80
- requirement: !ruby/object:Gem::Requirement
80
+ version_requirements: &id005 !ruby/object:Gem::Requirement
81
81
  none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
86
89
  type: :development
90
+ requirement: *id005
87
91
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
92
+ - !ruby/object:Gem::Dependency
93
+ name: json
94
+ version_requirements: &id006 !ruby/object:Gem::Requirement
89
95
  none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ requirement: *id006
105
+ prerelease: false
94
106
  description: Simple beanstalkd client for ruby
95
- email:
107
+ email:
96
108
  - nico.taing@gmail.com
97
109
  executables: []
110
+
98
111
  extensions: []
112
+
99
113
  extra_rdoc_files: []
100
- files:
114
+
115
+ files:
101
116
  - .gitignore
102
117
  - .yardopts
103
118
  - CHANGELOG.md
@@ -109,6 +124,7 @@ files:
109
124
  - beaneater.gemspec
110
125
  - examples/demo.rb
111
126
  - lib/beaneater.rb
127
+ - lib/beaneater/configuration.rb
112
128
  - lib/beaneater/connection.rb
113
129
  - lib/beaneater/errors.rb
114
130
  - lib/beaneater/job.rb
@@ -135,31 +151,40 @@ files:
135
151
  - test/test_helper.rb
136
152
  - test/tube_test.rb
137
153
  - test/tubes_test.rb
138
- homepage: ''
154
+ homepage: ""
139
155
  licenses: []
156
+
140
157
  post_install_message:
141
158
  rdoc_options: []
142
- require_paths:
159
+
160
+ require_paths:
143
161
  - lib
144
- required_ruby_version: !ruby/object:Gem::Requirement
162
+ required_ruby_version: !ruby/object:Gem::Requirement
145
163
  none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
172
  none: false
152
- requirements:
153
- - - ! '>='
154
- - !ruby/object:Gem::Version
155
- version: '0'
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ hash: 3
177
+ segments:
178
+ - 0
179
+ version: "0"
156
180
  requirements: []
181
+
157
182
  rubyforge_project:
158
183
  rubygems_version: 1.8.24
159
184
  signing_key:
160
185
  specification_version: 3
161
186
  summary: Simple beanstalkd client for ruby.
162
- test_files:
187
+ test_files:
163
188
  - test/beaneater_test.rb
164
189
  - test/connection_test.rb
165
190
  - test/errors_test.rb