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.
- checksums.yaml +4 -4
- data/.github/workflows/push.yml +36 -0
- data/.github/workflows/specs.yml +49 -44
- data/.github/workflows/verify-action-pins.yml +16 -0
- data/.gitignore +4 -1
- data/.rspec +3 -1
- data/.rubocop.yml +6 -1
- data/.ruby-version +1 -0
- data/.yard-lint.yml +279 -0
- data/CHANGELOG.md +308 -139
- data/Gemfile +1 -8
- data/Gemfile.lint +9 -0
- data/Gemfile.lint.lock +69 -0
- data/README.md +16 -33
- data/Rakefile +6 -10
- data/bin/clean_sqs +52 -0
- data/bin/cli/base.rb +22 -2
- data/bin/cli/sqs.rb +74 -7
- data/bin/integrations +275 -0
- data/bin/scenario +154 -0
- data/bin/shoryuken +3 -2
- data/docker-compose.yml +6 -0
- data/lib/{shoryuken/extensions/active_job_extensions.rb → active_job/extensions.rb} +20 -6
- data/lib/active_job/queue_adapters/shoryuken_adapter.rb +208 -0
- data/lib/active_job/queue_adapters/shoryuken_concurrent_send_adapter.rb +78 -0
- data/lib/shoryuken/active_job/current_attributes.rb +139 -0
- data/lib/shoryuken/active_job/job_wrapper.rb +28 -0
- data/lib/shoryuken/body_parser.rb +11 -1
- data/lib/shoryuken/client.rb +16 -0
- data/lib/shoryuken/default_exception_handler.rb +11 -0
- data/lib/shoryuken/default_worker_registry.rb +39 -11
- data/lib/shoryuken/environment_loader.rb +85 -15
- data/lib/shoryuken/errors.rb +36 -0
- data/lib/shoryuken/fetcher.rb +41 -3
- data/lib/shoryuken/helpers/atomic_boolean.rb +58 -0
- data/lib/shoryuken/helpers/atomic_counter.rb +104 -0
- data/lib/shoryuken/helpers/atomic_hash.rb +182 -0
- data/lib/shoryuken/helpers/hash_utils.rb +56 -0
- data/lib/shoryuken/helpers/string_utils.rb +65 -0
- data/lib/shoryuken/helpers/timer_task.rb +80 -0
- data/lib/shoryuken/inline_message.rb +22 -0
- data/lib/shoryuken/launcher.rb +55 -0
- data/lib/shoryuken/logging/base.rb +26 -0
- data/lib/shoryuken/logging/pretty.rb +25 -0
- data/lib/shoryuken/logging/without_timestamp.rb +25 -0
- data/lib/shoryuken/logging.rb +43 -15
- data/lib/shoryuken/manager.rb +84 -5
- data/lib/shoryuken/message.rb +116 -1
- data/lib/shoryuken/middleware/chain.rb +141 -43
- data/lib/shoryuken/middleware/entry.rb +30 -0
- data/lib/shoryuken/middleware/server/active_record.rb +10 -0
- data/lib/shoryuken/middleware/server/auto_delete.rb +12 -0
- data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +37 -11
- data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +34 -3
- data/lib/shoryuken/middleware/server/non_retryable_exception.rb +95 -0
- data/lib/shoryuken/middleware/server/timing.rb +13 -0
- data/lib/shoryuken/options.rb +154 -13
- data/lib/shoryuken/polling/base_strategy.rb +127 -0
- data/lib/shoryuken/polling/queue_configuration.rb +103 -0
- data/lib/shoryuken/polling/strict_priority.rb +41 -0
- data/lib/shoryuken/polling/weighted_round_robin.rb +44 -0
- data/lib/shoryuken/processor.rb +37 -3
- data/lib/shoryuken/queue.rb +99 -8
- data/lib/shoryuken/runner.rb +54 -16
- data/lib/shoryuken/util.rb +32 -7
- data/lib/shoryuken/version.rb +4 -1
- data/lib/shoryuken/worker/default_executor.rb +23 -1
- data/lib/shoryuken/worker/inline_executor.rb +33 -2
- data/lib/shoryuken/worker.rb +224 -0
- data/lib/shoryuken/worker_registry.rb +35 -0
- data/lib/shoryuken.rb +27 -38
- data/renovate.json +62 -0
- data/shoryuken.gemspec +8 -4
- data/spec/integration/.rspec +1 -0
- data/spec/integration/active_job/adapter_configuration/configuration_spec.rb +26 -0
- data/spec/integration/active_job/bulk_enqueue/bulk_enqueue_spec.rb +53 -0
- data/spec/integration/active_job/current_attributes/bulk_enqueue_spec.rb +50 -0
- data/spec/integration/active_job/current_attributes/complex_types_spec.rb +55 -0
- data/spec/integration/active_job/current_attributes/empty_context_spec.rb +41 -0
- data/spec/integration/active_job/current_attributes/full_context_spec.rb +63 -0
- data/spec/integration/active_job/current_attributes/partial_context_spec.rb +57 -0
- data/spec/integration/active_job/custom_attributes/number_attributes_spec.rb +37 -0
- data/spec/integration/active_job/custom_attributes/string_attributes_spec.rb +39 -0
- data/spec/integration/active_job/error_handling/job_wrapper_spec.rb +53 -0
- data/spec/integration/active_job/fifo_and_attributes/deduplication_spec.rb +86 -0
- data/spec/integration/active_job/keyword_arguments/keyword_arguments_spec.rb +63 -0
- data/spec/integration/active_job/retry/discard_on_spec.rb +43 -0
- data/spec/integration/active_job/retry/retry_on_spec.rb +36 -0
- data/spec/integration/active_job/roundtrip/roundtrip_spec.rb +52 -0
- data/spec/integration/active_job/scheduled/scheduled_spec.rb +76 -0
- data/spec/integration/active_record_middleware/active_record_middleware_spec.rb +84 -0
- data/spec/integration/auto_delete/auto_delete_spec.rb +53 -0
- data/spec/integration/auto_extend_visibility/auto_extend_visibility_spec.rb +57 -0
- data/spec/integration/aws_config/aws_config_spec.rb +59 -0
- data/spec/integration/batch_processing/batch_processing_spec.rb +37 -0
- data/spec/integration/body_parser/json_parser_spec.rb +45 -0
- data/spec/integration/body_parser/proc_parser_spec.rb +54 -0
- data/spec/integration/body_parser/text_parser_spec.rb +43 -0
- data/spec/integration/concurrent_processing/concurrent_processing_spec.rb +45 -0
- data/spec/integration/custom_group_polling_strategy/custom_group_polling_strategy_spec.rb +87 -0
- data/spec/integration/dead_letter_queue/dead_letter_queue_spec.rb +91 -0
- data/spec/integration/exception_handlers/exception_handlers_spec.rb +69 -0
- data/spec/integration/exponential_backoff/exponential_backoff_spec.rb +67 -0
- data/spec/integration/fifo_ordering/fifo_ordering_spec.rb +44 -0
- data/spec/integration/large_payloads/large_payloads_spec.rb +30 -0
- data/spec/integration/launcher/launcher_spec.rb +40 -0
- data/spec/integration/message_attributes/message_attributes_spec.rb +54 -0
- data/spec/integration/message_operations/message_operations_spec.rb +59 -0
- data/spec/integration/middleware_chain/empty_chain_spec.rb +11 -0
- data/spec/integration/middleware_chain/execution_order_spec.rb +33 -0
- data/spec/integration/middleware_chain/removal_spec.rb +31 -0
- data/spec/integration/middleware_chain/short_circuit_spec.rb +40 -0
- data/spec/integration/non_retryable_exception/non_retryable_exception_spec.rb +149 -0
- data/spec/integration/polling_strategies/polling_strategies_spec.rb +46 -0
- data/spec/integration/queue_operations/queue_operations_spec.rb +84 -0
- data/spec/integration/rails/rails_72/Gemfile +6 -0
- data/spec/integration/rails/rails_72/activejob_adapter_spec.rb +98 -0
- data/spec/integration/rails/rails_80/Gemfile +6 -0
- data/spec/integration/rails/rails_80/activejob_adapter_spec.rb +98 -0
- data/spec/integration/rails/rails_80/continuation_spec.rb +79 -0
- data/spec/integration/rails/rails_81/Gemfile +6 -0
- data/spec/integration/rails/rails_81/activejob_adapter_spec.rb +98 -0
- data/spec/integration/rails/rails_81/continuation_spec.rb +79 -0
- data/spec/integration/retry_behavior/retry_behavior_spec.rb +45 -0
- data/spec/integration/spec_helper.rb +7 -0
- data/spec/integration/strict_priority_polling/strict_priority_polling_spec.rb +58 -0
- data/spec/integration/visibility_timeout/visibility_timeout_spec.rb +37 -0
- data/spec/integration/worker_enqueueing/worker_enqueueing_spec.rb +60 -0
- data/spec/integration/worker_groups/worker_groups_spec.rb +79 -0
- data/spec/integration/worker_lifecycle/worker_lifecycle_spec.rb +33 -0
- data/spec/integrations_helper.rb +243 -0
- data/spec/lib/active_job/extensions_spec.rb +225 -0
- data/spec/lib/active_job/queue_adapters/shoryuken_adapter_spec.rb +29 -0
- data/spec/{shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb → lib/active_job/queue_adapters/shoryuken_concurrent_send_adapter_spec.rb} +5 -4
- data/spec/{shoryuken/extensions/active_job_wrapper_spec.rb → lib/shoryuken/active_job/job_wrapper_spec.rb} +6 -5
- data/spec/{shoryuken → lib/shoryuken}/body_parser_spec.rb +2 -4
- data/spec/{shoryuken → lib/shoryuken}/client_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/default_exception_handler_spec.rb +9 -10
- data/spec/{shoryuken → lib/shoryuken}/default_worker_registry_spec.rb +1 -2
- data/spec/{shoryuken → lib/shoryuken}/environment_loader_spec.rb +10 -9
- data/spec/{shoryuken → lib/shoryuken}/fetcher_spec.rb +23 -26
- data/spec/lib/shoryuken/helpers/atomic_boolean_spec.rb +196 -0
- data/spec/lib/shoryuken/helpers/atomic_counter_spec.rb +177 -0
- data/spec/lib/shoryuken/helpers/atomic_hash_spec.rb +307 -0
- data/spec/lib/shoryuken/helpers/hash_utils_spec.rb +145 -0
- data/spec/lib/shoryuken/helpers/string_utils_spec.rb +124 -0
- data/spec/lib/shoryuken/helpers/timer_task_spec.rb +298 -0
- data/spec/lib/shoryuken/helpers_integration_spec.rb +96 -0
- data/spec/lib/shoryuken/inline_message_spec.rb +196 -0
- data/spec/{shoryuken → lib/shoryuken}/launcher_spec.rb +23 -2
- data/spec/lib/shoryuken/logging_spec.rb +242 -0
- data/spec/{shoryuken → lib/shoryuken}/manager_spec.rb +1 -2
- data/spec/lib/shoryuken/message_spec.rb +109 -0
- data/spec/{shoryuken → lib/shoryuken}/middleware/chain_spec.rb +1 -1
- data/spec/lib/shoryuken/middleware/entry_spec.rb +68 -0
- data/spec/lib/shoryuken/middleware/server/active_record_spec.rb +133 -0
- data/spec/{shoryuken → lib/shoryuken}/middleware/server/auto_delete_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/middleware/server/auto_extend_visibility_spec.rb +51 -1
- data/spec/{shoryuken → lib/shoryuken}/middleware/server/exponential_backoff_retry_spec.rb +1 -1
- data/spec/lib/shoryuken/middleware/server/non_retryable_exception_spec.rb +214 -0
- data/spec/{shoryuken → lib/shoryuken}/middleware/server/timing_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/options_spec.rb +49 -6
- data/spec/lib/shoryuken/polling/base_strategy_spec.rb +280 -0
- data/spec/lib/shoryuken/polling/queue_configuration_spec.rb +195 -0
- data/spec/{shoryuken → lib/shoryuken}/polling/strict_priority_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/polling/weighted_round_robin_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/processor_spec.rb +1 -1
- data/spec/{shoryuken → lib/shoryuken}/queue_spec.rb +2 -3
- data/spec/{shoryuken → lib/shoryuken}/runner_spec.rb +1 -3
- data/spec/{shoryuken → lib/shoryuken}/util_spec.rb +2 -2
- data/spec/lib/shoryuken/version_spec.rb +17 -0
- data/spec/{shoryuken → lib/shoryuken}/worker/default_executor_spec.rb +1 -1
- data/spec/lib/shoryuken/worker/inline_executor_spec.rb +105 -0
- data/spec/lib/shoryuken/worker_registry_spec.rb +63 -0
- data/spec/{shoryuken → lib/shoryuken}/worker_spec.rb +15 -11
- data/spec/{shoryuken_spec.rb → lib/shoryuken_spec.rb} +1 -1
- data/spec/shared_examples_for_active_job.rb +40 -15
- data/spec/spec_helper.rb +48 -2
- metadata +295 -101
- data/.codeclimate.yml +0 -20
- data/.devcontainer/Dockerfile +0 -17
- data/.devcontainer/base.Dockerfile +0 -43
- data/.devcontainer/devcontainer.json +0 -35
- data/.github/FUNDING.yml +0 -12
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/stale.yml +0 -20
- data/.reek.yml +0 -5
- data/Appraisals +0 -42
- data/gemfiles/.gitignore +0 -1
- data/gemfiles/aws_sdk_core_2.gemfile +0 -21
- data/gemfiles/rails_4_2.gemfile +0 -20
- data/gemfiles/rails_5_2.gemfile +0 -21
- data/gemfiles/rails_6_0.gemfile +0 -21
- data/gemfiles/rails_6_1.gemfile +0 -21
- data/gemfiles/rails_7_0.gemfile +0 -22
- data/lib/shoryuken/core_ext.rb +0 -69
- data/lib/shoryuken/extensions/active_job_adapter.rb +0 -103
- data/lib/shoryuken/extensions/active_job_concurrent_send_adapter.rb +0 -50
- data/lib/shoryuken/polling/base.rb +0 -67
- data/shoryuken.jpg +0 -0
- data/spec/integration/launcher_spec.rb +0 -128
- data/spec/shoryuken/core_ext_spec.rb +0 -40
- data/spec/shoryuken/extensions/active_job_adapter_spec.rb +0 -7
- data/spec/shoryuken/extensions/active_job_base_spec.rb +0 -84
- data/spec/shoryuken/worker/inline_executor_spec.rb +0 -49
data/.github/workflows/stale.yml
DELETED
|
@@ -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
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: "../"
|
data/gemfiles/rails_4_2.gemfile
DELETED
|
@@ -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: "../"
|
data/gemfiles/rails_5_2.gemfile
DELETED
|
@@ -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: "../"
|
data/gemfiles/rails_6_0.gemfile
DELETED
|
@@ -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: "../"
|
data/gemfiles/rails_6_1.gemfile
DELETED
|
@@ -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: "../"
|
data/gemfiles/rails_7_0.gemfile
DELETED
|
@@ -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: "../"
|
data/lib/shoryuken/core_ext.rb
DELETED
|
@@ -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
|