shoryuken 6.2.1 → 7.0.2

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 (205) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/push.yml +36 -0
  3. data/.github/workflows/specs.yml +49 -44
  4. data/.github/workflows/verify-action-pins.yml +16 -0
  5. data/.gitignore +4 -1
  6. data/.rspec +3 -1
  7. data/.rubocop.yml +6 -1
  8. data/.ruby-version +1 -0
  9. data/.yard-lint.yml +279 -0
  10. data/CHANGELOG.md +308 -139
  11. data/Gemfile +1 -8
  12. data/Gemfile.lint +9 -0
  13. data/Gemfile.lint.lock +69 -0
  14. data/README.md +16 -33
  15. data/Rakefile +6 -10
  16. data/bin/clean_sqs +52 -0
  17. data/bin/cli/base.rb +22 -2
  18. data/bin/cli/sqs.rb +74 -7
  19. data/bin/integrations +275 -0
  20. data/bin/scenario +154 -0
  21. data/bin/shoryuken +3 -2
  22. data/docker-compose.yml +6 -0
  23. data/lib/{shoryuken/extensions/active_job_extensions.rb → active_job/extensions.rb} +20 -6
  24. data/lib/active_job/queue_adapters/shoryuken_adapter.rb +208 -0
  25. data/lib/active_job/queue_adapters/shoryuken_concurrent_send_adapter.rb +78 -0
  26. data/lib/shoryuken/active_job/current_attributes.rb +139 -0
  27. data/lib/shoryuken/active_job/job_wrapper.rb +28 -0
  28. data/lib/shoryuken/body_parser.rb +11 -1
  29. data/lib/shoryuken/client.rb +16 -0
  30. data/lib/shoryuken/default_exception_handler.rb +11 -0
  31. data/lib/shoryuken/default_worker_registry.rb +39 -11
  32. data/lib/shoryuken/environment_loader.rb +85 -15
  33. data/lib/shoryuken/errors.rb +36 -0
  34. data/lib/shoryuken/fetcher.rb +41 -3
  35. data/lib/shoryuken/helpers/atomic_boolean.rb +58 -0
  36. data/lib/shoryuken/helpers/atomic_counter.rb +104 -0
  37. data/lib/shoryuken/helpers/atomic_hash.rb +182 -0
  38. data/lib/shoryuken/helpers/hash_utils.rb +56 -0
  39. data/lib/shoryuken/helpers/string_utils.rb +65 -0
  40. data/lib/shoryuken/helpers/timer_task.rb +80 -0
  41. data/lib/shoryuken/inline_message.rb +22 -0
  42. data/lib/shoryuken/launcher.rb +55 -0
  43. data/lib/shoryuken/logging/base.rb +26 -0
  44. data/lib/shoryuken/logging/pretty.rb +25 -0
  45. data/lib/shoryuken/logging/without_timestamp.rb +25 -0
  46. data/lib/shoryuken/logging.rb +43 -15
  47. data/lib/shoryuken/manager.rb +84 -5
  48. data/lib/shoryuken/message.rb +116 -1
  49. data/lib/shoryuken/middleware/chain.rb +141 -43
  50. data/lib/shoryuken/middleware/entry.rb +30 -0
  51. data/lib/shoryuken/middleware/server/active_record.rb +10 -0
  52. data/lib/shoryuken/middleware/server/auto_delete.rb +12 -0
  53. data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +37 -11
  54. data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +34 -3
  55. data/lib/shoryuken/middleware/server/non_retryable_exception.rb +95 -0
  56. data/lib/shoryuken/middleware/server/timing.rb +13 -0
  57. data/lib/shoryuken/options.rb +154 -13
  58. data/lib/shoryuken/polling/base_strategy.rb +127 -0
  59. data/lib/shoryuken/polling/queue_configuration.rb +103 -0
  60. data/lib/shoryuken/polling/strict_priority.rb +41 -0
  61. data/lib/shoryuken/polling/weighted_round_robin.rb +44 -0
  62. data/lib/shoryuken/processor.rb +37 -3
  63. data/lib/shoryuken/queue.rb +99 -8
  64. data/lib/shoryuken/runner.rb +54 -16
  65. data/lib/shoryuken/util.rb +32 -7
  66. data/lib/shoryuken/version.rb +4 -1
  67. data/lib/shoryuken/worker/default_executor.rb +23 -1
  68. data/lib/shoryuken/worker/inline_executor.rb +33 -2
  69. data/lib/shoryuken/worker.rb +224 -0
  70. data/lib/shoryuken/worker_registry.rb +35 -0
  71. data/lib/shoryuken.rb +27 -38
  72. data/renovate.json +62 -0
  73. data/shoryuken.gemspec +8 -4
  74. data/spec/integration/.rspec +1 -0
  75. data/spec/integration/active_job/adapter_configuration/configuration_spec.rb +26 -0
  76. data/spec/integration/active_job/bulk_enqueue/bulk_enqueue_spec.rb +53 -0
  77. data/spec/integration/active_job/current_attributes/bulk_enqueue_spec.rb +50 -0
  78. data/spec/integration/active_job/current_attributes/complex_types_spec.rb +55 -0
  79. data/spec/integration/active_job/current_attributes/empty_context_spec.rb +41 -0
  80. data/spec/integration/active_job/current_attributes/full_context_spec.rb +63 -0
  81. data/spec/integration/active_job/current_attributes/partial_context_spec.rb +57 -0
  82. data/spec/integration/active_job/custom_attributes/number_attributes_spec.rb +37 -0
  83. data/spec/integration/active_job/custom_attributes/string_attributes_spec.rb +39 -0
  84. data/spec/integration/active_job/error_handling/job_wrapper_spec.rb +53 -0
  85. data/spec/integration/active_job/fifo_and_attributes/deduplication_spec.rb +86 -0
  86. data/spec/integration/active_job/keyword_arguments/keyword_arguments_spec.rb +63 -0
  87. data/spec/integration/active_job/retry/discard_on_spec.rb +43 -0
  88. data/spec/integration/active_job/retry/retry_on_spec.rb +36 -0
  89. data/spec/integration/active_job/roundtrip/roundtrip_spec.rb +52 -0
  90. data/spec/integration/active_job/scheduled/scheduled_spec.rb +76 -0
  91. data/spec/integration/active_record_middleware/active_record_middleware_spec.rb +84 -0
  92. data/spec/integration/auto_delete/auto_delete_spec.rb +53 -0
  93. data/spec/integration/auto_extend_visibility/auto_extend_visibility_spec.rb +57 -0
  94. data/spec/integration/aws_config/aws_config_spec.rb +59 -0
  95. data/spec/integration/batch_processing/batch_processing_spec.rb +37 -0
  96. data/spec/integration/body_parser/json_parser_spec.rb +45 -0
  97. data/spec/integration/body_parser/proc_parser_spec.rb +54 -0
  98. data/spec/integration/body_parser/text_parser_spec.rb +43 -0
  99. data/spec/integration/concurrent_processing/concurrent_processing_spec.rb +45 -0
  100. data/spec/integration/custom_group_polling_strategy/custom_group_polling_strategy_spec.rb +87 -0
  101. data/spec/integration/dead_letter_queue/dead_letter_queue_spec.rb +91 -0
  102. data/spec/integration/exception_handlers/exception_handlers_spec.rb +69 -0
  103. data/spec/integration/exponential_backoff/exponential_backoff_spec.rb +67 -0
  104. data/spec/integration/fifo_ordering/fifo_ordering_spec.rb +44 -0
  105. data/spec/integration/large_payloads/large_payloads_spec.rb +30 -0
  106. data/spec/integration/launcher/launcher_spec.rb +40 -0
  107. data/spec/integration/message_attributes/message_attributes_spec.rb +54 -0
  108. data/spec/integration/message_operations/message_operations_spec.rb +59 -0
  109. data/spec/integration/middleware_chain/empty_chain_spec.rb +11 -0
  110. data/spec/integration/middleware_chain/execution_order_spec.rb +33 -0
  111. data/spec/integration/middleware_chain/removal_spec.rb +31 -0
  112. data/spec/integration/middleware_chain/short_circuit_spec.rb +40 -0
  113. data/spec/integration/non_retryable_exception/non_retryable_exception_spec.rb +149 -0
  114. data/spec/integration/polling_strategies/polling_strategies_spec.rb +46 -0
  115. data/spec/integration/queue_operations/queue_operations_spec.rb +84 -0
  116. data/spec/integration/rails/rails_72/Gemfile +6 -0
  117. data/spec/integration/rails/rails_72/activejob_adapter_spec.rb +98 -0
  118. data/spec/integration/rails/rails_80/Gemfile +6 -0
  119. data/spec/integration/rails/rails_80/activejob_adapter_spec.rb +98 -0
  120. data/spec/integration/rails/rails_80/continuation_spec.rb +79 -0
  121. data/spec/integration/rails/rails_81/Gemfile +6 -0
  122. data/spec/integration/rails/rails_81/activejob_adapter_spec.rb +98 -0
  123. data/spec/integration/rails/rails_81/continuation_spec.rb +79 -0
  124. data/spec/integration/retry_behavior/retry_behavior_spec.rb +45 -0
  125. data/spec/integration/spec_helper.rb +7 -0
  126. data/spec/integration/strict_priority_polling/strict_priority_polling_spec.rb +58 -0
  127. data/spec/integration/visibility_timeout/visibility_timeout_spec.rb +37 -0
  128. data/spec/integration/worker_enqueueing/worker_enqueueing_spec.rb +60 -0
  129. data/spec/integration/worker_groups/worker_groups_spec.rb +79 -0
  130. data/spec/integration/worker_lifecycle/worker_lifecycle_spec.rb +33 -0
  131. data/spec/integrations_helper.rb +243 -0
  132. data/spec/lib/active_job/extensions_spec.rb +225 -0
  133. data/spec/lib/active_job/queue_adapters/shoryuken_adapter_spec.rb +29 -0
  134. data/spec/{shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb → lib/active_job/queue_adapters/shoryuken_concurrent_send_adapter_spec.rb} +5 -4
  135. data/spec/{shoryuken/extensions/active_job_wrapper_spec.rb → lib/shoryuken/active_job/job_wrapper_spec.rb} +6 -5
  136. data/spec/{shoryuken → lib/shoryuken}/body_parser_spec.rb +2 -4
  137. data/spec/{shoryuken → lib/shoryuken}/client_spec.rb +1 -1
  138. data/spec/{shoryuken → lib/shoryuken}/default_exception_handler_spec.rb +9 -10
  139. data/spec/{shoryuken → lib/shoryuken}/default_worker_registry_spec.rb +1 -2
  140. data/spec/{shoryuken → lib/shoryuken}/environment_loader_spec.rb +10 -9
  141. data/spec/{shoryuken → lib/shoryuken}/fetcher_spec.rb +23 -26
  142. data/spec/lib/shoryuken/helpers/atomic_boolean_spec.rb +196 -0
  143. data/spec/lib/shoryuken/helpers/atomic_counter_spec.rb +177 -0
  144. data/spec/lib/shoryuken/helpers/atomic_hash_spec.rb +307 -0
  145. data/spec/lib/shoryuken/helpers/hash_utils_spec.rb +145 -0
  146. data/spec/lib/shoryuken/helpers/string_utils_spec.rb +124 -0
  147. data/spec/lib/shoryuken/helpers/timer_task_spec.rb +298 -0
  148. data/spec/lib/shoryuken/helpers_integration_spec.rb +96 -0
  149. data/spec/lib/shoryuken/inline_message_spec.rb +196 -0
  150. data/spec/{shoryuken → lib/shoryuken}/launcher_spec.rb +23 -2
  151. data/spec/lib/shoryuken/logging_spec.rb +242 -0
  152. data/spec/{shoryuken → lib/shoryuken}/manager_spec.rb +1 -2
  153. data/spec/lib/shoryuken/message_spec.rb +109 -0
  154. data/spec/{shoryuken → lib/shoryuken}/middleware/chain_spec.rb +1 -1
  155. data/spec/lib/shoryuken/middleware/entry_spec.rb +68 -0
  156. data/spec/lib/shoryuken/middleware/server/active_record_spec.rb +133 -0
  157. data/spec/{shoryuken → lib/shoryuken}/middleware/server/auto_delete_spec.rb +1 -1
  158. data/spec/{shoryuken → lib/shoryuken}/middleware/server/auto_extend_visibility_spec.rb +51 -1
  159. data/spec/{shoryuken → lib/shoryuken}/middleware/server/exponential_backoff_retry_spec.rb +1 -1
  160. data/spec/lib/shoryuken/middleware/server/non_retryable_exception_spec.rb +214 -0
  161. data/spec/{shoryuken → lib/shoryuken}/middleware/server/timing_spec.rb +1 -1
  162. data/spec/{shoryuken → lib/shoryuken}/options_spec.rb +49 -6
  163. data/spec/lib/shoryuken/polling/base_strategy_spec.rb +280 -0
  164. data/spec/lib/shoryuken/polling/queue_configuration_spec.rb +195 -0
  165. data/spec/{shoryuken → lib/shoryuken}/polling/strict_priority_spec.rb +1 -1
  166. data/spec/{shoryuken → lib/shoryuken}/polling/weighted_round_robin_spec.rb +1 -1
  167. data/spec/{shoryuken → lib/shoryuken}/processor_spec.rb +1 -1
  168. data/spec/{shoryuken → lib/shoryuken}/queue_spec.rb +2 -3
  169. data/spec/{shoryuken → lib/shoryuken}/runner_spec.rb +1 -3
  170. data/spec/{shoryuken → lib/shoryuken}/util_spec.rb +2 -2
  171. data/spec/lib/shoryuken/version_spec.rb +17 -0
  172. data/spec/{shoryuken → lib/shoryuken}/worker/default_executor_spec.rb +1 -1
  173. data/spec/lib/shoryuken/worker/inline_executor_spec.rb +105 -0
  174. data/spec/lib/shoryuken/worker_registry_spec.rb +63 -0
  175. data/spec/{shoryuken → lib/shoryuken}/worker_spec.rb +15 -11
  176. data/spec/{shoryuken_spec.rb → lib/shoryuken_spec.rb} +1 -1
  177. data/spec/shared_examples_for_active_job.rb +40 -15
  178. data/spec/spec_helper.rb +48 -2
  179. metadata +295 -101
  180. data/.codeclimate.yml +0 -20
  181. data/.devcontainer/Dockerfile +0 -17
  182. data/.devcontainer/base.Dockerfile +0 -43
  183. data/.devcontainer/devcontainer.json +0 -35
  184. data/.github/FUNDING.yml +0 -12
  185. data/.github/dependabot.yml +0 -6
  186. data/.github/workflows/stale.yml +0 -20
  187. data/.reek.yml +0 -5
  188. data/Appraisals +0 -42
  189. data/gemfiles/.gitignore +0 -1
  190. data/gemfiles/aws_sdk_core_2.gemfile +0 -21
  191. data/gemfiles/rails_4_2.gemfile +0 -20
  192. data/gemfiles/rails_5_2.gemfile +0 -21
  193. data/gemfiles/rails_6_0.gemfile +0 -21
  194. data/gemfiles/rails_6_1.gemfile +0 -21
  195. data/gemfiles/rails_7_0.gemfile +0 -22
  196. data/lib/shoryuken/core_ext.rb +0 -69
  197. data/lib/shoryuken/extensions/active_job_adapter.rb +0 -103
  198. data/lib/shoryuken/extensions/active_job_concurrent_send_adapter.rb +0 -50
  199. data/lib/shoryuken/polling/base.rb +0 -67
  200. data/shoryuken.jpg +0 -0
  201. data/spec/integration/launcher_spec.rb +0 -128
  202. data/spec/shoryuken/core_ext_spec.rb +0 -40
  203. data/spec/shoryuken/extensions/active_job_adapter_spec.rb +0 -7
  204. data/spec/shoryuken/extensions/active_job_base_spec.rb +0 -84
  205. data/spec/shoryuken/worker/inline_executor_spec.rb +0 -49
@@ -1,20 +0,0 @@
1
- name: "Close stale issues and PRs"
2
- on:
3
- schedule:
4
- - cron: "30 1 * * *" # At 01:30 - https://crontab.guru/#30_1_*_*_*
5
- workflow_dispatch: {}
6
- jobs:
7
- stale:
8
- runs-on: ubuntu-latest
9
- permissions:
10
- issues: write
11
- pull-requests: write
12
- steps:
13
- - uses: actions/stale@v9
14
- with:
15
- stale-issue-message: This issue is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon.
16
- stale-pr-message: This PR is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon.
17
- close-issue-message: This issue was closed because it hasn't seen activity for a while.
18
- close-pr-message: This PR was closed because it hasn't seen activity for a while.
19
- days-before-stale: 60
20
- days-before-close: 7
data/.reek.yml DELETED
@@ -1,5 +0,0 @@
1
- ---
2
- detectors:
3
-
4
- UtilityFunction:
5
- public_methods_only: true
data/Appraisals DELETED
@@ -1,42 +0,0 @@
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
-
9
- appraise 'rails_4_2' do
10
- group :test do
11
- gem 'activejob', '~> 4.2'
12
- end
13
-
14
- group :development do
15
- gem 'appraisal', '~> 2.2'
16
- remove_gem 'pry-byebug'
17
- end
18
- end
19
-
20
- appraise 'rails_5_2' do
21
- group :test do
22
- gem 'activejob', '~> 5.2'
23
- end
24
- end
25
-
26
- appraise 'rails_6_0' do
27
- group :test do
28
- gem 'activejob', '~> 6.0'
29
- end
30
- end
31
-
32
- appraise 'rails_6_1' do
33
- group :test do
34
- gem 'activejob', '~> 6.1'
35
- end
36
- end
37
-
38
- appraise 'rails_7_0' do
39
- group :test do
40
- gem 'activejob', '~> 7.0'
41
- end
42
- end
data/gemfiles/.gitignore DELETED
@@ -1 +0,0 @@
1
- *.gemfile.lock
@@ -1,21 +0,0 @@
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"
18
- gem "rubocop"
19
- end
20
-
21
- gemspec path: "../"
@@ -1,20 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- group :test do
6
- gem "activejob", "~> 4.2"
7
- gem "aws-sdk-core", "~> 3"
8
- gem "aws-sdk-sqs"
9
- gem "codeclimate-test-reporter", require: nil
10
- gem "httparty"
11
- gem "multi_xml"
12
- gem "simplecov"
13
- end
14
-
15
- group :development do
16
- gem "appraisal", "~> 2.2"
17
- gem "rubocop"
18
- end
19
-
20
- gemspec path: "../"
@@ -1,21 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- group :test do
6
- gem "activejob", "~> 5.2"
7
- gem "aws-sdk-core", "~> 3"
8
- gem "aws-sdk-sqs"
9
- gem "codeclimate-test-reporter", require: nil
10
- gem "httparty"
11
- gem "multi_xml"
12
- gem "simplecov"
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: "../"
@@ -1,21 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- group :test do
6
- gem "activejob", "~> 6.0"
7
- gem "aws-sdk-core", "~> 3"
8
- gem "aws-sdk-sqs"
9
- gem "codeclimate-test-reporter", require: nil
10
- gem "httparty"
11
- gem "multi_xml"
12
- gem "simplecov"
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: "../"
@@ -1,21 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- group :test do
6
- gem "activejob", "~> 6.1"
7
- gem "aws-sdk-core", "~> 3"
8
- gem "aws-sdk-sqs"
9
- gem "codeclimate-test-reporter", require: nil
10
- gem "httparty"
11
- gem "multi_xml"
12
- gem "simplecov"
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: "../"
@@ -1,22 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- group :test do
6
- gem "activejob", "~> 7.0"
7
- gem "aws-sdk-core", "~> 3"
8
- gem "aws-sdk-sqs"
9
- gem "codeclimate-test-reporter", require: nil
10
- gem "httparty"
11
- gem "multi_xml"
12
- gem "simplecov"
13
- end
14
-
15
- group :development do
16
- gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
17
- gem "rubocop"
18
- gem "pry", ">= 0.14.2"
19
- gem "pry-byebug", ">= 3.10.1"
20
- end
21
-
22
- gemspec path: "../"
@@ -1,69 +0,0 @@
1
- module Shoryuken
2
- module HashExt
3
- module StringifyKeys
4
- def stringify_keys
5
- keys.each do |key|
6
- self[key.to_s] = delete(key)
7
- end
8
- self
9
- end
10
- end
11
-
12
- module SymbolizeKeys
13
- def symbolize_keys
14
- keys.each do |key|
15
- self[(key.to_sym rescue key) || key] = delete(key)
16
- end
17
- self
18
- end
19
- end
20
-
21
- module DeepSymbolizeKeys
22
- def deep_symbolize_keys
23
- keys.each do |key|
24
- value = delete(key)
25
- self[(key.to_sym rescue key) || key] = value
26
-
27
- value.deep_symbolize_keys if value.is_a? Hash
28
- end
29
- self
30
- end
31
- end
32
- end
33
-
34
- module StringExt
35
- module Constantize
36
- def constantize
37
- names = split('::')
38
- names.shift if names.empty? || names.first.empty?
39
-
40
- constant = Object
41
- names.each do |name|
42
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
43
- end
44
- constant
45
- end
46
- end
47
- end
48
- end
49
-
50
- begin
51
- require 'active_support/core_ext/hash/keys'
52
- require 'active_support/core_ext/hash/deep_merge'
53
- rescue LoadError
54
- end
55
-
56
- class Hash
57
- include Shoryuken::HashExt::StringifyKeys unless method_defined?(:stringify_keys)
58
- include Shoryuken::HashExt::SymbolizeKeys unless method_defined?(:symbolize_keys)
59
- include Shoryuken::HashExt::DeepSymbolizeKeys unless method_defined?(:deep_symbolize_keys)
60
- end
61
-
62
- begin
63
- require 'active_support/core_ext/string/inflections'
64
- rescue LoadError
65
- end
66
-
67
- class String
68
- include Shoryuken::StringExt::Constantize unless method_defined?(:constantize)
69
- end
@@ -1,103 +0,0 @@
1
- # ActiveJob docs: http://edgeguides.rubyonrails.org/active_job_basics.html
2
- # Example adapters ref: https://github.com/rails/rails/tree/master/activejob/lib/active_job/queue_adapters
3
-
4
- require 'shoryuken'
5
-
6
- module ActiveJob
7
- module QueueAdapters
8
- # == Shoryuken adapter for Active Job
9
- #
10
- # Shoryuken ("sho-ryu-ken") is a super-efficient AWS SQS thread based message processor.
11
- #
12
- # Read more about Shoryuken {here}[https://github.com/phstc/shoryuken].
13
- #
14
- # To use Shoryuken set the queue_adapter config to +:shoryuken+.
15
- #
16
- # Rails.application.config.active_job.queue_adapter = :shoryuken
17
- class ShoryukenAdapter
18
- class << self
19
- def instance
20
- # https://github.com/phstc/shoryuken/pull/174#issuecomment-174555657
21
- @instance ||= new
22
- end
23
-
24
- def enqueue(job)
25
- instance.enqueue(job)
26
- end
27
-
28
- def enqueue_at(job, timestamp)
29
- instance.enqueue_at(job, timestamp)
30
- end
31
- end
32
-
33
- def enqueue(job, options = {}) #:nodoc:
34
- register_worker!(job)
35
-
36
- job.sqs_send_message_parameters.merge! options
37
-
38
- queue = Shoryuken::Client.queues(job.queue_name)
39
- send_message_params = message queue, job
40
- job.sqs_send_message_parameters = send_message_params
41
- queue.send_message send_message_params
42
- end
43
-
44
- def enqueue_at(job, timestamp) #:nodoc:
45
- enqueue(job, delay_seconds: calculate_delay(timestamp))
46
- end
47
-
48
- private
49
-
50
- def calculate_delay(timestamp)
51
- delay = (timestamp - Time.current.to_f).round
52
- raise 'The maximum allowed delay is 15 minutes' if delay > 15.minutes
53
-
54
- delay
55
- end
56
-
57
- def message(queue, job)
58
- body = job.serialize
59
- job_params = job.sqs_send_message_parameters
60
-
61
- attributes = job_params[:message_attributes] || {}
62
-
63
- msg = {
64
- message_body: body,
65
- message_attributes: attributes.merge(MESSAGE_ATTRIBUTES)
66
- }
67
-
68
- if queue.fifo?
69
- # See https://github.com/ruby-shoryuken/shoryuken/issues/457 and
70
- # https://github.com/ruby-shoryuken/shoryuken/pull/750#issuecomment-1781317929
71
- msg[:message_deduplication_id] = Digest::SHA256.hexdigest(
72
- JSON.dump(body.except('job_id', 'enqueued_at'))
73
- )
74
- end
75
-
76
- msg.merge(job_params.except(:message_attributes))
77
- end
78
-
79
- def register_worker!(job)
80
- Shoryuken.register_worker(job.queue_name, JobWrapper)
81
- end
82
-
83
- class JobWrapper #:nodoc:
84
- include Shoryuken::Worker
85
-
86
- shoryuken_options body_parser: :json, auto_delete: true
87
-
88
- def perform(sqs_msg, hash)
89
- receive_count = sqs_msg.attributes['ApproximateReceiveCount'].to_i
90
- past_receives = receive_count - 1
91
- Base.execute hash.merge({ 'executions' => past_receives })
92
- end
93
- end
94
-
95
- MESSAGE_ATTRIBUTES = {
96
- 'shoryuken_class' => {
97
- string_value: JobWrapper.to_s,
98
- data_type: 'String'
99
- }
100
- }.freeze
101
- end
102
- end
103
- end
@@ -1,50 +0,0 @@
1
- # ActiveJob docs: http://edgeguides.rubyonrails.org/active_job_basics.html
2
- # Example adapters ref: https://github.com/rails/rails/tree/master/activejob/lib/active_job/queue_adapters
3
- module ActiveJob
4
- module QueueAdapters
5
- # == Shoryuken concurrent adapter for Active Job
6
- #
7
- # This adapter sends messages asynchronously (ie non-blocking) and allows
8
- # the caller to set up handlers for both success and failure
9
- #
10
- # To use this adapter, set up as:
11
- #
12
- # success_handler = ->(response, job, options) { StatsD.increment("#{job.class.name}.success") }
13
- # error_handler = ->(err, job, options) { StatsD.increment("#{job.class.name}.failure") }
14
- #
15
- # adapter = ActiveJob::QueueAdapters::ShoryukenConcurrentSendAdapter.new(success_handler, error_handler)
16
- #
17
- # config.active_job.queue_adapter = adapter
18
- class ShoryukenConcurrentSendAdapter < ShoryukenAdapter
19
- def initialize(success_handler = nil, error_handler = nil)
20
- @success_handler = success_handler
21
- @error_handler = error_handler
22
- end
23
-
24
- def enqueue(job, options = {})
25
- send_concurrently(job, options) { |f_job, f_options| super(f_job, f_options) }
26
- end
27
-
28
- def success_handler
29
- @success_handler ||= ->(_send_message_response, _job, _options) { nil }
30
- end
31
-
32
- 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
38
- end
39
-
40
- private
41
-
42
- def send_concurrently(job, options)
43
- Concurrent::Promises
44
- .future(job, options) { |f_job, f_options| [yield(f_job, f_options), f_job, f_options] }
45
- .then { |send_message_response, f_job, f_options| success_handler.call(send_message_response, f_job, f_options) }
46
- .rescue(job, options) { |err, f_job, f_options| error_handler.call(err, f_job, f_options) }
47
- end
48
- end
49
- end
50
- end
@@ -1,67 +0,0 @@
1
- module Shoryuken
2
- module Polling
3
- QueueConfiguration = Struct.new(:name, :options) do
4
- def hash
5
- name.hash
6
- end
7
-
8
- def ==(other)
9
- case other
10
- when String
11
- if options.empty?
12
- name == other
13
- else
14
- false
15
- end
16
- else
17
- super
18
- end
19
- end
20
-
21
- alias_method :eql?, :==
22
-
23
- def to_s
24
- if options.empty?
25
- name
26
- else
27
- "#<QueueConfiguration #{name} options=#{options.inspect}>"
28
- end
29
- end
30
- end
31
-
32
- class BaseStrategy
33
- include Util
34
-
35
- def next_queue
36
- fail NotImplementedError
37
- end
38
-
39
- def messages_found(_queue, _messages_found)
40
- fail NotImplementedError
41
- end
42
-
43
- def message_processed(_queue); end
44
-
45
- def active_queues
46
- fail NotImplementedError
47
- end
48
-
49
- def ==(other)
50
- case other
51
- when Array
52
- @queues == other
53
- else
54
- if other.respond_to?(:active_queues)
55
- active_queues == other.active_queues
56
- else
57
- false
58
- end
59
- end
60
- end
61
-
62
- def delay
63
- @delay || Shoryuken.options[:delay].to_f
64
- end
65
- end
66
- end
67
- end
data/shoryuken.jpg DELETED
Binary file
@@ -1,128 +0,0 @@
1
- require 'spec_helper'
2
- require 'shoryuken/manager'
3
- require 'shoryuken/launcher'
4
- require 'securerandom'
5
-
6
- RSpec.describe Shoryuken::Launcher 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
26
- before do
27
- Aws.config[:stub_responses] = false
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
38
-
39
- StandardWorker.received_messages = 0
40
-
41
- queue = "shoryuken-travis-#{StandardWorker}-#{SecureRandom.uuid}"
42
-
43
- Shoryuken::Client.sqs.create_queue(queue_name: queue)
44
-
45
- Shoryuken.add_group('default', 1)
46
- Shoryuken.add_queue(queue, 1, 'default')
47
-
48
- StandardWorker.get_shoryuken_options['queue'] = queue
49
-
50
- Shoryuken.register_worker(queue, StandardWorker)
51
- end
52
-
53
- after do
54
- Aws.config[:stub_responses] = true
55
-
56
- queue_url = Shoryuken::Client.sqs.get_queue_url(
57
- queue_name: StandardWorker.get_shoryuken_options['queue']
58
- ).queue_url
59
-
60
- Shoryuken::Client.sqs.delete_queue(queue_url: queue_url)
61
- end
62
-
63
- it 'consumes as a command worker' do
64
- StandardWorker.perform_async('Yo')
65
-
66
- poll_queues_until { StandardWorker.received_messages > 0 }
67
-
68
- expect(StandardWorker.received_messages).to eq 1
69
- end
70
-
71
- it 'consumes a message' do
72
- StandardWorker.get_shoryuken_options['batch'] = false
73
-
74
- Shoryuken::Client.queues(StandardWorker.get_shoryuken_options['queue']).send_message(message_body: 'Yo')
75
-
76
- poll_queues_until { StandardWorker.received_messages > 0 }
77
-
78
- expect(StandardWorker.received_messages).to eq 1
79
- end
80
-
81
- it 'consumes a batch' do
82
- StandardWorker.get_shoryuken_options['batch'] = true
83
-
84
- entries = 10.times.map { |i| { id: SecureRandom.uuid, message_body: i.to_s } }
85
-
86
- Shoryuken::Client.queues(StandardWorker.get_shoryuken_options['queue']).send_messages(entries: entries)
87
-
88
- # Give the messages a chance to hit the queue so they are all available at the same time
89
- sleep 2
90
-
91
- poll_queues_until { StandardWorker.received_messages > 0 }
92
-
93
- expect(StandardWorker.received_messages).to be > 1
94
- end
95
-
96
- def poll_queues_until
97
- subject.start
98
-
99
- Timeout::timeout(10) do
100
- begin
101
- sleep 0.5
102
- end until yield
103
- end
104
- ensure
105
- subject.stop
106
- end
107
-
108
- class StandardWorker
109
- include Shoryuken::Worker
110
-
111
- @@received_messages = 0
112
-
113
- shoryuken_options auto_delete: true
114
-
115
- def perform(sqs_msg, _body)
116
- @@received_messages += Array(sqs_msg).size
117
- end
118
-
119
- def self.received_messages
120
- @@received_messages
121
- end
122
-
123
- def self.received_messages=(received_messages)
124
- @@received_messages = received_messages
125
- end
126
- end
127
- end
128
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe 'Core Extensions' do
4
- describe Hash do
5
- describe '#stringify_keys' do
6
- it 'converts keys into strings' do
7
- expect({ :key1 => 'value1', 'key2' => 'value2' }.stringify_keys).to eq('key1' => 'value1', 'key2' => 'value2')
8
- end
9
- end
10
-
11
- describe '#symbolize_keys' do
12
- it 'converts keys into symbols' do
13
- expect({ :key1 => 'value1', 'key2' => 'value2' }.symbolize_keys).to eq(key1: 'value1', key2: 'value2')
14
- end
15
- end
16
-
17
- describe '#deep_symbolize_keys' do
18
- it 'converts keys into symbols' do
19
- expect({ :key1 => 'value1',
20
- 'key2' => 'value2',
21
- 'key3' => {
22
- 'key31' => { 'key311' => 'value311' },
23
- 'key32' => 'value32'
24
- } }.deep_symbolize_keys).to eq(key1: 'value1',
25
- key2: 'value2',
26
- key3: { key31: { key311: 'value311' },
27
- key32: 'value32' })
28
- end
29
- end
30
- end
31
-
32
- describe String do
33
- describe '#constantize' do
34
- class HelloWorld; end
35
- it 'returns a class from a string' do
36
- expect('HelloWorld'.constantize).to eq HelloWorld
37
- end
38
- end
39
- end
40
- end
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
- require 'shared_examples_for_active_job'
3
- require 'shoryuken/extensions/active_job_adapter'
4
-
5
- RSpec.describe ActiveJob::QueueAdapters::ShoryukenAdapter do
6
- include_examples 'active_job_adapters'
7
- end