shoryuken 5.2.0 → 5.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c855ac4349659f917c53b48687c306ded163e5e0bcab0437eddca57544f4eb0f
4
- data.tar.gz: 2e7494359335eee6f17f663fb43922ff4d5ef1944256a88472efe9a0b7391347
3
+ metadata.gz: 9f4f8cbfdd04c4d39b7f672c549b0d112f64c99a8df4807b83083b57dab8addd
4
+ data.tar.gz: 0cfeaef14f59567382eefacb342be547a43f7dc7a118a3f824a6bdc88710ceea
5
5
  SHA512:
6
- metadata.gz: f6ab1140e26468002b6f1ca41a57296d8168fbf19caf4d5f47ec3e51e89c48b1a961a271d0a416b3f6f1b81b27a7fea775bf5a950fa9658fdcf6b97c095f571e
7
- data.tar.gz: 4ea7336a630cc887e82b7adcbafda5ed373c7fa5b82147b6f7c0038099980c6c86457df6471507f15189ad2391cccd6224a898f91c086e6bdcb9053b858d9114
6
+ metadata.gz: 0ee996f0a835c46c50adaef43f413374505df454e8e696c5a1faaefdd9c28a4ed7922f620b56f800a3aad152881c66dd812bad573fec91f9d2ed9bd168c468f8
7
+ data.tar.gz: 9208b28922188d06f60ade86d0c53d56c6bedbc8577e908d5aa4a819c23cc13889fdea5dcb8875608495f2bb785f3b198bddbdb4fd93f3d6f7fa53d2f9cfec3f
@@ -9,9 +9,14 @@ jobs:
9
9
  name: All Specs
10
10
  strategy:
11
11
  matrix:
12
- ruby: ['2.4.4', '2.5.1', '2.6.3']
13
- gemfile: ['Gemfile', 'Gemfile.aws-sdk-core-v2']
12
+ ruby: ['2.4', '2.5', '2.6', '2.7', '3.0']
13
+ gemfile: ['Gemfile', 'gemfiles/aws_sdk_core_2.gemfile']
14
14
  runs-on: ubuntu-20.04
15
+ services:
16
+ moto_sqs:
17
+ image: quay.io/cjlarose/moto-sqs-server:1.1.0
18
+ ports:
19
+ - 5000:5000
15
20
  env:
16
21
  BUNDLE_GEMFILE: ${{ matrix.gemfile }}
17
22
  steps:
@@ -22,9 +27,9 @@ jobs:
22
27
  ruby-version: ${{ matrix.ruby }}
23
28
  bundler-cache: true
24
29
  - name: Run specs
25
- env:
26
- SPEC_ALL: true
27
30
  run: bundle exec rake spec
31
+ - name: Run integration specs
32
+ run: bundle exec rake spec:integration
28
33
  rails_specs:
29
34
  name: Rails Specs
30
35
  strategy:
@@ -54,4 +59,4 @@ jobs:
54
59
  ruby-version: ${{ matrix.ruby }}
55
60
  bundler-cache: true
56
61
  - name: Run Rails specs
57
- run: bundle exec rake rails_specs
62
+ run: bundle exec rake spec:rails
data/.gitignore CHANGED
@@ -25,4 +25,4 @@ shoryuken.yml
25
25
  *.log
26
26
  .env
27
27
  rubocop.html
28
- .byebug_history
28
+ .byebug_history
data/.rubocop.yml CHANGED
@@ -23,7 +23,7 @@ Metrics/AbcSize:
23
23
  # because codeclimate already give that for us with more details
24
24
  Enabled: false
25
25
 
26
- Metrics/LineLength:
26
+ Layout/LineLength:
27
27
  Max: 125
28
28
 
29
29
  Style/Alias:
data/Appraisals CHANGED
@@ -1,3 +1,11 @@
1
+ appraise 'aws_sdk_core_2' do
2
+ group :test do
3
+ gem 'aws-sdk-core', '~> 2'
4
+ gem 'webrick' # required for Ruby 3
5
+ remove_gem 'aws-sdk-sqs'
6
+ end
7
+ end
8
+
1
9
  appraise 'rails_4_2' do
2
10
  group :test do
3
11
  gem 'activejob', '~> 4.2'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## [v5.3.0] - 2021-10-31
2
+
3
+ - (Refactor) Use Forwardable within Message to avoid method boilerplate
4
+ - [#681](https://github.com/ruby-shoryuken/shoryuken/pull/681)
5
+
6
+ - Add basic health check API
7
+ - [#679](https://github.com/ruby-shoryuken/shoryuken/pull/679)
8
+
9
+ ## [v5.2.3] - 2021-07-29
10
+
11
+ - Fire new `:utilization_update` event any time a worker pool's utilization changes
12
+ - [#673](https://github.com/ruby-shoryuken/shoryuken/pull/673)
13
+
14
+ ## [v5.2.2] - 2021-06-22
15
+
16
+ - When using ActiveJob queue name prefixing, avoid applying prefix to queues configured with a URL or ARN
17
+ - [#667](https://github.com/ruby-shoryuken/shoryuken/pull/667)
18
+
19
+ ## [v5.2.1] - 2021-04-06
20
+
21
+ - Reduce message batch sizes in `shoryuken sqs requeue` and `shoryuken sqs mv` commands
22
+ - [#666](https://github.com/ruby-shoryuken/shoryuken/pull/666)
23
+
24
+ - Fix bug in `shoryuken sqs requeue` and `shoryuken sqs mv` where those commands would exceed the SQS `SendMessageBatch` maximum payload size
25
+ - [#663](https://github.com/ruby-shoryuken/shoryuken/issues/663)
26
+ - [#664](https://github.com/ruby-shoryuken/shoryuken/pull/664)
27
+
28
+ - Remove test stub for `Concurrent.global_io_executor`
29
+ - [#662](https://github.com/ruby-shoryuken/shoryuken/pull/662)
30
+
31
+ - Run integration tests on CI
32
+ - [#660](https://github.com/ruby-shoryuken/shoryuken/pull/660)
33
+
1
34
  ## [v5.2.0] - 2021-02-26
2
35
 
3
36
  - Set `executions` correctly for ActiveJob jobs
data/Gemfile CHANGED
@@ -16,5 +16,5 @@ end
16
16
  group :development do
17
17
  gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
18
18
  gem 'pry-byebug', '3.9.0'
19
- gem 'rubocop'
19
+ gem 'rubocop', '<= 1.12'
20
20
  end
data/README.md CHANGED
@@ -69,7 +69,7 @@ For more information check the [wiki page](https://github.com/phstc/shoryuken/wi
69
69
 
70
70
  ### Testing
71
71
 
72
- To run all specs against the latest dependency vesions, execute
72
+ To run all unit specs against the latest dependency vesions, execute
73
73
 
74
74
  ```sh
75
75
  bundle exec rake spec
@@ -78,5 +78,11 @@ bundle exec rake spec
78
78
  To run all Rails-related specs against all supported versions of Rails, execute
79
79
 
80
80
  ```sh
81
- bundle exec appraisal rake rails_specs
81
+ bundle exec appraisal rake spec:rails
82
+ ```
83
+
84
+ To run integration specs, start a mock SQS server on `localhost:5000`. One such option is [cjlarose/moto-sqs-server](https://github.com/cjlarose/moto-sqs-server). Then execute
85
+
86
+ ```sh
87
+ bundle exec rake spec:integration
82
88
  ```
data/Rakefile CHANGED
@@ -3,10 +3,21 @@ $stdout.sync = true
3
3
 
4
4
  begin
5
5
  require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec)
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.exclude_pattern = 'spec/integration/**/*_spec.rb'
8
+ end
9
+
10
+ namespace :spec do
11
+ desc 'Run Rails specs only'
12
+ RSpec::Core::RakeTask.new(:rails) do |t|
13
+ t.pattern = 'spec/shoryuken/{environment_loader_spec,extensions/active_job_*}.rb'
14
+ end
7
15
 
8
- rails_task = RSpec::Core::RakeTask.new(:rails_specs)
9
- rails_task.pattern = 'spec/shoryuken/{environment_loader_spec,extensions/active_job_*}.rb'
16
+ desc 'Run integration specs only'
17
+ RSpec::Core::RakeTask.new(:integration) do |t|
18
+ t.pattern = 'spec/integration/**/*_spec.rb'
19
+ end
20
+ end
10
21
  rescue LoadError
11
22
  end
12
23
 
data/bin/cli/sqs.rb CHANGED
@@ -4,6 +4,9 @@ require 'date'
4
4
  module Shoryuken
5
5
  module CLI
6
6
  class SQS < Base
7
+ # See https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/quotas-messages.html
8
+ MAX_BATCH_SIZE = 256 * 1024
9
+
7
10
  namespace :sqs
8
11
  class_option :endpoint, aliases: '-e', type: :string, default: ENV['SHORYUKEN_SQS_ENDPOINT'], desc: 'Endpoint URL'
9
12
 
@@ -51,14 +54,56 @@ module Shoryuken
51
54
  end
52
55
  end
53
56
 
54
- def batch_send(url, messages, messages_per_batch = 10)
55
- messages.to_a.flatten.map(&method(:normalize_dump_message)).each_slice(messages_per_batch) do |batch|
56
- sqs.send_message_batch(queue_url: url, entries: batch).failed.any? do |failure|
57
- say "Could not requeue #{failure.id}, code: #{failure.code}", :yellow
57
+ def batch_send(url, messages, max_batch_size = 10)
58
+ messages = messages.to_a.flatten.map(&method(:normalize_dump_message))
59
+ batch_send_normalized_messages url, messages, max_batch_size
60
+ end
61
+
62
+ def batch_send_normalized_messages(url, messages, max_batch_size)
63
+ # Repeatedly take the longest prefix of messages such that
64
+ # 1. The number of messages is less than or equal to max_batch_size
65
+ # 2. The total message payload size is less than or equal to the
66
+ # batch payload limit
67
+ while messages.size.positive?
68
+ batch_size = max_batch_size
69
+ loop do
70
+ batch = messages.take batch_size
71
+
72
+ unless batch.size == 1 || batch_payload_size(batch) <= MAX_BATCH_SIZE
73
+ batch_size = batch.size - 1
74
+ next
75
+ end
76
+
77
+ sqs.send_message_batch(queue_url: url, entries: batch).failed.any? do |failure|
78
+ say "Could not requeue #{failure.id}, code: #{failure.code}", :yellow
79
+ end
80
+ messages = messages.drop batch.size
81
+ break
58
82
  end
59
83
  end
60
84
  end
61
85
 
86
+ def batch_payload_size(messages)
87
+ messages.sum(&method(:message_size))
88
+ end
89
+
90
+ def message_size(message)
91
+ attribute_size = (message[:message_attributes] || []).sum do |name, value|
92
+ name_size = name.to_s.bytesize
93
+ data_type_size = value[:data_type].bytesize
94
+ value_size = if value[:string_value]
95
+ value[:string_value].bytesize
96
+ elsif value[:binary_value]
97
+ value[:binary_value].bytesize
98
+ end
99
+ name_size + data_type_size + value_size
100
+ end
101
+
102
+ body_size = message[:message_body].bytesize
103
+
104
+ attribute_size + body_size
105
+ end
106
+
62
107
  def find_all(url, limit)
63
108
  count = 0
64
109
  batch_size = limit > 10 ? 10 : limit
@@ -160,7 +205,7 @@ module Shoryuken
160
205
  end
161
206
 
162
207
  desc 'requeue QUEUE-NAME PATH', 'Requeues messages from a dump file'
163
- method_option :batch_size, aliases: '-n', type: :numeric, default: 10, desc: 'number of messages per batch to send'
208
+ method_option :batch_size, aliases: '-n', type: :numeric, default: 10, desc: 'maximum number of messages per batch to send'
164
209
  def requeue(queue_name, path)
165
210
  fail_task "Path #{path} not found" unless File.exist?(path)
166
211
 
@@ -0,0 +1,21 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ group :test do
6
+ gem "activejob"
7
+ gem "aws-sdk-core", "~> 2"
8
+ gem "codeclimate-test-reporter", require: nil
9
+ gem "httparty"
10
+ gem "multi_xml"
11
+ gem "simplecov"
12
+ gem "webrick"
13
+ end
14
+
15
+ group :development do
16
+ gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
17
+ gem "pry-byebug", "3.9.0"
18
+ gem "rubocop"
19
+ end
20
+
21
+ gemspec path: "../"
@@ -80,6 +80,8 @@ module Shoryuken
80
80
  end
81
81
 
82
82
  def prefix_active_job_queue_name(queue_name, weight)
83
+ return [queue_name, weight] if queue_name.start_with?('https://', 'arn:')
84
+
83
85
  queue_name_prefix = ::ActiveJob::Base.queue_name_prefix
84
86
  queue_name_delimiter = ::ActiveJob::Base.queue_name_delimiter
85
87
 
@@ -32,6 +32,13 @@ module Shoryuken
32
32
  executor.wait_for_termination
33
33
  end
34
34
 
35
+ def healthy?
36
+ Shoryuken.groups.keys.all? do |group|
37
+ manager = @managers.find { |m| m.group == group }
38
+ manager && manager.running?
39
+ end
40
+ end
41
+
35
42
  private
36
43
 
37
44
  def executor
@@ -71,6 +78,7 @@ module Shoryuken
71
78
  def create_managers
72
79
  Shoryuken.groups.map do |group, options|
73
80
  Shoryuken::Manager.new(
81
+ group,
74
82
  Shoryuken::Fetcher.new(group),
75
83
  Shoryuken.polling_strategy(group).new(options[:queues], Shoryuken.delay(group)),
76
84
  options[:concurrency],
@@ -6,7 +6,10 @@ module Shoryuken
6
6
  # See https://github.com/phstc/shoryuken/issues/348#issuecomment-292847028
7
7
  MIN_DISPATCH_INTERVAL = 0.1
8
8
 
9
- def initialize(fetcher, polling_strategy, concurrency, executor)
9
+ attr_reader :group
10
+
11
+ def initialize(group, fetcher, polling_strategy, concurrency, executor)
12
+ @group = group
10
13
  @fetcher = fetcher
11
14
  @polling_strategy = polling_strategy
12
15
  @max_processors = concurrency
@@ -16,15 +19,16 @@ module Shoryuken
16
19
  end
17
20
 
18
21
  def start
22
+ fire_utilization_update_event
19
23
  dispatch_loop
20
24
  end
21
25
 
22
- private
23
-
24
26
  def running?
25
27
  @running.true? && @executor.running?
26
28
  end
27
29
 
30
+ private
31
+
28
32
  def dispatch_loop
29
33
  return unless running?
30
34
 
@@ -59,6 +63,8 @@ module Shoryuken
59
63
 
60
64
  def processor_done(queue)
61
65
  @busy_processors.decrement
66
+ fire_utilization_update_event
67
+
62
68
  client_queue = Shoryuken::Client.queues(queue)
63
69
  return unless client_queue.fifo?
64
70
  return unless @polling_strategy.respond_to?(:message_processed)
@@ -72,6 +78,7 @@ module Shoryuken
72
78
  logger.debug { "Assigning #{sqs_msg.message_id}" }
73
79
 
74
80
  @busy_processors.increment
81
+ fire_utilization_update_event
75
82
 
76
83
  Concurrent::Promise
77
84
  .execute(executor: @executor) { Processor.process(queue_name, sqs_msg) }
@@ -114,5 +121,13 @@ module Shoryuken
114
121
 
115
122
  @running.make_false
116
123
  end
124
+
125
+ def fire_utilization_update_event
126
+ fire_event :utilization_update, false, {
127
+ group: @group,
128
+ max_processors: @max_processors,
129
+ busy_processors: busy
130
+ }
131
+ end
117
132
  end
118
133
  end
@@ -1,5 +1,16 @@
1
1
  module Shoryuken
2
2
  class Message
3
+ extend Forwardable
4
+
5
+ def_delegators(:data,
6
+ :message_id,
7
+ :receipt_handle,
8
+ :md5_of_body,
9
+ :body,
10
+ :attributes,
11
+ :md5_of_message_attributes,
12
+ :message_attributes)
13
+
3
14
  attr_accessor :client, :queue_url, :queue_name, :data
4
15
 
5
16
  def initialize(client, queue, data)
@@ -29,33 +40,5 @@ module Shoryuken
29
40
  visibility_timeout: timeout
30
41
  )
31
42
  end
32
-
33
- def message_id
34
- data.message_id
35
- end
36
-
37
- def receipt_handle
38
- data.receipt_handle
39
- end
40
-
41
- def md5_of_body
42
- data.md5_of_body
43
- end
44
-
45
- def body
46
- data.body
47
- end
48
-
49
- def attributes
50
- data.attributes
51
- end
52
-
53
- def md5_of_message_attributes
54
- data.md5_of_message_attributes
55
- end
56
-
57
- def message_attributes
58
- data.message_attributes
59
- end
60
43
  end
61
44
  end
@@ -9,6 +9,7 @@ module Shoryuken
9
9
  lifecycle_events: {
10
10
  startup: [],
11
11
  dispatch: [],
12
+ utilization_update: [],
12
13
  quiet: [],
13
14
  shutdown: []
14
15
  }
@@ -55,6 +55,10 @@ module Shoryuken
55
55
  end
56
56
  end
57
57
 
58
+ def healthy?
59
+ (@launcher && @launcher.healthy?) || false
60
+ end
61
+
58
62
  private
59
63
 
60
64
  def initialize_concurrent_logger
@@ -1,3 +1,3 @@
1
1
  module Shoryuken
2
- VERSION = '5.2.0'.freeze
2
+ VERSION = '5.3.0'.freeze
3
3
  end
data/lib/shoryuken.rb CHANGED
@@ -45,6 +45,10 @@ module Shoryuken
45
45
  @_shoryuken_options ||= Shoryuken::Options.new
46
46
  end
47
47
 
48
+ def self.healthy?
49
+ Shoryuken::Runner.instance.healthy?
50
+ end
51
+
48
52
  def_delegators(
49
53
  :shoryuken_options,
50
54
  :active_job?,
@@ -4,10 +4,37 @@ require 'shoryuken/launcher'
4
4
  require 'securerandom'
5
5
 
6
6
  RSpec.describe Shoryuken::Launcher do
7
- describe 'Consuming messages', slow: true do
7
+ let(:sqs_client) do
8
+ Aws::SQS::Client.new(
9
+ region: 'us-east-1',
10
+ endpoint: 'http://localhost:5000',
11
+ access_key_id: 'fake',
12
+ secret_access_key: 'fake'
13
+ )
14
+ end
15
+
16
+ let(:executor) do
17
+ # We can't use Concurrent.global_io_executor in these tests since once you
18
+ # shut down a thread pool, you can't start it back up. Instead, we create
19
+ # one new thread pool executor for each spec. We use a new
20
+ # CachedThreadPool, since that most closely resembles
21
+ # Concurrent.global_io_executor
22
+ Concurrent::CachedThreadPool.new auto_terminate: true
23
+ end
24
+
25
+ describe 'Consuming messages' do
8
26
  before do
9
27
  Aws.config[:stub_responses] = false
10
- Aws.config[:region] = 'us-east-1'
28
+
29
+ allow(Shoryuken).to receive(:launcher_executor).and_return(executor)
30
+
31
+ Shoryuken.configure_client do |config|
32
+ config.sqs_client = sqs_client
33
+ end
34
+
35
+ Shoryuken.configure_server do |config|
36
+ config.sqs_client = sqs_client
37
+ end
11
38
 
12
39
  StandardWorker.received_messages = 0
13
40
 
@@ -57,11 +57,11 @@ RSpec.describe Shoryuken::EnvironmentLoader do
57
57
  ActiveJob::Base.queue_name_delimiter = '_'
58
58
 
59
59
  allow(Shoryuken).to receive(:active_job?).and_return(true)
60
- end
61
60
 
62
- specify do
63
61
  Shoryuken.active_job_queue_name_prefixing = true
62
+ end
64
63
 
64
+ specify do
65
65
  Shoryuken.options[:queues] = ['queue1', ['queue2', 2]]
66
66
 
67
67
  Shoryuken.options[:groups] = {
@@ -73,6 +73,26 @@ RSpec.describe Shoryuken::EnvironmentLoader do
73
73
  expect(Shoryuken.groups['default'][:queues]).to eq(%w[test_queue1 test_queue2 test_queue2])
74
74
  expect(Shoryuken.groups['group1'][:queues]).to eq(%w[test_group1_queue1 test_group1_queue2])
75
75
  end
76
+
77
+ it 'does not prefix url-based queues' do
78
+ Shoryuken.options[:queues] = ['https://example.com/test_queue1']
79
+ Shoryuken.options[:groups] = {'group1' => {queues: ['https://example.com/test_group1_queue1']}}
80
+
81
+ subject.load
82
+
83
+ expect(Shoryuken.groups['default'][:queues]).to(eq(['https://example.com/test_queue1']))
84
+ expect(Shoryuken.groups['group1'][:queues]).to(eq(['https://example.com/test_group1_queue1']))
85
+ end
86
+
87
+ it 'does not prefix arn-based queues' do
88
+ Shoryuken.options[:queues] = ['arn:aws:sqs:fake-region-1:1234:test_queue1']
89
+ Shoryuken.options[:groups] = {'group1' => {queues: ['arn:aws:sqs:fake-region-1:1234:test_group1_queue1']}}
90
+
91
+ subject.load
92
+
93
+ expect(Shoryuken.groups['default'][:queues]).to(eq(['arn:aws:sqs:fake-region-1:1234:test_queue1']))
94
+ expect(Shoryuken.groups['group1'][:queues]).to(eq(['arn:aws:sqs:fake-region-1:1234:test_group1_queue1']))
95
+ end
76
96
  end
77
97
  describe "#setup_options" do
78
98
  let (:cli_queues) { { "queue1"=> 10, "queue2" => 20 } }
@@ -10,6 +10,10 @@ RSpec.describe ActiveJob::QueueAdapters::ShoryukenConcurrentSendAdapter do
10
10
  let(:error_handler) { -> {} }
11
11
  let(:success_handler) { -> {} }
12
12
 
13
+ before do
14
+ allow(Concurrent).to receive(:global_io_executor).and_return(Concurrent::ImmediateExecutor.new)
15
+ end
16
+
13
17
  subject { described_class.new(success_handler, error_handler) }
14
18
 
15
19
  context 'when success' do
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+ require 'shoryuken/launcher'
3
+
4
+ RSpec.describe Shoryuken::Launcher do
5
+ let(:executor) do
6
+ # We can't use Concurrent.global_io_executor in these tests since once you
7
+ # shut down a thread pool, you can't start it back up. Instead, we create
8
+ # one new thread pool executor for each spec. We use a new
9
+ # CachedThreadPool, since that most closely resembles
10
+ # Concurrent.global_io_executor
11
+ Concurrent::CachedThreadPool.new auto_terminate: true
12
+ end
13
+
14
+ let(:first_group_manager) { double(:first_group_manager, group: 'first_group') }
15
+ let(:second_group_manager) { double(:second_group_manager, group: 'second_group') }
16
+ let(:first_queue) { "launcher_spec_#{SecureRandom.uuid}" }
17
+ let(:second_queue) { "launcher_spec_#{SecureRandom.uuid}" }
18
+
19
+ before do
20
+ Shoryuken.add_group('first_group', 1)
21
+ Shoryuken.add_group('second_group', 1)
22
+ Shoryuken.add_queue(first_queue, 1, 'first_group')
23
+ Shoryuken.add_queue(second_queue, 1, 'second_group')
24
+ allow(Shoryuken).to receive(:launcher_executor).and_return(executor)
25
+ allow(Shoryuken::Manager).to receive(:new).with('first_group', any_args).and_return(first_group_manager)
26
+ allow(Shoryuken::Manager).to receive(:new).with('second_group', any_args).and_return(second_group_manager)
27
+ allow(first_group_manager).to receive(:running?).and_return(true)
28
+ allow(second_group_manager).to receive(:running?).and_return(true)
29
+ end
30
+
31
+ describe '#healthy?' do
32
+ context 'when all groups have managers' do
33
+ context 'when all managers are running' do
34
+ it 'returns true' do
35
+ expect(subject.healthy?).to be true
36
+ end
37
+ end
38
+
39
+ context 'when one manager is not running' do
40
+ before do
41
+ allow(second_group_manager).to receive(:running?).and_return(false)
42
+ end
43
+
44
+ it 'returns false' do
45
+ expect(subject.healthy?).to be false
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'when all groups do not have managers' do
51
+ before do
52
+ allow(second_group_manager).to receive(:group).and_return('some_random_group')
53
+ end
54
+
55
+ it 'returns false' do
56
+ expect(subject.healthy?).to be false
57
+ end
58
+ end
59
+ end
60
+ end
@@ -15,7 +15,7 @@ RSpec.describe Shoryuken::Manager do
15
15
  let(:concurrency) { 1 }
16
16
  let(:executor) { Concurrent::ImmediateExecutor.new }
17
17
 
18
- subject { Shoryuken::Manager.new(fetcher, polling_strategy, concurrency, executor) }
18
+ subject { Shoryuken::Manager.new('default', fetcher, polling_strategy, concurrency, executor) }
19
19
 
20
20
  before do
21
21
  allow(fetcher).to receive(:fetch).and_return([])
@@ -71,6 +71,11 @@ RSpec.describe Shoryuken::Manager do
71
71
 
72
72
  expect(fetcher).to receive(:fetch).with(q, concurrency).and_return(messages)
73
73
  expect(subject).to receive(:fire_event).with(:dispatch, false, queue_name: q.name)
74
+ expect(subject).to receive(:fire_event).with(:utilization_update,
75
+ false,
76
+ group: 'default',
77
+ busy_processors: 1,
78
+ max_processors: 1)
74
79
  expect(Shoryuken::Processor).to receive(:process).with(q, message)
75
80
  expect(Shoryuken.logger).to receive(:info).never
76
81
 
@@ -99,6 +104,11 @@ RSpec.describe Shoryuken::Manager do
99
104
  q = Shoryuken::Polling::QueueConfiguration.new(queue, {})
100
105
 
101
106
  expect(fetcher).to receive(:fetch).with(q, described_class::BATCH_LIMIT).and_return(messages)
107
+ expect(subject).to receive(:fire_event).with(:utilization_update,
108
+ false,
109
+ group: 'default',
110
+ busy_processors: 1,
111
+ max_processors: 1)
102
112
  expect(subject).to receive(:fire_event).with(:dispatch, false, queue_name: q.name)
103
113
  allow(subject).to receive(:batched_queue?).with(q).and_return(true)
104
114
  expect(Shoryuken::Processor).to receive(:process).with(q, messages)
@@ -163,4 +173,26 @@ RSpec.describe Shoryuken::Manager do
163
173
  end
164
174
  end
165
175
  end
176
+
177
+ describe '#running?' do
178
+ context 'when the executor is running' do
179
+ before do
180
+ allow(executor).to receive(:running?).and_return(true)
181
+ end
182
+
183
+ it 'returns true' do
184
+ expect(subject.running?).to be true
185
+ end
186
+ end
187
+
188
+ context 'when the executor is not running' do
189
+ before do
190
+ allow(executor).to receive(:running?).and_return(false)
191
+ end
192
+
193
+ it 'returns false' do
194
+ expect(subject.running?).to be false
195
+ end
196
+ end
197
+ end
166
198
  end
@@ -1,4 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Shoryuken do
4
+ describe '.healthy?' do
5
+ before do
6
+ allow(Shoryuken::Runner).to receive(:instance).and_return(double(:instance, healthy?: :some_result))
7
+ end
8
+
9
+ it 'delegates to the runner instance' do
10
+ expect(described_class.healthy?).to eq(:some_result)
11
+ end
12
+ end
4
13
  end
data/spec/spec_helper.rb CHANGED
@@ -32,9 +32,6 @@ class TestWorker
32
32
  end
33
33
 
34
34
  RSpec.configure do |config|
35
- # TODO: Run these tests again on CI
36
- config.filter_run_excluding slow: true
37
-
38
35
  config.before do
39
36
  Shoryuken::Client.class_variable_set :@@queues, {}
40
37
 
@@ -63,7 +60,6 @@ RSpec.configure do |config|
63
60
 
64
61
  Shoryuken.cache_visibility_timeout = false
65
62
 
66
- allow(Concurrent).to receive(:global_io_executor).and_return(Concurrent::ImmediateExecutor.new)
67
63
  allow(Shoryuken).to receive(:active_job?).and_return(false)
68
64
  end
69
65
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoryuken
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Cantero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-26 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -112,7 +112,6 @@ files:
112
112
  - Appraisals
113
113
  - CHANGELOG.md
114
114
  - Gemfile
115
- - Gemfile.aws-sdk-core-v2
116
115
  - LICENSE
117
116
  - README.md
118
117
  - Rakefile
@@ -122,6 +121,7 @@ files:
122
121
  - examples/bootstrap_queues.rb
123
122
  - examples/default_worker.rb
124
123
  - gemfiles/.gitignore
124
+ - gemfiles/aws_sdk_core_2.gemfile
125
125
  - gemfiles/rails_4_2.gemfile
126
126
  - gemfiles/rails_5_2.gemfile
127
127
  - gemfiles/rails_6_0.gemfile
@@ -174,6 +174,7 @@ files:
174
174
  - spec/shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb
175
175
  - spec/shoryuken/extensions/active_job_wrapper_spec.rb
176
176
  - spec/shoryuken/fetcher_spec.rb
177
+ - spec/shoryuken/launcher_spec.rb
177
178
  - spec/shoryuken/manager_spec.rb
178
179
  - spec/shoryuken/middleware/chain_spec.rb
179
180
  - spec/shoryuken/middleware/server/auto_delete_spec.rb
@@ -231,6 +232,7 @@ test_files:
231
232
  - spec/shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb
232
233
  - spec/shoryuken/extensions/active_job_wrapper_spec.rb
233
234
  - spec/shoryuken/fetcher_spec.rb
235
+ - spec/shoryuken/launcher_spec.rb
234
236
  - spec/shoryuken/manager_spec.rb
235
237
  - spec/shoryuken/middleware/chain_spec.rb
236
238
  - spec/shoryuken/middleware/server/auto_delete_spec.rb
@@ -1,13 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in shoryuken.gemspec
4
- gemspec
5
-
6
- group :test do
7
- gem 'activejob', '~> 4'
8
- gem 'aws-sdk-core', '~> 2'
9
- gem 'codeclimate-test-reporter', require: nil
10
- gem 'httparty'
11
- gem 'multi_xml'
12
- gem 'simplecov'
13
- end