rabbit_jobs 0.11.5 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,15 +2,15 @@ require 'rabbit_jobs'
2
2
  require 'rake'
3
3
 
4
4
  def rails_env
5
- $my_rails_env ||= defined?(Rails) ? Rails.env : (ENV['RAILS_ENV'] || 'development')
5
+ defined?(Rails) ? Rails.env : (ENV['RAILS_ENV'] || 'development')
6
6
  end
7
7
 
8
8
  def app_root
9
- $my_rails_root ||= Pathname.new(ENV['RAILS_ROOT'] || Rails.root)
9
+ Pathname.new(ENV['RAILS_ROOT'] || Rails.root)
10
10
  end
11
11
 
12
12
  def make_dirs
13
- ["log", "tmp", "tmp/pids"].each do |subdir|
13
+ %w(log tmp tmp/pids).each do |subdir|
14
14
  dir = app_root.join(subdir)
15
15
  Dir.mkdir(dir) unless File.directory?(dir)
16
16
  end
@@ -21,9 +21,9 @@ namespace :rj do
21
21
  Rails.application.require_environment! if defined?(Rails)
22
22
  end
23
23
 
24
- desc "Start a Rabbit Jobs worker"
25
- task :worker => :environment do
26
- queues = (ENV['QUEUES'] || ENV['QUEUE'] || "").split(',')
24
+ desc 'Starts a Rabbit Jobs worker'
25
+ task worker: :environment do
26
+ queues = (ENV['QUEUES'] || ENV['QUEUE'] || '').split(',')
27
27
  make_dirs
28
28
  worker = RJ::Worker.new(*queues)
29
29
  worker.consumer = RJ::Consumer.const_get(ENV['CONSUMER'].classify).new if ENV['CONSUMER']
@@ -31,11 +31,11 @@ namespace :rj do
31
31
  exit(worker.work)
32
32
  end
33
33
 
34
- desc "Start a Rabbit Jobs scheduler"
34
+ desc 'Starts a Rabbit Jobs scheduler'
35
35
  task :scheduler do
36
36
  make_dirs
37
37
  scheduler = RabbitJobs::Scheduler.new
38
38
  scheduler.process_name = "rj_scheduler #{rails_env}"
39
39
  exit(scheduler.work)
40
40
  end
41
- end
41
+ end
@@ -1,5 +1,3 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
1
  module RabbitJobs
4
- VERSION = "0.11.5"
2
+ VERSION = '0.12.0'
5
3
  end
@@ -1,32 +1,22 @@
1
- # -*- encoding : utf-8 -*-
1
+ require 'rabbit_jobs/amqp_transport'
2
2
 
3
3
  module RabbitJobs
4
+ # Worker daemon.
4
5
  class Worker
5
6
  include MainLoop
6
7
 
8
+ delegate :amqp_connection, :consumer_channel, :amqp_cleanup, to: RabbitJobs::AmqpTransport
9
+
7
10
  attr_accessor :process_name
8
11
  attr_reader :consumer
9
12
 
10
13
  def consumer=(value)
11
- raise ArgumentError.new("value=#{value.inspect}") unless value.respond_to?(:process_message)
14
+ unless value.respond_to?(:process_message)
15
+ fail ArgumentError, 'value must implement #process_message'
16
+ end
12
17
  @consumer = value
13
18
  end
14
19
 
15
- def amqp_connection
16
- Thread.current[:rj_worker_connection] ||= Bunny.new(RabbitJobs.config.server, automatically_recover: false,
17
- properties: Bunny::Session::DEFAULT_CLIENT_PROPERTIES.merge(product: "rj_worker #{Process.pid}")).start
18
- end
19
-
20
- def amqp_channel
21
- @amqp_channel ||= amqp_connection.create_channel
22
- end
23
-
24
- def self.cleanup
25
- conn = Thread.current[:rj_worker_connection]
26
- conn.close if conn && conn.status != :not_connected
27
- Thread.current[:rj_worker_connection] = nil
28
- end
29
-
30
20
  def queue_params(routing_key)
31
21
  RJ.config[:queues][routing_key.to_sym]
32
22
  end
@@ -47,7 +37,8 @@ module RabbitJobs
47
37
  if @queues == ['*'] || @queues.empty?
48
38
  @queues = RabbitJobs.config.routing_keys
49
39
  end
50
- raise "Cannot initialize worker without queues." if @queues.empty?
40
+
41
+ fail 'Cannot initialize worker without queues.' if @queues.empty?
51
42
  end
52
43
 
53
44
  def queues
@@ -55,26 +46,26 @@ module RabbitJobs
55
46
  end
56
47
 
57
48
  # Subscribes to queue and working on jobs
58
- def work(time = -1)
49
+ def work
59
50
  return false unless startup
60
51
  @consumer ||= RJ::Consumer::JobConsumer.new
61
52
 
62
- $0 = self.process_name || "rj_worker (#{queues.join(', ')})"
53
+ $0 = process_name || "rj_worker (#{queues.join(', ')})"
63
54
 
64
55
  @processed_count = 0
65
56
 
66
57
  begin
67
- amqp_channel.prefetch(1)
58
+ consumer_channel.prefetch(1)
68
59
 
69
60
  queues.each do |routing_key|
70
61
  consume_queue(routing_key)
71
62
  end
72
63
 
73
- RJ.logger.info "Started."
64
+ RJ.logger.info 'Started.'
74
65
 
75
- return main_loop(time) {
66
+ return main_loop do
76
67
  RJ.logger.info "Processed jobs: #{@processed_count}."
77
- }
68
+ end
78
69
  rescue
79
70
  log_daemon_error($!)
80
71
  end
@@ -82,29 +73,19 @@ module RabbitJobs
82
73
  true
83
74
  end
84
75
 
85
- def startup
86
- count = RJ._run_after_fork_callbacks
87
-
88
- $stdout.sync = true
89
-
90
- @shutdown = false
91
-
92
- Signal.trap('TERM') { shutdown }
93
- Signal.trap('INT') { shutdown! }
94
-
95
- true
96
- end
97
-
98
76
  private
99
77
 
100
78
  def consume_message(delivery_info, properties, payload)
101
- if (RJ.run_before_process_message_callbacks rescue nil)
79
+ if RJ.run_before_process_message_callbacks
102
80
  begin
103
81
  @consumer.process_message(delivery_info, properties, payload)
104
82
  @processed_count += 1
105
83
  rescue ScriptError, StandardError
106
- RabbitJobs.logger.error(short_message: $!.message,
107
- _payload: payload, _exception: $!.class, full_message: $!.backtrace.join("\r\n"))
84
+ RabbitJobs.logger.error(
85
+ short_message: $!.message,
86
+ _payload: payload,
87
+ _exception: $!.class,
88
+ full_message: $!.backtrace.join("\r\n"))
108
89
  end
109
90
  true
110
91
  else
@@ -117,16 +98,16 @@ module RabbitJobs
117
98
  RJ.logger.info "Subscribing to #{routing_key}"
118
99
  routing_key = routing_key.to_sym
119
100
 
120
- queue = amqp_channel.queue(routing_key, queue_params(routing_key))
101
+ queue = consumer_channel.queue(routing_key, queue_params(routing_key))
121
102
 
122
- explicit_ack = !!queue_params(routing_key)[:ack]
103
+ explicit_ack = queue_params(routing_key)[:manual_ack].present?
123
104
 
124
- queue.subscribe(ack: explicit_ack) do |delivery_info, properties, payload|
105
+ queue.subscribe(manual_ack: explicit_ack) do |delivery_info, properties, payload|
125
106
  if consume_message(delivery_info, properties, payload)
126
- amqp_channel.ack(delivery_info.delivery_tag) if explicit_ack
107
+ consumer_channel.ack(delivery_info.delivery_tag) if explicit_ack
127
108
  else
128
109
  requeue = false
129
- amqp_channel.nack(delivery_info.delivery_tag, requeue) if explicit_ack
110
+ consumer_channel.nack(delivery_info.delivery_tag, requeue) if explicit_ack
130
111
  end
131
112
  end
132
113
  end
@@ -1,2 +1,2 @@
1
1
  $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
2
- require 'rabbit_jobs/tasks'
2
+ require 'rabbit_jobs/tasks'
data/rabbit_jobs.gemspec CHANGED
@@ -1,33 +1,34 @@
1
- $:.push File.expand_path("../lib", __FILE__)
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  require 'rabbit_jobs/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.authors = ["Pavel Lazureykis"]
9
- spec.email = ["lazureykis@gmail.com"]
10
- spec.description = %q{Background jobs on RabbitMQ}
11
- spec.summary = %q{Background jobs on RabbitMQ}
12
- spec.homepage = ""
8
+ spec.authors = ['Pavel Lazureykis']
9
+ spec.email = ['lazureykis@gmail.com']
10
+ spec.description = 'Background jobs on RabbitMQ'
11
+ spec.summary = 'Background jobs on RabbitMQ'
12
+ spec.homepage = ''
13
13
  spec.date = Time.now.strftime('%Y-%m-%d')
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
16
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
- spec.name = "rabbit_jobs"
18
- spec.require_paths = ["lib"]
16
+ spec.test_files = spec.files.grep(/^spec/)
17
+ spec.name = 'rabbit_jobs'
18
+ spec.require_paths = ['lib']
19
19
  spec.version = RabbitJobs::VERSION
20
- spec.license = "MIT"
20
+ spec.license = 'MIT'
21
21
 
22
- spec.add_dependency "bunny", "~> 1.0"
23
- spec.add_dependency "rake"
24
- spec.add_dependency "rufus-scheduler", "~> 3.0"
25
- spec.add_dependency "activesupport", "~> 4.0"
22
+ spec.add_dependency 'bunny', '~> 1.6.0'
23
+ spec.add_dependency 'rake'
24
+ spec.add_dependency 'rufus-scheduler', '~> 3.0'
25
+ spec.add_dependency 'activesupport', '~> 4.0'
26
26
 
27
- spec.add_development_dependency "bundler"
27
+ spec.add_development_dependency 'bundler'
28
28
  # spec.add_development_dependency "rake"
29
- spec.add_development_dependency "timecop"
30
- spec.add_development_dependency "rspec"
31
- spec.add_development_dependency "rr"
32
- spec.add_development_dependency "simplecov"
29
+ spec.add_development_dependency 'timecop'
30
+ spec.add_development_dependency 'rspec'
31
+ spec.add_development_dependency 'rr'
32
+ spec.add_development_dependency 'simplecov'
33
+ spec.add_development_dependency 'codeclimate-test-reporter'
33
34
  end
@@ -4,10 +4,10 @@ rabbit_jobs:
4
4
  durable_queue:
5
5
  durable: true
6
6
  auto_delete: false
7
- ack: true
7
+ manual_ack: true
8
8
  arguments:
9
9
  x-ha-policy: all
10
10
  fast_queue:
11
11
  durable: false
12
12
  auto_delete: true
13
- ack: false
13
+ manual_ack: false
@@ -1,5 +1,3 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
1
  class TestJob
4
2
  include RJ::Job
5
3
  def perform
@@ -16,7 +14,7 @@ end
16
14
 
17
15
  class JobWithExpire
18
16
  include RJ::Job
19
- expires_in 60*60 # expires in 1 hour
17
+ expires_in 1.hour
20
18
  def perform
21
19
 
22
20
  end
@@ -17,33 +17,54 @@ describe RabbitJobs::Publisher do
17
17
 
18
18
  it 'should publish message to queue' do
19
19
  RJ.publish_to(:rspec_queue, TestJob, 'some', 'other', 'params')
20
- RJ.purge_queue('rspec_queue').should == 1
20
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 1
21
+ RJ.purge_queue('rspec_queue')
22
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 0
21
23
  end
22
24
 
23
25
  it 'should accept symbol as queue name' do
24
26
  RJ.publish_to(:rspec_queue, TestJob)
25
- RJ.purge_queue('rspec_queue').should == 1
27
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 1
28
+ RJ.purge_queue('rspec_queue')
29
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 0
26
30
  end
27
31
 
28
32
  it 'purge_queue should accept many queues' do
29
33
  RJ.publish_to(:rspec_queue, TestJob)
30
34
  RJ.publish_to(:rspec_queue2, TestJob)
31
35
  RJ.publish_to(:rspec_queue3, TestJob)
32
- RJ.purge_queue(:rspec_queue, :rspec_queue2, :rspec_queue3).should == 3
36
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 1
37
+ RJ.queue_status('rspec_queue2')[:message_count].to_i.should == 1
38
+ RJ.queue_status('rspec_queue3')[:message_count].to_i.should == 1
39
+ RJ.purge_queue(:rspec_queue, :rspec_queue2, :rspec_queue3)
40
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 0
41
+ RJ.queue_status('rspec_queue2')[:message_count].to_i.should == 0
42
+ RJ.queue_status('rspec_queue3')[:message_count].to_i.should == 0
33
43
  end
34
44
 
35
45
  it 'should publish job with *params' do
36
46
  RJ.publish_to(:rspec_queue, JobWithArgsArray, 'first value', :some_symbol, 123, 'and string')
37
- RJ.purge_queue(:rspec_queue).should == 1
47
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 1
48
+ RJ.purge_queue(:rspec_queue)
49
+ RJ.queue_status('rspec_queue')[:message_count].to_i.should == 0
38
50
  end
39
51
 
40
52
  it 'should publish 1000 messages in one second' do
41
53
  count = 1000
42
- time = Benchmark.measure {
54
+ time = Benchmark.measure do
43
55
  count.times { RJ.publish_to(:rspec_queue, TestJob) }
44
- removed = RJ.purge_queue(:rspec_queue, :rspec_queue2, :rspec_queue3)
45
- removed.should == count
46
- }
56
+ to_remove = RJ.queue_status('rspec_queue')[:message_count].to_i
57
+ to_remove += RJ.queue_status('rspec_queue2')[:message_count].to_i
58
+ to_remove += RJ.queue_status('rspec_queue3')[:message_count].to_i
59
+ to_remove.should == count
60
+
61
+ RJ.purge_queue(:rspec_queue, :rspec_queue2, :rspec_queue3)
62
+
63
+ remains = RJ.queue_status('rspec_queue')[:message_count].to_i
64
+ remains += RJ.queue_status('rspec_queue2')[:message_count].to_i
65
+ remains += RJ.queue_status('rspec_queue3')[:message_count].to_i
66
+ remains.should == 0
67
+ end
47
68
  puts time
48
69
  end
49
- end
70
+ end
@@ -1,4 +1,3 @@
1
- # -*- encoding : utf-8 -*-
2
1
  require 'spec_helper'
3
2
 
4
3
  describe RabbitJobs::Scheduler do
@@ -6,10 +5,16 @@ describe RabbitJobs::Scheduler do
6
5
  scheduler = RabbitJobs::Scheduler.new
7
6
  scheduler.schedule = YAML.load_file(File.expand_path('../../fixtures/schedule.yml', __FILE__))
8
7
 
9
- scheduler.work(10) # work for 1 second
8
+ # stop scheduler after 3 seconds
9
+ Thread.start do
10
+ sleep 3
11
+ scheduler.shutdown
12
+ end
13
+ scheduler.work
10
14
 
11
15
  RJ.config.queue 'default', RJ::Configuration::DEFAULT_QUEUE_PARAMS
12
- puts "messages queued: " + RJ.purge_queue('default').to_s
13
- RJ.purge_queue('default').should == 0
16
+ puts "messages queued: #{RJ.purge_queue('default')}"
17
+ RJ.queue_status('default')[:message_count].to_i.should == 0
18
+ RJ.purge_queue('default')
14
19
  end
15
- end
20
+ end
@@ -5,7 +5,7 @@ describe RabbitJobs::Worker do
5
5
  it 'should allow to publish jobs from worker' do
6
6
  RabbitJobs.configure do |c|
7
7
  c.server 'amqp://localhost/rj'
8
- c.queue 'rspec_durable_queue', auto_delete: false, durable: true, ack: true
8
+ c.queue 'rspec_durable_queue', auto_delete: false, durable: true, manual_ack: true
9
9
  end
10
10
 
11
11
  RJ::Publisher.purge_queue('rspec_durable_queue')
@@ -13,6 +13,13 @@ describe RabbitJobs::Worker do
13
13
 
14
14
  worker = RabbitJobs::Worker.new
15
15
  # mock(RJ).publish_to(:rspec_durable_queue, JobWithPublish, 5)
16
- worker.work(3) # work for 1 second
16
+
17
+ # stop worker after 3 seconds
18
+ Thread.start do
19
+ sleep 3
20
+ worker.shutdown
21
+ end
22
+
23
+ worker.work
17
24
  end
18
- end
25
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,11 @@
1
- # -*- encoding : utf-8 -*-
2
1
  require 'simplecov'
3
2
  SimpleCov.start do
4
- add_filter "spec" # ignore spec files
3
+ add_filter 'spec' # ignore spec files
4
+ end
5
+
6
+ if ENV['CC']
7
+ require 'codeclimate-test-reporter'
8
+ CodeClimate::TestReporter.start
5
9
  end
6
10
 
7
11
  require 'rr'
@@ -27,4 +31,4 @@ RSpec.configure do |config|
27
31
  # config.formatter = :progress
28
32
  config.formatter = :html
29
33
  end
30
- end
34
+ end
@@ -1,33 +1,45 @@
1
- # -*- encoding : utf-8 -*-
2
1
  require 'spec_helper'
3
2
 
4
3
  describe RabbitJobs::Configuration do
4
+ around(:each) do |example|
5
+ old_config = RJ.instance_variable_get '@configuration'
6
+ RJ.instance_variable_set '@configuration', nil
7
+ example.run
8
+ RJ.instance_variable_set '@configuration', old_config
9
+ end
10
+
5
11
  it 'builds configuration from configure block' do
6
12
  RabbitJobs.configure do |c|
7
13
  c.disable_error_log
8
14
 
9
- c.server "amqp://somehost.lan"
15
+ c.server 'amqp://somehost.lan'
10
16
 
11
- c.queue 'durable_queue', durable: true, auto_delete: false, ack: true, arguments: {'x-ha-policy' => 'all'}
12
- c.queue 'fast_queue', durable: false, auto_delete: true, ack: false
17
+ c.queue 'durable_queue', durable: true, auto_delete: false, manual_ack: true, arguments: { 'x-ha-policy' => 'all' }
18
+ c.queue 'fast_queue', durable: false, auto_delete: true, manual_ack: false
13
19
  end
14
20
 
15
21
  RabbitJobs.config.to_hash.should == {
16
22
  error_log: false,
17
- server: "amqp://somehost.lan",
23
+ server: 'amqp://somehost.lan',
18
24
  queues: {
25
+ jobs: {
26
+ auto_delete: false,
27
+ exclusive: false,
28
+ durable: true,
29
+ manual_ack: true
30
+ },
19
31
  durable_queue: {
20
32
  auto_delete: false,
21
33
  exclusive: false,
22
34
  durable: true,
23
- ack: true,
24
- arguments: {"x-ha-policy"=>"all"}
35
+ manual_ack: true,
36
+ arguments: { 'x-ha-policy' => 'all' }
25
37
  },
26
38
  fast_queue: {
27
39
  auto_delete: true,
28
40
  exclusive: false,
29
41
  durable: false,
30
- ack: false
42
+ manual_ack: false
31
43
  }
32
44
  }
33
45
  }
@@ -37,20 +49,20 @@ describe RabbitJobs::Configuration do
37
49
  RabbitJobs.config.load_file(File.expand_path('../../fixtures/config.yml', __FILE__))
38
50
 
39
51
  RabbitJobs.config.to_hash.should == {
40
- server: "amqp://example.com/vhost",
52
+ server: 'amqp://example.com/vhost',
41
53
  queues: {
42
54
  durable_queue: {
43
55
  durable: true,
44
56
  exclusive: false,
45
57
  auto_delete: false,
46
- ack: true,
47
- arguments: {"x-ha-policy"=>"all"}
58
+ manual_ack: true,
59
+ arguments: { 'x-ha-policy' => 'all' }
48
60
  },
49
61
  fast_queue: {
50
62
  durable: false,
51
63
  exclusive: false,
52
64
  auto_delete: true,
53
- ack: false
65
+ manual_ack: false
54
66
  }
55
67
  }
56
68
  }
@@ -59,14 +71,21 @@ describe RabbitJobs::Configuration do
59
71
  it 'use default value for #server' do
60
72
  RabbitJobs.config.to_hash.should == {
61
73
  error_log: true,
62
- server: "amqp://localhost",
63
- queues: {}
74
+ server: 'amqp://localhost',
75
+ queues: {
76
+ jobs: {
77
+ auto_delete: false,
78
+ exclusive: false,
79
+ durable: true,
80
+ manual_ack: true
81
+ }
82
+ }
64
83
  }
65
84
  end
66
85
 
67
86
  it 'returns settings on some methods' do
68
- RabbitJobs.config.error_log == true
69
- RabbitJobs.config.server.should == 'amqp://localhost'
70
- RabbitJobs.config.routing_keys.should == []
87
+ RabbitJobs.config.error_log.should eq true
88
+ RabbitJobs.config.server.should eq 'amqp://localhost'
89
+ RabbitJobs.config.routing_keys.should eq [:jobs]
71
90
  end
72
- end
91
+ end