shoryuken 7.0.0.alpha1 → 7.0.0.alpha2

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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/push.yml +3 -3
  3. data/.github/workflows/specs.yml +6 -9
  4. data/.github/workflows/verify-action-pins.yml +1 -1
  5. data/.rspec +2 -1
  6. data/.ruby-version +1 -1
  7. data/Appraisals +0 -6
  8. data/CHANGELOG.md +186 -142
  9. data/Gemfile +1 -0
  10. data/README.md +12 -13
  11. data/bin/cli/base.rb +1 -2
  12. data/bin/cli/sqs.rb +5 -4
  13. data/bin/shoryuken +2 -1
  14. data/gemfiles/rails_7_0.gemfile +10 -10
  15. data/gemfiles/rails_7_1.gemfile +10 -9
  16. data/gemfiles/rails_7_2.gemfile +10 -9
  17. data/gemfiles/rails_8_0.gemfile +10 -9
  18. data/lib/shoryuken/body_parser.rb +3 -1
  19. data/lib/shoryuken/client.rb +2 -0
  20. data/lib/shoryuken/default_exception_handler.rb +2 -0
  21. data/lib/shoryuken/default_worker_registry.rb +11 -11
  22. data/lib/shoryuken/environment_loader.rb +6 -6
  23. data/lib/shoryuken/extensions/active_job_adapter.rb +8 -6
  24. data/lib/shoryuken/extensions/active_job_concurrent_send_adapter.rb +5 -5
  25. data/lib/shoryuken/extensions/active_job_extensions.rb +2 -0
  26. data/lib/shoryuken/fetcher.rb +4 -2
  27. data/lib/shoryuken/helpers/atomic_boolean.rb +44 -0
  28. data/lib/shoryuken/helpers/atomic_counter.rb +104 -0
  29. data/lib/shoryuken/helpers/atomic_hash.rb +182 -0
  30. data/lib/shoryuken/helpers/hash_utils.rb +56 -0
  31. data/lib/shoryuken/helpers/string_utils.rb +65 -0
  32. data/lib/shoryuken/inline_message.rb +22 -0
  33. data/lib/shoryuken/launcher.rb +2 -0
  34. data/lib/shoryuken/logging.rb +19 -5
  35. data/lib/shoryuken/manager.rb +6 -4
  36. data/lib/shoryuken/message.rb +2 -0
  37. data/lib/shoryuken/middleware/chain.rb +2 -0
  38. data/lib/shoryuken/middleware/server/active_record.rb +2 -0
  39. data/lib/shoryuken/middleware/server/auto_delete.rb +2 -0
  40. data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +10 -10
  41. data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +5 -3
  42. data/lib/shoryuken/middleware/server/timing.rb +2 -0
  43. data/lib/shoryuken/options.rb +9 -5
  44. data/lib/shoryuken/polling/base_strategy.rb +126 -0
  45. data/lib/shoryuken/polling/queue_configuration.rb +103 -0
  46. data/lib/shoryuken/polling/strict_priority.rb +2 -0
  47. data/lib/shoryuken/polling/weighted_round_robin.rb +2 -0
  48. data/lib/shoryuken/processor.rb +5 -2
  49. data/lib/shoryuken/queue.rb +6 -4
  50. data/lib/shoryuken/runner.rb +9 -12
  51. data/lib/shoryuken/util.rb +6 -6
  52. data/lib/shoryuken/version.rb +3 -1
  53. data/lib/shoryuken/worker/default_executor.rb +2 -0
  54. data/lib/shoryuken/worker/inline_executor.rb +3 -1
  55. data/lib/shoryuken/worker.rb +2 -0
  56. data/lib/shoryuken/worker_registry.rb +2 -0
  57. data/lib/shoryuken.rb +8 -28
  58. data/shoryuken.gemspec +6 -6
  59. data/spec/integration/launcher_spec.rb +2 -3
  60. data/spec/shared_examples_for_active_job.rb +13 -8
  61. data/spec/shoryuken/body_parser_spec.rb +1 -2
  62. data/spec/shoryuken/client_spec.rb +1 -1
  63. data/spec/shoryuken/default_exception_handler_spec.rb +9 -10
  64. data/spec/shoryuken/default_worker_registry_spec.rb +1 -2
  65. data/spec/shoryuken/environment_loader_spec.rb +9 -8
  66. data/spec/shoryuken/extensions/active_job_adapter_spec.rb +2 -1
  67. data/spec/shoryuken/extensions/active_job_base_spec.rb +2 -1
  68. data/spec/shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb +2 -1
  69. data/spec/shoryuken/extensions/active_job_wrapper_spec.rb +2 -1
  70. data/spec/shoryuken/fetcher_spec.rb +23 -26
  71. data/spec/shoryuken/helpers/atomic_boolean_spec.rb +196 -0
  72. data/spec/shoryuken/helpers/atomic_counter_spec.rb +177 -0
  73. data/spec/shoryuken/helpers/atomic_hash_spec.rb +307 -0
  74. data/spec/shoryuken/helpers/hash_utils_spec.rb +145 -0
  75. data/spec/shoryuken/helpers/string_utils_spec.rb +124 -0
  76. data/spec/shoryuken/helpers_integration_spec.rb +96 -0
  77. data/spec/shoryuken/inline_message_spec.rb +196 -0
  78. data/spec/shoryuken/launcher_spec.rb +1 -2
  79. data/spec/shoryuken/manager_spec.rb +1 -2
  80. data/spec/shoryuken/middleware/chain_spec.rb +1 -1
  81. data/spec/shoryuken/middleware/server/auto_delete_spec.rb +1 -1
  82. data/spec/shoryuken/middleware/server/auto_extend_visibility_spec.rb +1 -1
  83. data/spec/shoryuken/middleware/server/exponential_backoff_retry_spec.rb +1 -1
  84. data/spec/shoryuken/middleware/server/timing_spec.rb +1 -1
  85. data/spec/shoryuken/options_spec.rb +4 -4
  86. data/spec/shoryuken/polling/base_strategy_spec.rb +280 -0
  87. data/spec/shoryuken/polling/queue_configuration_spec.rb +195 -0
  88. data/spec/shoryuken/polling/strict_priority_spec.rb +1 -1
  89. data/spec/shoryuken/polling/weighted_round_robin_spec.rb +1 -1
  90. data/spec/shoryuken/processor_spec.rb +1 -1
  91. data/spec/shoryuken/queue_spec.rb +2 -3
  92. data/spec/shoryuken/runner_spec.rb +1 -3
  93. data/spec/shoryuken/util_spec.rb +1 -1
  94. data/spec/shoryuken/worker/default_executor_spec.rb +1 -1
  95. data/spec/shoryuken/worker/inline_executor_spec.rb +1 -1
  96. data/spec/shoryuken/worker_spec.rb +15 -11
  97. data/spec/shoryuken_spec.rb +1 -1
  98. data/spec/spec_helper.rb +16 -0
  99. metadata +60 -27
  100. data/.github/FUNDING.yml +0 -12
  101. data/gemfiles/rails_6_1.gemfile +0 -18
  102. data/lib/shoryuken/core_ext.rb +0 -69
  103. data/lib/shoryuken/polling/base.rb +0 -67
  104. data/shoryuken.jpg +0 -0
  105. data/spec/shoryuken/core_ext_spec.rb +0 -40
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ group :test do
8
8
  gem 'httparty'
9
9
  gem 'multi_xml'
10
10
  gem 'simplecov'
11
+ gem 'warning'
11
12
  end
12
13
 
13
14
  group :development do
data/README.md CHANGED
@@ -1,21 +1,20 @@
1
1
  # Shoryuken
2
2
 
3
- ![Shoryuken](shoryuken.jpg)
4
-
5
3
  Shoryuken _sho-ryu-ken_ is a super-efficient [Amazon SQS](https://aws.amazon.com/sqs/) thread-based message processor.
6
4
 
7
5
  [![Build Status](https://github.com/ruby-shoryuken/shoryuken/workflows/Specs/badge.svg)](https://github.com/ruby-shoryuken/shoryuken/actions)
6
+ [![Join the chat at https://slack.shoryuken.io](https://raw.githubusercontent.com/karafka/misc/master/slack.svg)](https://slack.shoryuken.io)
8
7
 
9
8
  ## Key features
10
9
 
11
- - [Rails Active Job](https://github.com/phstc/shoryuken/wiki/Rails-Integration-Active-Job)
12
- - [Queue Load balancing](https://github.com/phstc/shoryuken/wiki/Shoryuken-options#load-balancing)
13
- - [Concurrency per queue](https://github.com/phstc/shoryuken/wiki/Processing-Groups)
14
- - [Long Polling](https://github.com/phstc/shoryuken/wiki/Long-Polling)
15
- - [Batch processing](https://github.com/phstc/shoryuken/wiki/Worker-options#batch)
16
- - [Auto extend visibility timeout](https://github.com/phstc/shoryuken/wiki/Worker-options#auto_visibility_timeout)
17
- - [Exponential backoff](https://github.com/phstc/shoryuken/wiki/Worker-options#retry_intervals)
18
- - [Middleware support](https://github.com/phstc/shoryuken/wiki/Middleware)
10
+ - [Rails Active Job](https://github.com/ruby-shoryuken/shoryuken/wiki/Rails-Integration-Active-Job)
11
+ - [Queue Load balancing](https://github.com/ruby-shoryuken/shoryuken/wiki/Shoryuken-options#load-balancing)
12
+ - [Concurrency per queue](https://github.com/ruby-shoryuken/shoryuken/wiki/Processing-Groups)
13
+ - [Long Polling](https://github.com/ruby-shoryuken/shoryuken/wiki/Long-Polling)
14
+ - [Batch processing](https://github.com/ruby-shoryuken/shoryuken/wiki/Worker-options#batch)
15
+ - [Auto extend visibility timeout](https://github.com/ruby-shoryuken/shoryuken/wiki/Worker-options#auto_visibility_timeout)
16
+ - [Exponential backoff](https://github.com/ruby-shoryuken/shoryuken/wiki/Worker-options#retry_intervals)
17
+ - [Middleware support](https://github.com/ruby-shoryuken/shoryuken/wiki/Middleware)
19
18
  - Amazon SQS CLI. See `shoryuken help sqs`
20
19
 
21
20
  ## Requirements
@@ -38,11 +37,11 @@ $ bundle
38
37
 
39
38
  ## Usage
40
39
 
41
- Check the [Getting Started](https://github.com/phstc/shoryuken/wiki/Getting-Started) page.
40
+ Check the [Getting Started](https://github.com/ruby-shoryuken/shoryuken/wiki/Getting-Started) page.
42
41
 
43
42
  ## More Information
44
43
 
45
- For more information check the [wiki page](https://github.com/phstc/shoryuken/wiki).
44
+ For more information check the [wiki page](https://github.com/ruby-shoryuken/shoryuken/wiki).
46
45
 
47
46
  ## Credits
48
47
 
@@ -50,7 +49,7 @@ For more information check the [wiki page](https://github.com/phstc/shoryuken/wi
50
49
 
51
50
  ## Contributing
52
51
 
53
- 1. Fork it ( https://github.com/phstc/shoryuken/fork )
52
+ 1. Fork it ( https://github.com/ruby-shoryuken/shoryuken/fork )
54
53
  2. Create your feature branch (`git checkout -b my-new-feature`)
55
54
  3. Commit your changes (`git commit -am 'Add some feature'`)
56
55
  4. Push to the branch (`git push origin my-new-feature`)
data/bin/cli/base.rb CHANGED
@@ -25,8 +25,7 @@ module Shoryuken
25
25
 
26
26
  def print_format_column(column, size)
27
27
  size_with_padding = size + 4
28
- column = column.to_s.ljust(size_with_padding)
29
- column
28
+ column.to_s.ljust(size_with_padding)
30
29
  end
31
30
 
32
31
  def fail_task(msg, quit = true)
data/bin/cli/sqs.rb CHANGED
@@ -5,7 +5,7 @@ module Shoryuken
5
5
  module CLI
6
6
  class SQS < Base
7
7
  # See https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/quotas-messages.html
8
- MAX_BATCH_SIZE = 256 * 1024
8
+ MAX_BATCH_SIZE = 1024 * 1024
9
9
 
10
10
  namespace :sqs
11
11
  class_option :endpoint, aliases: '-e', type: :string, default: ENV['SHORYUKEN_SQS_ENDPOINT'], desc: 'Endpoint URL'
@@ -111,7 +111,7 @@ module Shoryuken
111
111
  attribute_size + body_size
112
112
  end
113
113
 
114
- def find_all(url, limit)
114
+ def find_all(url, limit, &block)
115
115
  count = 0
116
116
  batch_size = limit > 10 ? 10 : limit
117
117
 
@@ -126,7 +126,7 @@ module Shoryuken
126
126
  message_attribute_names: ['All']
127
127
  ).messages || []
128
128
 
129
- messages.each { |m| yield m }
129
+ messages.each(&block)
130
130
 
131
131
  count += messages.size
132
132
 
@@ -212,7 +212,8 @@ module Shoryuken
212
212
  end
213
213
 
214
214
  desc 'requeue QUEUE-NAME PATH', 'Requeues messages from a dump file'
215
- method_option :batch_size, aliases: '-n', type: :numeric, default: 10, desc: 'maximum number of messages per batch to send'
215
+ method_option :batch_size, aliases: '-n', type: :numeric, default: 10,
216
+ desc: 'maximum number of messages per batch to send'
216
217
  def requeue(queue_name, path)
217
218
  fail_task "Path #{path} not found" unless File.exist?(path)
218
219
 
data/bin/shoryuken CHANGED
@@ -26,7 +26,8 @@ module Shoryuken
26
26
  method_option :logfile, aliases: '-L', type: :string, desc: 'Path to logfile'
27
27
  method_option :pidfile, aliases: '-P', type: :string, desc: 'Path to pidfile'
28
28
  method_option :verbose, aliases: '-v', type: :boolean, desc: 'Print more verbose output'
29
- method_option :delay, aliases: '-D', type: :numeric, desc: 'Number of seconds to pause fetching from an empty queue'
29
+ method_option :delay, aliases: '-D', type: :numeric,
30
+ desc: 'Number of seconds to pause fetching from an empty queue'
30
31
  def start
31
32
  opts = options.to_h.symbolize_keys
32
33
 
@@ -1,19 +1,19 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  group :test do
6
- gem "activejob", "~> 7.0"
7
- gem "httparty"
8
- gem "multi_xml"
9
- gem "simplecov"
6
+ gem 'activejob', '~> 7.0'
7
+ gem 'httparty'
8
+ gem 'multi_xml'
9
+ gem 'simplecov'
10
+ gem 'warning'
10
11
  end
11
12
 
12
13
  group :development do
13
- gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
14
- gem "rubocop"
15
- gem "pry", ">= 0.14.2"
16
- gem "pry-byebug", ">= 3.10.1"
14
+ gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
15
+ gem 'pry-byebug'
16
+ gem 'rubocop'
17
17
  end
18
18
 
19
- gemspec path: "../"
19
+ gemspec path: '../'
@@ -1,18 +1,19 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  group :test do
6
- gem "activejob", "~> 7.1"
7
- gem "httparty"
8
- gem "multi_xml"
9
- gem "simplecov"
6
+ gem 'activejob', '~> 7.1'
7
+ gem 'httparty'
8
+ gem 'multi_xml'
9
+ gem 'simplecov'
10
+ gem 'warning'
10
11
  end
11
12
 
12
13
  group :development do
13
- gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
14
- gem "pry-byebug"
15
- gem "rubocop"
14
+ gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
15
+ gem 'pry-byebug'
16
+ gem 'rubocop'
16
17
  end
17
18
 
18
- gemspec path: "../"
19
+ gemspec path: '../'
@@ -1,18 +1,19 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  group :test do
6
- gem "activejob", "~> 7.2"
7
- gem "httparty"
8
- gem "multi_xml"
9
- gem "simplecov"
6
+ gem 'activejob', '~> 7.2'
7
+ gem 'httparty'
8
+ gem 'multi_xml'
9
+ gem 'simplecov'
10
+ gem 'warning'
10
11
  end
11
12
 
12
13
  group :development do
13
- gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
14
- gem "pry-byebug"
15
- gem "rubocop"
14
+ gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
15
+ gem 'pry-byebug'
16
+ gem 'rubocop'
16
17
  end
17
18
 
18
- gemspec path: "../"
19
+ gemspec path: '../'
@@ -1,18 +1,19 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  group :test do
6
- gem "activejob", "~> 8.0"
7
- gem "httparty"
8
- gem "multi_xml"
9
- gem "simplecov"
6
+ gem 'activejob', '~> 8.0'
7
+ gem 'httparty'
8
+ gem 'multi_xml'
9
+ gem 'simplecov'
10
+ gem 'warning'
10
11
  end
11
12
 
12
13
  group :development do
13
- gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
14
- gem "pry-byebug"
15
- gem "rubocop"
14
+ gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
15
+ gem 'pry-byebug'
16
+ gem 'rubocop'
16
17
  end
17
18
 
18
- gemspec path: "../"
19
+ gemspec path: '../'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class BodyParser
3
5
  class << self
@@ -16,7 +18,7 @@ module Shoryuken
16
18
  # JSON.parse
17
19
  body_parser.parse(sqs_msg.body)
18
20
  elsif body_parser.respond_to?(:load)
19
- # see https://github.com/phstc/shoryuken/pull/91
21
+ # see https://github.com/ruby-shoryuken/shoryuken/pull/91
20
22
  # JSON.load
21
23
  body_parser.load(sqs_msg.body)
22
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class Client
3
5
  @@queues = {}
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class DefaultExceptionHandler
3
5
  extend Util
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class DefaultWorkerRegistry < WorkerRegistry
3
5
  def initialize
4
- @workers = Concurrent::Hash.new
6
+ @workers = Shoryuken::Helpers::AtomicHash.new
5
7
  end
6
8
 
7
9
  def batch_receive_messages?(queue)
@@ -19,10 +21,10 @@ module Shoryuken
19
21
  message.message_attributes['shoryuken_class'][:string_value]
20
22
 
21
23
  worker_class = begin
22
- worker_class.constantize
23
- rescue
24
- @workers[queue]
25
- end
24
+ Shoryuken::Helpers::StringUtils.constantize(worker_class)
25
+ rescue
26
+ @workers[queue]
27
+ end
26
28
 
27
29
  worker_class.new if worker_class
28
30
  end
@@ -32,12 +34,10 @@ module Shoryuken
32
34
  end
33
35
 
34
36
  def register_worker(queue, clazz)
35
- if (worker_class = @workers[queue])
36
- if worker_class.get_shoryuken_options['batch'] == true || clazz.get_shoryuken_options['batch'] == true
37
- fail ArgumentError, "Could not register #{clazz} for #{queue}, "\
38
- "because #{worker_class} is already registered for this queue, "\
39
- "and Shoryuken doesn't support a batchable worker for a queue with multiple workers"
40
- end
37
+ if (worker_class = @workers[queue]) && (worker_class.get_shoryuken_options['batch'] == true || clazz.get_shoryuken_options['batch'] == true)
38
+ fail ArgumentError, "Could not register #{clazz} for #{queue}, "\
39
+ "because #{worker_class} is already registered for this queue, "\
40
+ "and Shoryuken doesn't support a batchable worker for a queue with multiple workers"
41
41
  end
42
42
 
43
43
  @workers[queue] = clazz
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class EnvironmentLoader
3
5
  attr_reader :options
@@ -44,7 +46,7 @@ module Shoryuken
44
46
  fail ArgumentError, "The supplied config file #{path} does not exist" unless File.exist?(path)
45
47
 
46
48
  if (result = YAML.load(ERB.new(IO.read(path)).result))
47
- result.deep_symbolize_keys
49
+ Shoryuken::Helpers::HashUtils.deep_symbolize_keys(result)
48
50
  else
49
51
  {}
50
52
  end
@@ -161,11 +163,9 @@ module Shoryuken
161
163
  non_existent_queues = []
162
164
 
163
165
  Shoryuken.ungrouped_queues.uniq.each do |queue|
164
- begin
165
- Shoryuken::Client.queues(queue)
166
- rescue Aws::Errors::NoSuchEndpointError, Aws::SQS::Errors::NonExistentQueue
167
- non_existent_queues << queue
168
- end
166
+ Shoryuken::Client.queues(queue)
167
+ rescue Aws::Errors::NoSuchEndpointError, Aws::SQS::Errors::NonExistentQueue
168
+ non_existent_queues << queue
169
169
  end
170
170
 
171
171
  return if non_existent_queues.none?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ActiveJob docs: http://edgeguides.rubyonrails.org/active_job_basics.html
2
4
  # Example adapters ref: https://github.com/rails/rails/tree/master/activejob/lib/active_job/queue_adapters
3
5
 
@@ -9,15 +11,15 @@ module ActiveJob
9
11
  #
10
12
  # Shoryuken ("sho-ryu-ken") is a super-efficient AWS SQS thread based message processor.
11
13
  #
12
- # Read more about Shoryuken {here}[https://github.com/phstc/shoryuken].
14
+ # Read more about Shoryuken {here}[https://github.com/ruby-shoryuken/shoryuken].
13
15
  #
14
16
  # To use Shoryuken set the queue_adapter config to +:shoryuken+.
15
17
  #
16
18
  # Rails.application.config.active_job.queue_adapter = :shoryuken
17
- class ShoryukenAdapter
19
+ class ShoryukenAdapter < ActiveJob::QueueAdapters::AbstractAdapter
18
20
  class << self
19
21
  def instance
20
- # https://github.com/phstc/shoryuken/pull/174#issuecomment-174555657
22
+ # https://github.com/ruby-shoryuken/shoryuken/pull/174#issuecomment-174555657
21
23
  @instance ||= new
22
24
  end
23
25
 
@@ -35,7 +37,7 @@ module ActiveJob
35
37
  true
36
38
  end
37
39
 
38
- def enqueue(job, options = {}) #:nodoc:
40
+ def enqueue(job, options = {}) # :nodoc:
39
41
  register_worker!(job)
40
42
 
41
43
  job.sqs_send_message_parameters.merge! options
@@ -46,7 +48,7 @@ module ActiveJob
46
48
  queue.send_message send_message_params
47
49
  end
48
50
 
49
- def enqueue_at(job, timestamp) #:nodoc:
51
+ def enqueue_at(job, timestamp) # :nodoc:
50
52
  enqueue(job, delay_seconds: calculate_delay(timestamp))
51
53
  end
52
54
 
@@ -85,7 +87,7 @@ module ActiveJob
85
87
  Shoryuken.register_worker(job.queue_name, JobWrapper)
86
88
  end
87
89
 
88
- class JobWrapper #:nodoc:
90
+ class JobWrapper # :nodoc:
89
91
  include Shoryuken::Worker
90
92
 
91
93
  shoryuken_options body_parser: :json, auto_delete: true
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ActiveJob docs: http://edgeguides.rubyonrails.org/active_job_basics.html
2
4
  # Example adapters ref: https://github.com/rails/rails/tree/master/activejob/lib/active_job/queue_adapters
3
5
  module ActiveJob
@@ -30,11 +32,9 @@ module ActiveJob
30
32
  end
31
33
 
32
34
  def error_handler
33
- @error_handler ||= begin
34
- lambda { |error, job, _options|
35
- Shoryuken.logger.warn("Failed to enqueue job: #{job.inspect} due to error: #{error}")
36
- }
37
- end
35
+ @error_handler ||= lambda { |error, job, _options|
36
+ Shoryuken.logger.warn("Failed to enqueue job: #{job.inspect} due to error: #{error}")
37
+ }
38
38
  end
39
39
 
40
40
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  module ActiveJobExtensions
3
5
  # Adds an accessor for SQS SendMessage parameters on ActiveJob jobs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shoryuken
2
4
  class Fetcher
3
5
  include Util
@@ -30,13 +32,13 @@ module Shoryuken
30
32
 
31
33
  begin
32
34
  yield
33
- rescue => ex
35
+ rescue => e
34
36
  # Tries to auto retry connectivity errors
35
37
  raise if attempts >= max_attempts
36
38
 
37
39
  attempts += 1
38
40
 
39
- logger.debug { "Retrying fetch attempt #{attempts} for #{ex.message}" }
41
+ logger.debug { "Retrying fetch attempt #{attempts} for #{e.message}" }
40
42
 
41
43
  sleep((1..5).to_a.sample)
42
44
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoryuken
4
+ module Helpers
5
+ # A thread-safe boolean implementation using AtomicCounter as base.
6
+ # Drop-in replacement for Concurrent::AtomicBoolean without external dependencies.
7
+ # Uses 1 for true and 0 for false internally.
8
+ class AtomicBoolean < AtomicCounter
9
+ # Prevent misuse of counter operations on a boolean
10
+ undef_method :increment, :decrement
11
+
12
+ def initialize(initial_value = false)
13
+ super(initial_value ? 1 : 0)
14
+ end
15
+
16
+ # Get the current value as boolean
17
+ def value
18
+ super != 0
19
+ end
20
+
21
+ # Set the value to true
22
+ def make_true
23
+ @mutex.synchronize { @value = 1 }
24
+ true
25
+ end
26
+
27
+ # Set the value to false
28
+ def make_false
29
+ @mutex.synchronize { @value = 0 }
30
+ false
31
+ end
32
+
33
+ # Check if the value is true
34
+ def true?
35
+ @mutex.synchronize { @value != 0 }
36
+ end
37
+
38
+ # Check if the value is false
39
+ def false?
40
+ @mutex.synchronize { @value == 0 }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoryuken
4
+ module Helpers
5
+ # A thread-safe counter implementation using Ruby's Mutex.
6
+ #
7
+ # This class provides atomic operations for incrementing, decrementing, and reading
8
+ # integer values in a thread-safe manner. It serves as a drop-in replacement for
9
+ # Concurrent::AtomicFixnum without requiring external dependencies.
10
+ #
11
+ # The implementation uses a Mutex to ensure thread safety across all Ruby
12
+ # implementations including JRuby, where true parallelism makes atomic operations
13
+ # critical for data integrity.
14
+ #
15
+ # @note This class is optimized for scenarios with frequent atomic updates
16
+ # and occasional reads, such as tracking active worker counts.
17
+ #
18
+ # @example Basic usage
19
+ # counter = Shoryuken::Helpers::AtomicCounter.new(0)
20
+ # counter.increment # => 1
21
+ # counter.increment # => 2
22
+ # counter.value # => 2
23
+ # counter.decrement # => 1
24
+ #
25
+ # @example Tracking busy processors
26
+ # @busy_processors = Shoryuken::Helpers::AtomicCounter.new(0)
27
+ #
28
+ # # When starting work
29
+ # @busy_processors.increment
30
+ #
31
+ # # When work is done
32
+ # @busy_processors.decrement
33
+ #
34
+ # # Check current load
35
+ # current_busy = @busy_processors.value
36
+ class AtomicCounter
37
+ # Creates a new atomic counter with the specified initial value.
38
+ #
39
+ # @param initial_value [Integer] The starting value for the counter
40
+ # @return [AtomicCounter] A new atomic counter instance
41
+ #
42
+ # @example Create counter starting at zero
43
+ # counter = Shoryuken::Helpers::AtomicCounter.new
44
+ # counter.value # => 0
45
+ #
46
+ # @example Create counter with custom initial value
47
+ # counter = Shoryuken::Helpers::AtomicCounter.new(100)
48
+ # counter.value # => 100
49
+ def initialize(initial_value = 0)
50
+ @mutex = Mutex.new
51
+ @value = initial_value
52
+ end
53
+
54
+ # Returns the current value of the counter.
55
+ #
56
+ # This operation is thread-safe and will return a consistent value
57
+ # even when called concurrently with increment/decrement operations.
58
+ #
59
+ # @return [Integer] The current counter value
60
+ #
61
+ # @example Reading the current value
62
+ # counter = Shoryuken::Helpers::AtomicCounter.new(42)
63
+ # counter.value # => 42
64
+ def value
65
+ @mutex.synchronize { @value }
66
+ end
67
+
68
+ # Atomically increments the counter by 1 and returns the new value.
69
+ #
70
+ # This operation is thread-safe and can be called concurrently from
71
+ # multiple threads without risk of data corruption or lost updates.
72
+ #
73
+ # @return [Integer] The new counter value after incrementing
74
+ #
75
+ # @example Incrementing the counter
76
+ # counter = Shoryuken::Helpers::AtomicCounter.new(5)
77
+ # counter.increment # => 6
78
+ # counter.increment # => 7
79
+ def increment
80
+ @mutex.synchronize { @value += 1 }
81
+ end
82
+
83
+ # Atomically decrements the counter by 1 and returns the new value.
84
+ #
85
+ # This operation is thread-safe and can be called concurrently from
86
+ # multiple threads without risk of data corruption or lost updates.
87
+ # The counter can go negative if decremented below zero.
88
+ #
89
+ # @return [Integer] The new counter value after decrementing
90
+ #
91
+ # @example Decrementing the counter
92
+ # counter = Shoryuken::Helpers::AtomicCounter.new(5)
93
+ # counter.decrement # => 4
94
+ # counter.decrement # => 3
95
+ #
96
+ # @example Counter can go negative
97
+ # counter = Shoryuken::Helpers::AtomicCounter.new(0)
98
+ # counter.decrement # => -1
99
+ def decrement
100
+ @mutex.synchronize { @value -= 1 }
101
+ end
102
+ end
103
+ end
104
+ end