rabbit_jobs 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,12 +2,13 @@ source :rubygems
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rabbit_jobs', :path => './'
6
-
7
5
  group :development do
6
+ gem 'actionmailer', '>= 3.0'
7
+
8
8
  gem 'rspec', '~> 2.8'
9
9
  gem 'rr'
10
10
  gem 'autotest'
11
- # gem 'fs-event'
11
+ gem 'autotest-fsevent'
12
+ gem 'autotest-growl'
12
13
  gem 'simplecov', require: false
13
14
  end
data/lib/rabbit_jobs.rb CHANGED
@@ -6,6 +6,7 @@ require 'rabbit_jobs/helpers'
6
6
  require 'rabbit_jobs/amqp_helpers'
7
7
  require 'rabbit_jobs/configuration'
8
8
  require 'rabbit_jobs/logger'
9
+ require 'rabbit_jobs/error_mailer'
9
10
 
10
11
  require 'rabbit_jobs/job'
11
12
  require 'rabbit_jobs/publisher'
@@ -49,6 +49,7 @@ module RabbitJobs
49
49
 
50
50
  def initialize
51
51
  @data = {
52
+ error_log: true,
52
53
  host: 'localhost',
53
54
  exchange: 'rabbit_jobs',
54
55
  exchange_params: DEFAULT_EXCHANGE_PARAMS,
@@ -60,6 +61,27 @@ module RabbitJobs
60
61
  @data[name]
61
62
  end
62
63
 
64
+ def mail_errors_to(email = nil, from_email = nil)
65
+ if email && from_email
66
+ @data[:mail_errors_to] = email
67
+ @data[:mail_errors_form] = from_email
68
+ else
69
+ @data[:mail_errors_to]
70
+ end
71
+ end
72
+
73
+ def mail_errors_from
74
+ @data[:mail_errors_form]
75
+ end
76
+
77
+ def error_log
78
+ @data[:error_log]
79
+ end
80
+
81
+ def disable_error_log
82
+ @data[:error_log] = false
83
+ end
84
+
63
85
  def host(value = nil)
64
86
  if value
65
87
  raise ArgumentError unless value.is_a?(String) && value != ""
@@ -0,0 +1,37 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module RabbitJobs
4
+ class ErrorMailer
5
+ include RabbitJobs::Logger
6
+
7
+ def self.enabled?
8
+ !!RabbitJobs.config.mail_errors_from && !RabbitJobs.config.mail_errors_from.empty?
9
+ end
10
+
11
+ def self.send(job, error = $!)
12
+ return unless enabled?
13
+
14
+ raise "You must require action_mailer or turn of error reporting in config." unless defined?(ActionMailer)
15
+
16
+ params ||= []
17
+
18
+ params_str = job.params == [] ? '' : job.params.map { |p| p.inspect }.join(', ')
19
+ subject = "RJ:Worker: #{error.class} on #{job.class}.perform(#{params_str}) "
20
+ text = "\n#{job.class}.perform(#{params_str})\n"
21
+ text += "\n#{error.inspect}\n"
22
+ text += "\nBacktrace:\n#{error.backtrace.join("\n")}" if error.backtrace
23
+
24
+ letter = ActionMailer::Base.mail
25
+ letter.from = RabbitJobs.config.mail_errors_from
26
+ letter.to = RabbitJobs.config.mail_errors_to
27
+ letter.subject = subject
28
+ letter.body = text
29
+
30
+ begin
31
+ letter.deliver
32
+ rescue
33
+ log $!.inspect
34
+ end
35
+ end
36
+ end
37
+ end
@@ -30,12 +30,34 @@ module RabbitJobs::Job
30
30
  self.class.perform(*params)
31
31
  # log 'after perform'
32
32
  rescue
33
- puts $!.inspect
33
+ RabbitJobs::Logger.log($!.inspect) if RabbitJobs.config.error_log
34
+ RabbitJobs::ErrorMailer.send(self, $!)
35
+
36
+ run_on_error_hooks($!)
34
37
  end
35
38
  exit!
36
39
  end
37
40
  end
38
41
 
42
+ def run_on_error_hooks(error)
43
+ if self.class.rj_on_error_hooks
44
+ self.class.rj_on_error_hooks.each do |proc_or_symbol|
45
+ if proc_or_symbol.is_a?(Symbol)
46
+ self.send(proc_or_symbol, error, *params)
47
+ else
48
+ case proc_or_symbol.arity
49
+ when 0
50
+ proc_or_symbol.call()
51
+ when 1
52
+ proc_or_symbol.call(error)
53
+ else
54
+ proc_or_symbol.call(error, *params)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
39
61
  def payload
40
62
  {'class' => self.class.to_s, 'opts' => (self.opts || {}), 'params' => params}.to_json
41
63
  # ([self.class.to_s] + params).to_json
@@ -46,14 +68,14 @@ module RabbitJobs::Job
46
68
  end
47
69
 
48
70
  def expires?
49
- !!self.expires_in
71
+ self.expires_in && self.expires_in > 0
50
72
  end
51
73
 
52
74
  def expired?
53
75
  if self.opts['expires_at']
54
- Time.now > Time.new(opts['expires_at'])
76
+ Time.now.to_i > opts['expires_at'].to_i
55
77
  elsif expires? && opts['created_at']
56
- Time.now > (Time.new(opts['created_at']) + expires_in)
78
+ Time.now.to_i > (opts['created_at'].to_i + expires_in.to_i)
57
79
  else
58
80
  false
59
81
  end
@@ -61,11 +83,19 @@ module RabbitJobs::Job
61
83
  end
62
84
 
63
85
  module ClassMethods
64
- attr_accessor :rj_expires_in
86
+ attr_accessor :rj_expires_in, :rj_on_error_hooks
65
87
 
66
88
  # DSL method for jobs
67
89
  def expires_in(seconds)
68
- @rj_expires_in = seconds
90
+ @rj_expires_in = seconds.to_i
91
+ end
92
+
93
+ def on_error(*hooks)
94
+ hooks.each do |proc_or_symbol|
95
+ raise ArgumentError unless proc_or_symbol && ( proc_or_symbol.is_a?(Proc) || proc_or_symbol.is_a?(Symbol) )
96
+ @rj_on_error_hooks ||= []
97
+ @rj_on_error_hooks << proc_or_symbol
98
+ end
69
99
  end
70
100
  end
71
101
 
@@ -33,7 +33,7 @@ module RabbitJobs
33
33
 
34
34
  queue = make_queue(exchange, routing_key)
35
35
 
36
- job.opts['created_at'] = Time.now.to_s
36
+ job.opts['created_at'] = Time.now.to_i
37
37
 
38
38
  payload = job.payload
39
39
  exchange.publish(job.payload, Configuration::DEFAULT_MESSAGE_PARAMS.merge({routing_key: routing_key})) {
@@ -46,10 +46,9 @@ module RabbitJobs
46
46
 
47
47
  def em_publish_job_to(routing_key, job)
48
48
  em_amqp_with_exchange do |connection, exchange|
49
-
50
49
  queue = make_queue(exchange, routing_key)
51
50
 
52
- job.opts['created_at'] = Time.now.to_s
51
+ job.opts['created_at'] = Time.now.to_i
53
52
 
54
53
  payload = job.payload
55
54
  exchange.publish(job.payload, Configuration::DEFAULT_MESSAGE_PARAMS.merge({routing_key: routing_key})) {
@@ -38,8 +38,8 @@ module RabbitJobs
38
38
  interval_types = %w{cron every}
39
39
  interval_types.each do |interval_type|
40
40
  if !config[interval_type].nil? && config[interval_type].length > 0
41
+ log "queueing #{config['class']} (#{name})"
41
42
  rufus_scheduler.send(interval_type, config[interval_type]) do
42
- log! "queueing #{config['class']} (#{name})"
43
43
  publish_from_config(config)
44
44
  end
45
45
  interval_defined = true
@@ -68,7 +68,7 @@ module RabbitJobs
68
68
  log "publishing #{config}"
69
69
  RabbitJobs.publish_to(queue, klass_name.constantize, nil, *params)
70
70
  rescue
71
- log! "Failed to enqueue #{klass_name}:\n #{$!}\n params = #{params.inspect}"
71
+ log! "Failed to publish #{klass_name}:\n #{$!}\n params = #{params.inspect}"
72
72
  end
73
73
 
74
74
  def rufus_scheduler
@@ -103,7 +103,6 @@ module RabbitJobs
103
103
  if time > 0
104
104
  # for debugging
105
105
  EM.add_timer(time) do
106
- log "Stopping scheduler..."
107
106
  self.shutdown
108
107
  end
109
108
  end
@@ -1,3 +1,3 @@
1
1
  module RabbitJobs
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -56,9 +56,11 @@ module RabbitJobs
56
56
 
57
57
  queue.subscribe(ack: true) do |metadata, payload|
58
58
  @job = RabbitJobs::Job.parse(payload)
59
- @job.run_perform unless @job.expired?
60
- metadata.ack
61
- processed_count += 1
59
+ unless @job.expired?
60
+ @job.run_perform
61
+ metadata.ack
62
+ processed_count += 1
63
+ end
62
64
  check_shutdown.call
63
65
  end
64
66
  end
@@ -26,4 +26,21 @@ class ExpiredJob
26
26
  def self.perform
27
27
 
28
28
  end
29
+ end
30
+
31
+ class JobWithErrorHook
32
+ include RabbitJobs::Job
33
+ on_error :first_hook, lambda { puts "second hook" }, :last_hook
34
+
35
+ def first_hook(error)
36
+ puts 'first hook'
37
+ end
38
+
39
+ def last_hook(error)
40
+ puts 'last hook'
41
+ end
42
+
43
+ def self.perform
44
+ raise "Job raised an error at #{Time.now}"
45
+ end
29
46
  end
@@ -11,6 +11,7 @@ describe RabbitJobs::Worker do
11
11
 
12
12
  5.times { RabbitJobs.publish(PrintTimeJob, nil, Time.now) }
13
13
  5.times { RabbitJobs.publish(ExpiredJob, { :expires_at => Time.now - 10 }) }
14
+ 1.times { RabbitJobs.publish(JobWithErrorHook) }
14
15
  worker = RabbitJobs::Worker.new
15
16
 
16
17
  worker.work(1) # work for 1 second
@@ -4,6 +4,8 @@ require 'spec_helper'
4
4
  describe RabbitJobs::Configuration do
5
5
  it 'builds configuration from configure block' do
6
6
  RabbitJobs.configure do |c|
7
+ c.disable_error_log
8
+
7
9
  c.host "somehost.lan"
8
10
 
9
11
  c.exchange 'my_exchange', durable: true, auto_delete: false
@@ -13,6 +15,7 @@ describe RabbitJobs::Configuration do
13
15
  end
14
16
 
15
17
  RabbitJobs.config.to_hash.should == {
18
+ error_log: false,
16
19
  host: "somehost.lan",
17
20
  exchange: "my_exchange",
18
21
  exchange_params: {
@@ -63,6 +66,7 @@ describe RabbitJobs::Configuration do
63
66
 
64
67
  it 'use default config' do
65
68
  RabbitJobs.config.to_hash.should == {
69
+ error_log: true,
66
70
  host: "localhost",
67
71
  exchange: "rabbit_jobs",
68
72
  exchange_params: {
@@ -80,6 +84,7 @@ describe RabbitJobs::Configuration do
80
84
  end
81
85
 
82
86
  it 'returns settings on some methods' do
87
+ RabbitJobs.config.error_log == true
83
88
  RabbitJobs.config.host.should == 'localhost'
84
89
  RabbitJobs.config[:host].should == 'localhost'
85
90
  RabbitJobs.config.routing_keys.should == ['default']
@@ -16,14 +16,20 @@ describe RabbitJobs::Job do
16
16
  context 'job expiration' do
17
17
  it 'should expire job by expires_in option' do
18
18
  job = TestJob.new
19
- job.opts['expires_at'] = (Time.now - 10).to_s
19
+ job.opts['expires_at'] = (Time.now - 10).to_i
20
20
  job.expired?.should == true
21
21
  end
22
22
 
23
23
  it 'should expire job by expires_in option in job class and current_time' do
24
24
  job = JobWithExpire.new(1, 2, 3)
25
- job.opts['created_at'] = (Time.now - job.expires_in - 10).to_s
25
+ job.opts['created_at'] = (Time.now - job.expires_in - 10).to_i
26
26
  job.expired?.should == true
27
27
  end
28
+
29
+ it 'should not be expired with default params' do
30
+ job = TestJob.new(1, 2, 3)
31
+ job.opts['created_at'] = (Time.now).to_i
32
+ job.expired?.should == false
33
+ end
28
34
  end
29
35
  end
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'action_mailer'
4
+
5
+ describe RabbitJobs::ErrorMailer do
6
+ describe '#enabled?' do
7
+ it 'should be enabled when use setup email' do
8
+ RabbitJobs::ErrorMailer.enabled?.should == false
9
+ RabbitJobs.configure do |c|
10
+ c.mail_errors_to 'dev@exampe.com', 'app@example.com'
11
+ end
12
+ RabbitJobs::ErrorMailer.enabled?.should == true
13
+ end
14
+ end
15
+
16
+ describe '#send' do
17
+ it 'should send email with error' do
18
+ email = ActionMailer::Base.mail
19
+ mock(ActionMailer::Base).mail { email }
20
+ mock(email).deliver { }
21
+ mock(RabbitJobs::ErrorMailer).enabled? { true }
22
+
23
+ RabbitJobs::ErrorMailer.send(TestJob.new, RuntimeError.new('error text'))
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbit_jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: amqp
16
- requirement: &70230061017880 !ruby/object:Gem::Requirement
16
+ requirement: &70238047574860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0.9'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70230061017880
24
+ version_requirements: *70238047574860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70230061016460 !ruby/object:Gem::Requirement
27
+ requirement: &70238047573560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70230061016460
35
+ version_requirements: *70238047573560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rufus-scheduler
38
- requirement: &70230061008760 !ruby/object:Gem::Requirement
38
+ requirement: &70238047572140 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '2.0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70230061008760
46
+ version_requirements: *70238047572140
47
47
  description: Background jobs on RabbitMQ
48
48
  email:
49
49
  - lazureykis@gmail.com
@@ -61,6 +61,7 @@ files:
61
61
  - lib/rabbit_jobs.rb
62
62
  - lib/rabbit_jobs/amqp_helpers.rb
63
63
  - lib/rabbit_jobs/configuration.rb
64
+ - lib/rabbit_jobs/error_mailer.rb
64
65
  - lib/rabbit_jobs/helpers.rb
65
66
  - lib/rabbit_jobs/job.rb
66
67
  - lib/rabbit_jobs/logger.rb
@@ -81,6 +82,7 @@ files:
81
82
  - spec/unit/configuration_spec.rb
82
83
  - spec/unit/job_spec.rb
83
84
  - spec/unit/logger_spec.rb
85
+ - spec/unit/mailer_spec.rb
84
86
  - spec/unit/rabbit_jobs_spec.rb
85
87
  - spec/unit/worker_spec.rb
86
88
  homepage: ''
@@ -118,5 +120,6 @@ test_files:
118
120
  - spec/unit/configuration_spec.rb
119
121
  - spec/unit/job_spec.rb
120
122
  - spec/unit/logger_spec.rb
123
+ - spec/unit/mailer_spec.rb
121
124
  - spec/unit/rabbit_jobs_spec.rb
122
125
  - spec/unit/worker_spec.rb