rabbit_jobs 0.7.9 → 0.8.0
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/examples/client +5 -3
- data/examples/configuration.rb +1 -1
- data/examples/worker +2 -2
- data/lib/rabbit_jobs/consumer/job_consumer.rb +19 -24
- data/lib/rabbit_jobs/job.rb +18 -1
- data/lib/rabbit_jobs/publisher.rb +3 -19
- data/lib/rabbit_jobs/version.rb +1 -1
- data/spec/fixtures/jobs.rb +7 -5
- data/spec/integration/worker_spec.rb +0 -28
- data/spec/unit/error_mailer_spec.rb +14 -0
- data/spec/unit/job_consumer_spec.rb +63 -0
- metadata +14 -12
data/examples/client
CHANGED
@@ -7,20 +7,22 @@ require File.expand_path('../../lib/rabbit_jobs', __FILE__)
|
|
7
7
|
|
8
8
|
class MyCurrentJob
|
9
9
|
include RJ::Job
|
10
|
-
|
10
|
+
queue :failover_test
|
11
|
+
def perform(count)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
15
|
RJ.configure { |c|
|
15
16
|
c.queue "failover_test"
|
16
|
-
c.server "amqp://localhost/
|
17
|
+
c.server "amqp://localhost/rj"
|
17
18
|
}
|
18
19
|
|
19
20
|
i = 0
|
20
21
|
loop do
|
21
22
|
puts "publishing job #{i}"
|
22
23
|
begin
|
23
|
-
RJ.publish_to(:failover_test, MyCurrentJob, i)
|
24
|
+
# RJ.publish_to(:failover_test, MyCurrentJob, i)
|
25
|
+
MyCurrentJob.perform_async(i)
|
24
26
|
rescue Exception => e
|
25
27
|
# RJ::Publisher.amqp_connection.stop
|
26
28
|
puts e.message
|
data/examples/configuration.rb
CHANGED
data/examples/worker
CHANGED
@@ -7,7 +7,7 @@ require File.expand_path('../../lib/rabbit_jobs', __FILE__)
|
|
7
7
|
|
8
8
|
class MyCurrentJob
|
9
9
|
include RJ::Job
|
10
|
-
def
|
10
|
+
def perform(count = 0)
|
11
11
|
puts count
|
12
12
|
# RJ.publish_to(:default, MyCurrentJob, count - 1) if count > 0
|
13
13
|
end
|
@@ -15,7 +15,7 @@ end
|
|
15
15
|
|
16
16
|
RJ.configure { |c|
|
17
17
|
c.queue "failover_test"
|
18
|
-
c.server "amqp://localhost/
|
18
|
+
c.server "amqp://localhost/rj"
|
19
19
|
}
|
20
20
|
|
21
21
|
worker = RJ::Worker.new
|
@@ -2,46 +2,41 @@
|
|
2
2
|
module RabbitJobs
|
3
3
|
module Consumer
|
4
4
|
class JobConsumer
|
5
|
+
include RabbitJobs::Helpers
|
6
|
+
|
5
7
|
def process_message(delivery_info, properties, payload)
|
6
8
|
job, *error_args = RJ::Job.parse(payload)
|
7
9
|
|
8
10
|
if job.is_a?(Symbol)
|
9
11
|
report_error(job, *error_args)
|
10
|
-
# case @job
|
11
|
-
# when :not_found
|
12
|
-
# when :parsing_error
|
13
|
-
# when :error
|
14
|
-
# end
|
15
12
|
else
|
16
13
|
if job.expired?
|
17
14
|
RJ.logger.warn "Job expired: #{job.to_ruby_string}"
|
18
|
-
false
|
19
15
|
else
|
20
16
|
job.run_perform
|
21
17
|
end
|
22
18
|
end
|
23
|
-
|
24
19
|
true
|
25
20
|
end
|
26
|
-
end
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
def log_error(msg)
|
23
|
+
RJ.logger.error msg
|
24
|
+
end
|
31
25
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
26
|
+
def report_error(error_type, *args)
|
27
|
+
case error_type
|
28
|
+
when :not_found
|
29
|
+
log_error "Cannot find job class '#{args.first}'"
|
30
|
+
when :parsing_error
|
31
|
+
log_error "Cannot initialize job. Json parsing error."
|
32
|
+
log_error "Data received: #{args.first.inspect}"
|
33
|
+
when :error
|
34
|
+
ex, payload = args
|
35
|
+
log_error "Cannot initialize job."
|
36
|
+
log_error ex.message
|
37
|
+
log_error _cleanup_backtrace(ex.backtrace).join("\n")
|
38
|
+
log_error "Data received: #{payload.inspect}"
|
39
|
+
end
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
data/lib/rabbit_jobs/job.rb
CHANGED
@@ -18,7 +18,7 @@ module RabbitJobs
|
|
18
18
|
begin
|
19
19
|
start_time = Time.now
|
20
20
|
RabbitJobs.logger.info "Started to perform #{self.to_ruby_string}"
|
21
|
-
self.
|
21
|
+
self.perform(*params)
|
22
22
|
execution_time = Time.now - start_time
|
23
23
|
RabbitJobs.logger.info " Job completed #{self.to_ruby_string} in #{execution_time} seconds."
|
24
24
|
rescue
|
@@ -117,6 +117,23 @@ module RabbitJobs
|
|
117
117
|
@rj_on_error_hooks << proc_or_symbol
|
118
118
|
end
|
119
119
|
end
|
120
|
+
|
121
|
+
def queue(routing_key)
|
122
|
+
raise ArgumentError unless routing_key.present?
|
123
|
+
@rj_queue = routing_key.to_sym
|
124
|
+
end
|
125
|
+
|
126
|
+
def perform_async(*args)
|
127
|
+
RJ::Publisher.publish_to(@rj_queue || :jobs, self, *args)
|
128
|
+
end
|
129
|
+
|
130
|
+
def serialize_job(*params)
|
131
|
+
{
|
132
|
+
'class' => self.to_s,
|
133
|
+
'opts' => {'created_at' => Time.now.to_i},
|
134
|
+
'params' => params
|
135
|
+
}.to_json
|
136
|
+
end
|
120
137
|
end
|
121
138
|
|
122
139
|
def self.parse(payload)
|
@@ -15,12 +15,7 @@ module RabbitJobs
|
|
15
15
|
routing_key = routing_key.to_sym unless routing_key.is_a?(Symbol)
|
16
16
|
raise ArgumentError.new("routing_key=#{routing_key}") unless RabbitJobs.config[:queues][routing_key]
|
17
17
|
|
18
|
-
payload =
|
19
|
-
'class' => klass.to_s,
|
20
|
-
'opts' => {'created_at' => Time.now.to_i},
|
21
|
-
'params' => params
|
22
|
-
}.to_json
|
23
|
-
|
18
|
+
payload = klass.serialize_job(*params)
|
24
19
|
direct_publish_to(routing_key, payload)
|
25
20
|
end
|
26
21
|
|
@@ -39,24 +34,13 @@ module RabbitJobs
|
|
39
34
|
true
|
40
35
|
end
|
41
36
|
|
42
|
-
def queue_status(routing_key)
|
43
|
-
raise ArgumentError unless routing_key.present?
|
44
|
-
|
45
|
-
routing_key = routing_key.to_sym
|
46
|
-
queue_declare_ok = connection.default_channel.queue_declare(routing_key, RabbitJobs.config[:queues][routing_key].merge(passive: true))
|
47
|
-
{
|
48
|
-
message_count: queue_declare_ok.message_count,
|
49
|
-
consumer_count: queue_declare_ok.consumer_count
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
37
|
def purge_queue(*routing_keys)
|
54
38
|
raise ArgumentError unless routing_keys.present?
|
55
39
|
|
56
40
|
messages_count = 0
|
57
|
-
|
58
41
|
routing_keys.map(&:to_sym).each do |routing_key|
|
59
|
-
|
42
|
+
queue = connection.default_channel.queue(routing_key, RabbitJobs.config[:queues][routing_key])
|
43
|
+
messages_count += queue.status[:message_count].to_i
|
60
44
|
connection.default_channel.queue_purge(routing_key)
|
61
45
|
end
|
62
46
|
|
data/lib/rabbit_jobs/version.rb
CHANGED
data/spec/fixtures/jobs.rb
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
class TestJob
|
4
4
|
include RJ::Job
|
5
|
+
def perform
|
6
|
+
end
|
5
7
|
end
|
6
8
|
|
7
9
|
class PrintTimeJob
|
8
10
|
include RJ::Job
|
9
11
|
|
10
|
-
def
|
12
|
+
def perform(time)
|
11
13
|
puts "Running job queued at #{time}"
|
12
14
|
end
|
13
15
|
end
|
@@ -15,7 +17,7 @@ end
|
|
15
17
|
class JobWithExpire
|
16
18
|
include RJ::Job
|
17
19
|
expires_in 60*60 # expires in 1 hour
|
18
|
-
def
|
20
|
+
def perform
|
19
21
|
|
20
22
|
end
|
21
23
|
end
|
@@ -23,7 +25,7 @@ end
|
|
23
25
|
class ExpiredJob
|
24
26
|
include RJ::Job
|
25
27
|
|
26
|
-
def
|
28
|
+
def perform
|
27
29
|
|
28
30
|
end
|
29
31
|
end
|
@@ -31,7 +33,7 @@ end
|
|
31
33
|
class JobWithPublish
|
32
34
|
include RJ::Job
|
33
35
|
|
34
|
-
def
|
36
|
+
def perform(param = 0)
|
35
37
|
if param < 5
|
36
38
|
puts "publishing job #{param}"
|
37
39
|
RJ.publish_to :rspec_durable_queue, JobWithPublish, param + 1
|
@@ -53,7 +55,7 @@ class JobWithErrorHook
|
|
53
55
|
puts 'last hook'
|
54
56
|
end
|
55
57
|
|
56
|
-
def
|
58
|
+
def perform
|
57
59
|
raise "Job raised an error at #{Time.now}"
|
58
60
|
end
|
59
61
|
end
|
@@ -2,34 +2,6 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe RabbitJobs::Worker do
|
5
|
-
it 'should listen for messages' do
|
6
|
-
RabbitJobs.configure do |c|
|
7
|
-
c.server 'amqp://localhost/rj'
|
8
|
-
c.queue 'rspec_durable_queue', auto_delete: false, durable: true, ack: true
|
9
|
-
end
|
10
|
-
|
11
|
-
RJ::Publisher.purge_queue('rspec_durable_queue')
|
12
|
-
count = 5
|
13
|
-
5.times {
|
14
|
-
RabbitJobs.publish_to(:rspec_durable_queue, PrintTimeJob, Time.now)
|
15
|
-
}
|
16
|
-
|
17
|
-
Timecop.freeze(Time.now - 4600) {
|
18
|
-
5.times { RabbitJobs.publish_to(:rspec_durable_queue, JobWithExpire) }
|
19
|
-
}
|
20
|
-
|
21
|
-
RabbitJobs.publish_to(:rspec_durable_queue, JobWithErrorHook)
|
22
|
-
|
23
|
-
worker = RabbitJobs::Worker.new
|
24
|
-
RJ.logger.level = Logger::FATAL
|
25
|
-
|
26
|
-
mock(PrintTimeJob).perform(anything).times(5)
|
27
|
-
mock(JobWithErrorHook).perform
|
28
|
-
dont_allow(JobWithExpire).perform
|
29
|
-
worker.work(1) # work for 1 second
|
30
|
-
RJ::Publisher.purge_queue('rspec_durable_queue')
|
31
|
-
end
|
32
|
-
|
33
5
|
it 'should allow to publish jobs from worker' do
|
34
6
|
RabbitJobs.configure do |c|
|
35
7
|
c.server 'amqp://localhost/rj'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe RabbitJobs::ErrorMailer do
|
5
|
+
describe '#report_error' do
|
6
|
+
it 'logs error raised in #send_letter' do
|
7
|
+
mock(RabbitJobs::ErrorMailer).enabled? { true }
|
8
|
+
mock(RabbitJobs::ErrorMailer).send_letter(anything, anything) { raise 'hello' }
|
9
|
+
|
10
|
+
mock(RabbitJobs.logger).error(anything)
|
11
|
+
RabbitJobs::ErrorMailer.report_error(TestJob.new, StandardError.new)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe RabbitJobs::Consumer::JobConsumer do
|
5
|
+
let(:consumer) { RabbitJobs::Consumer::JobConsumer.new }
|
6
|
+
let(:job) { TestJob.new }
|
7
|
+
|
8
|
+
describe '#process_message' do
|
9
|
+
it 'parses job' do
|
10
|
+
payload = TestJob.serialize_job
|
11
|
+
mock(RJ::Job).parse(payload) { job }
|
12
|
+
consumer.process_message(:delivery_info, :properties, payload)
|
13
|
+
end
|
14
|
+
it 'reports parsing errors' do
|
15
|
+
payload = "some bad json data"
|
16
|
+
mock(consumer).report_error(:parsing_error, payload)
|
17
|
+
consumer.process_message(:delivery_info, :properties, payload).should == true
|
18
|
+
end
|
19
|
+
it 'skips expired jobs' do
|
20
|
+
payload = TestJob.serialize_job
|
21
|
+
job
|
22
|
+
mock(TestJob).new { job }
|
23
|
+
mock(job).expired? { true }
|
24
|
+
dont_allow(job).run_perform
|
25
|
+
consumer.process_message(:delivery_info, :properties, payload)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'executes job.perform' do
|
29
|
+
payload = TestJob.serialize_job
|
30
|
+
job
|
31
|
+
mock(TestJob).new { job }
|
32
|
+
mock(job).run_perform
|
33
|
+
consumer.process_message(:delivery_info, :properties, payload)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#log_error' do
|
38
|
+
it 'logs error with RJ.logger' do
|
39
|
+
mock(RJ.logger).error("hello")
|
40
|
+
consumer.log_error 'hello'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#report_error' do
|
45
|
+
it "accepts error type :not_found" do
|
46
|
+
lambda { consumer.report_error(:not_found, 'klass_name') }.should_not raise_error
|
47
|
+
end
|
48
|
+
|
49
|
+
it "accepts error type :parsing_error" do
|
50
|
+
lambda { consumer.report_error(:parsing_error, 'payload data') }.should_not raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "accepts error type :error" do
|
54
|
+
exception = nil
|
55
|
+
begin
|
56
|
+
raise 'testing'
|
57
|
+
rescue Exception => e
|
58
|
+
exception = e
|
59
|
+
end
|
60
|
+
lambda { consumer.report_error(:error, exception, 'payload data') }.should_not raise_error
|
61
|
+
end
|
62
|
+
end
|
63
|
+
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.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bunny
|
16
|
-
requirement: &
|
16
|
+
requirement: &4081060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.9.0.pre8
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *4081060
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &4074840 !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: *
|
35
|
+
version_requirements: *4074840
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rufus-scheduler
|
38
|
-
requirement: &
|
38
|
+
requirement: &4466480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '2.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *4466480
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rails
|
49
|
-
requirement: &
|
49
|
+
requirement: &4465120 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '3.0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *4465120
|
58
58
|
description: Background jobs on RabbitMQ
|
59
59
|
email:
|
60
60
|
- lazureykis@gmail.com
|
@@ -97,6 +97,8 @@ files:
|
|
97
97
|
- spec/integration/worker_spec.rb
|
98
98
|
- spec/spec_helper.rb
|
99
99
|
- spec/unit/configuration_spec.rb
|
100
|
+
- spec/unit/error_mailer_spec.rb
|
101
|
+
- spec/unit/job_consumer_spec.rb
|
100
102
|
- spec/unit/job_spec.rb
|
101
103
|
- spec/unit/mailer_spec.rb
|
102
104
|
- spec/unit/rabbit_jobs_spec.rb
|
@@ -115,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
117
|
version: '0'
|
116
118
|
segments:
|
117
119
|
- 0
|
118
|
-
hash:
|
120
|
+
hash: 3460661242446233476
|
119
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
122
|
none: false
|
121
123
|
requirements:
|
@@ -124,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
126
|
version: '0'
|
125
127
|
segments:
|
126
128
|
- 0
|
127
|
-
hash:
|
129
|
+
hash: 3460661242446233476
|
128
130
|
requirements: []
|
129
131
|
rubyforge_project:
|
130
132
|
rubygems_version: 1.8.11
|