rabbit_jobs 0.0.5 → 0.0.6

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/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