juggler 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/examples/app.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+
4
+ get '/slow' do
5
+ sleep 3
6
+ return 'Finally done'
7
+ end
@@ -1,12 +1,15 @@
1
1
  require 'rubygems'
2
2
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'juggler'
4
+ require 'eventmachine'
5
+
6
+ Juggler.logger = Logger.new(STDOUT)
4
7
 
5
8
  EM.run {
6
9
  Juggler.juggle(:http, 3) do |path|
7
10
  http = EM::Protocols::HttpClient.request({
8
- :host => "0.0.0.0",
9
- :port => 3000,
11
+ :host => "localhost",
12
+ :port => 4567,
10
13
  :request => path
11
14
  })
12
15
  http.callback do |response|
@@ -2,10 +2,19 @@ require 'rubygems'
2
2
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'juggler'
4
4
 
5
+ Juggler.logger = Logger.new(STDOUT)
6
+
5
7
  # Throw some jobs
6
8
 
7
- 10.times do |i|
9
+ class Foo; end
10
+
11
+ 2.times do |i|
8
12
  path = ['/fast', '/slow'][i % 2]
9
- Juggler.throw(:http, path)
13
+ Juggler.throw(:http, path, {
14
+ :ttr => 1
15
+ })
10
16
  end
11
17
  10.times { Juggler.throw(:timer, {:foo => 'bar'}) }
18
+
19
+ # Test that unmarshaling errors are handled
20
+ Juggler.throw(:http, Foo.new)
data/lib/juggler.rb CHANGED
@@ -22,7 +22,13 @@ class Juggler
22
22
  def throw(method, params, options = {})
23
23
  # TODO: Do some checking on the method
24
24
  connection.use(method.to_s)
25
- connection.put(Marshal.dump(params))
25
+
26
+ priority = options[:priority] || 50
27
+ delay = 0
28
+ # Add 2s because we want to handle the timeout before beanstalk does
29
+ ttr = (options[:ttr] || 60) + 2
30
+
31
+ connection.put(Marshal.dump(params), priority, delay, ttr)
26
32
  end
27
33
 
28
34
  def juggle(method, concurrency = 1, &strategy)
@@ -19,19 +19,46 @@ class Juggler
19
19
 
20
20
  def reserve
21
21
  beanstalk_job = connection.reserve(0)
22
- params = Marshal.load(beanstalk_job.body)
23
- job = @strategy.call(params)
22
+
23
+ begin
24
+ params = Marshal.load(beanstalk_job.body)
25
+ rescue => e
26
+ handle_exception(e, "Exception unmarshaling #{@queue} job")
27
+ beanstalk_job.delete
28
+ return
29
+ end
30
+
31
+ begin
32
+ job = @strategy.call(params)
33
+ rescue => e
34
+ handle_exception(e, "Exception calling #{@queue} strategy")
35
+ beanstalk_job.decay
36
+ return
37
+ end
38
+
39
+ EM::Timer.new(beanstalk_job.ttr - 2) do
40
+ job.fail(:timeout)
41
+ end
42
+
24
43
  @running << job
25
44
  job.callback do
26
45
  @running.delete(job)
27
46
  beanstalk_job.delete
28
47
  end
29
- job.errback do
48
+ job.errback do |error|
49
+ Juggler.logger.info("#{@queue} job failed: #{error}")
30
50
  @running.delete(job)
31
51
  # Built in exponential backoff
32
52
  beanstalk_job.decay
33
53
  end
34
54
  rescue Beanstalk::TimedOut
55
+ rescue Beanstalk::NotConnected
56
+ Juggler.logger.fatal "Could not connect any beanstalk hosts. " \
57
+ "Retrying in 1s."
58
+ sleep 1
59
+ rescue => e
60
+ handle_exception(e, "Unhandled exception")
61
+ beanstalk_job.delete if beanstalk_job
35
62
  end
36
63
 
37
64
  def run
@@ -47,6 +74,11 @@ class Juggler
47
74
  @running.size < @concurrency
48
75
  end
49
76
 
77
+ def handle_exception(e, message)
78
+ Juggler.logger.error "#{message}: #{e.class} #{e.message}"
79
+ Juggler.logger.debug e.backtrace.join("\n")
80
+ end
81
+
50
82
  def connection
51
83
  @pool ||= begin
52
84
  pool = Beanstalk::Pool.new(Juggler.hosts)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: juggler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martyn Loughran
@@ -66,5 +66,6 @@ test_files:
66
66
  - spec/juggler_spec.rb
67
67
  - spec/runner_spec.rb
68
68
  - spec/spec_helper.rb
69
+ - examples/app.rb
69
70
  - examples/test_consumer.rb
70
71
  - examples/test_producer.rb