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
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shoryuken
|
|
4
|
+
module Middleware
|
|
5
|
+
# Represents an entry in a middleware chain, storing the middleware class
|
|
6
|
+
# and any arguments needed for its instantiation.
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
class Entry
|
|
10
|
+
# @return [Class] The middleware class this entry represents
|
|
11
|
+
attr_reader :klass
|
|
12
|
+
|
|
13
|
+
# Creates a new middleware entry.
|
|
14
|
+
#
|
|
15
|
+
# @param klass [Class] The middleware class
|
|
16
|
+
# @param args [Array] Arguments to pass to the middleware constructor
|
|
17
|
+
def initialize(klass, *args)
|
|
18
|
+
@klass = klass
|
|
19
|
+
@args = args
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Creates a new instance of the middleware class with the stored arguments.
|
|
23
|
+
#
|
|
24
|
+
# @return [Object] A new instance of the middleware class
|
|
25
|
+
def make_new
|
|
26
|
+
@klass.new(*@args)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
2
4
|
module Middleware
|
|
5
|
+
# Server-side middleware that runs around message processing
|
|
3
6
|
module Server
|
|
7
|
+
# Middleware that clears ActiveRecord connections after message processing.
|
|
8
|
+
# Ensures database connections are returned to the pool after each job.
|
|
4
9
|
class ActiveRecord
|
|
10
|
+
# Processes a message and clears database connections afterwards
|
|
11
|
+
#
|
|
12
|
+
# @param _args [Array<Object>] middleware call arguments (unused)
|
|
13
|
+
# @yield continues to the next middleware in the chain
|
|
14
|
+
# @return [Object] return value from the next middleware or worker in the chain
|
|
5
15
|
def call(*_args)
|
|
6
16
|
yield
|
|
7
17
|
ensure
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
2
4
|
module Middleware
|
|
3
5
|
module Server
|
|
6
|
+
# Middleware that automatically deletes messages after successful processing.
|
|
7
|
+
# Only deletes messages when the worker has auto_delete enabled.
|
|
4
8
|
class AutoDelete
|
|
9
|
+
# Processes a message and deletes it if auto_delete is enabled
|
|
10
|
+
#
|
|
11
|
+
# @param worker [Object] the worker instance
|
|
12
|
+
# @param queue [String] the queue name
|
|
13
|
+
# @param sqs_msg [Shoryuken::Message, Array<Shoryuken::Message>] the message or batch
|
|
14
|
+
# @param _body [Object] the parsed message body (unused)
|
|
15
|
+
# @yield continues to the next middleware in the chain
|
|
16
|
+
# @return [void]
|
|
5
17
|
def call(worker, queue, sqs_msg, _body)
|
|
6
18
|
yield
|
|
7
19
|
|
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
2
4
|
module Middleware
|
|
3
5
|
module Server
|
|
6
|
+
# Middleware that automatically extends message visibility timeout during processing.
|
|
7
|
+
# Prevents messages from becoming visible to other consumers while still being processed.
|
|
4
8
|
class AutoExtendVisibility
|
|
5
9
|
include Util
|
|
6
10
|
|
|
11
|
+
# Number of seconds before timeout to extend visibility
|
|
7
12
|
EXTEND_UPFRONT_SECONDS = 5
|
|
8
13
|
|
|
14
|
+
# Processes a message with automatic visibility timeout extension
|
|
15
|
+
#
|
|
16
|
+
# @param worker [Object] the worker instance
|
|
17
|
+
# @param queue [String] the queue name
|
|
18
|
+
# @param sqs_msg [Shoryuken::Message, Array<Shoryuken::Message>] the message or batch
|
|
19
|
+
# @param body [Object] the parsed message body
|
|
20
|
+
# @yield continues to the next middleware in the chain
|
|
21
|
+
# @return [void]
|
|
9
22
|
def call(worker, queue, sqs_msg, body)
|
|
10
23
|
return yield unless worker.class.auto_visibility_timeout?
|
|
11
24
|
|
|
@@ -22,28 +35,41 @@ module Shoryuken
|
|
|
22
35
|
|
|
23
36
|
private
|
|
24
37
|
|
|
38
|
+
# Helper class for extending message visibility
|
|
25
39
|
class MessageVisibilityExtender
|
|
26
40
|
include Util
|
|
27
41
|
|
|
42
|
+
# Creates a timer task that extends message visibility
|
|
43
|
+
#
|
|
44
|
+
# @param _worker [Object] the worker instance (unused)
|
|
45
|
+
# @param queue [String] the queue name
|
|
46
|
+
# @param sqs_msg [Shoryuken::Message] the message
|
|
47
|
+
# @param _body [Object] the parsed message body (unused)
|
|
48
|
+
# @return [Shoryuken::Helpers::TimerTask] the timer task
|
|
28
49
|
def auto_extend(_worker, queue, sqs_msg, _body)
|
|
29
50
|
queue_visibility_timeout = Shoryuken::Client.queues(queue).visibility_timeout
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"Could not auto extend the message #{queue}/#{sqs_msg.message_id} visibility timeout. Error: #{ex.message}"
|
|
41
|
-
end
|
|
52
|
+
Shoryuken::Helpers::TimerTask.new(execution_interval: queue_visibility_timeout - EXTEND_UPFRONT_SECONDS) do
|
|
53
|
+
logger.debug do
|
|
54
|
+
"Extending message #{queue}/#{sqs_msg.message_id} visibility timeout by #{queue_visibility_timeout}s"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
sqs_msg.change_visibility(visibility_timeout: queue_visibility_timeout)
|
|
58
|
+
rescue => e
|
|
59
|
+
logger.error do
|
|
60
|
+
"Could not auto extend the message #{queue}/#{sqs_msg.message_id} visibility timeout. Error: #{e.message}"
|
|
42
61
|
end
|
|
43
62
|
end
|
|
44
63
|
end
|
|
45
64
|
end
|
|
46
65
|
|
|
66
|
+
# Creates and starts a visibility extension timer
|
|
67
|
+
#
|
|
68
|
+
# @param worker [Object] the worker instance
|
|
69
|
+
# @param queue [String] the queue name
|
|
70
|
+
# @param sqs_msg [Shoryuken::Message] the message
|
|
71
|
+
# @param body [Object] the parsed message body
|
|
72
|
+
# @return [Shoryuken::Helpers::TimerTask] the started timer
|
|
47
73
|
def auto_visibility_timer(worker, queue, sqs_msg, body)
|
|
48
74
|
MessageVisibilityExtender.new.auto_extend(worker, queue, sqs_msg, body).tap(&:execute)
|
|
49
75
|
end
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
2
4
|
module Middleware
|
|
3
5
|
module Server
|
|
6
|
+
# Middleware that implements exponential backoff retry for failed messages.
|
|
7
|
+
# When a job fails, the message visibility timeout is adjusted based on
|
|
8
|
+
# configured retry intervals.
|
|
4
9
|
class ExponentialBackoffRetry
|
|
5
10
|
include Util
|
|
6
11
|
|
|
12
|
+
# Processes a message with exponential backoff retry on failure
|
|
13
|
+
#
|
|
14
|
+
# @param worker [Object] the worker instance
|
|
15
|
+
# @param _queue [String] the queue name (unused)
|
|
16
|
+
# @param sqs_msg [Shoryuken::Message, Array<Shoryuken::Message>] the message or batch
|
|
17
|
+
# @param _body [Object] the parsed message body (unused)
|
|
18
|
+
# @yield continues to the next middleware in the chain
|
|
19
|
+
# @return [void]
|
|
20
|
+
# @raise [StandardError] re-raises the original exception if retry intervals are not configured
|
|
21
|
+
# or if retry limit is exceeded
|
|
7
22
|
def call(worker, _queue, sqs_msg, _body)
|
|
8
23
|
return yield unless worker.class.exponential_backoff?
|
|
9
24
|
|
|
@@ -14,7 +29,7 @@ module Shoryuken
|
|
|
14
29
|
|
|
15
30
|
started_at = Time.now
|
|
16
31
|
yield
|
|
17
|
-
rescue =>
|
|
32
|
+
rescue => e
|
|
18
33
|
retry_intervals = worker.class.get_shoryuken_options['retry_intervals']
|
|
19
34
|
|
|
20
35
|
if retry_intervals.nil? || !handle_failure(sqs_msg, started_at, retry_intervals)
|
|
@@ -23,13 +38,18 @@ module Shoryuken
|
|
|
23
38
|
raise
|
|
24
39
|
end
|
|
25
40
|
|
|
26
|
-
logger.warn { "Message #{sqs_msg.message_id} will attempt retry due to error: #{
|
|
41
|
+
logger.warn { "Message #{sqs_msg.message_id} will attempt retry due to error: #{e.message}" }
|
|
27
42
|
# since we didn't raise, lets log the backtrace for debugging purposes.
|
|
28
|
-
logger.debug {
|
|
43
|
+
logger.debug { e.backtrace.join("\n") } unless e.backtrace.nil?
|
|
29
44
|
end
|
|
30
45
|
|
|
31
46
|
private
|
|
32
47
|
|
|
48
|
+
# Gets the retry interval for a given attempt number
|
|
49
|
+
#
|
|
50
|
+
# @param retry_intervals [Array<Integer>, #call] the configured intervals or callable
|
|
51
|
+
# @param attempts [Integer] the current attempt number
|
|
52
|
+
# @return [Integer, nil] the interval in seconds or nil
|
|
33
53
|
def get_interval(retry_intervals, attempts)
|
|
34
54
|
return retry_intervals.call(attempts) if retry_intervals.respond_to?(:call)
|
|
35
55
|
|
|
@@ -40,12 +60,23 @@ module Shoryuken
|
|
|
40
60
|
end
|
|
41
61
|
end
|
|
42
62
|
|
|
63
|
+
# Calculates the next visibility timeout capped at SQS maximum
|
|
64
|
+
#
|
|
65
|
+
# @param interval [Integer] the desired interval
|
|
66
|
+
# @param started_at [Time] when processing started
|
|
67
|
+
# @return [Integer] the capped visibility timeout
|
|
43
68
|
def next_visibility_timeout(interval, started_at)
|
|
44
69
|
max_timeout = 43_200 - (Time.now - started_at).ceil - 1
|
|
45
70
|
interval = max_timeout if interval > max_timeout
|
|
46
71
|
interval.to_i
|
|
47
72
|
end
|
|
48
73
|
|
|
74
|
+
# Handles a message failure by adjusting visibility timeout
|
|
75
|
+
#
|
|
76
|
+
# @param sqs_msg [Shoryuken::Message] the failed message
|
|
77
|
+
# @param started_at [Time] when processing started
|
|
78
|
+
# @param retry_intervals [Array<Integer>, #call] the configured intervals
|
|
79
|
+
# @return [Boolean] true if retry was scheduled, false otherwise
|
|
49
80
|
def handle_failure(sqs_msg, started_at, retry_intervals)
|
|
50
81
|
receive_count = sqs_msg.attributes['ApproximateReceiveCount'].to_i
|
|
51
82
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shoryuken
|
|
4
|
+
module Middleware
|
|
5
|
+
module Server
|
|
6
|
+
# Middleware that handles non-retryable exceptions by deleting messages immediately.
|
|
7
|
+
# When a configured exception occurs, the message is deleted instead of being retried.
|
|
8
|
+
#
|
|
9
|
+
# Configure non-retryable exceptions per worker:
|
|
10
|
+
#
|
|
11
|
+
# class MyWorker
|
|
12
|
+
# include Shoryuken::Worker
|
|
13
|
+
#
|
|
14
|
+
# # Using exception classes
|
|
15
|
+
# shoryuken_options queue: 'my_queue',
|
|
16
|
+
# non_retryable_exceptions: [InvalidInputError, RecordNotFoundError]
|
|
17
|
+
#
|
|
18
|
+
# # Or using a lambda for dynamic classification
|
|
19
|
+
# shoryuken_options queue: 'my_queue',
|
|
20
|
+
# non_retryable_exceptions: ->(error) {
|
|
21
|
+
# error.is_a?(StandardError) && error.message.include?('permanent')
|
|
22
|
+
# }
|
|
23
|
+
#
|
|
24
|
+
# def perform(sqs_msg, body)
|
|
25
|
+
# # ...
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
class NonRetryableException
|
|
29
|
+
include Util
|
|
30
|
+
|
|
31
|
+
# Processes a message and handles non-retryable exceptions
|
|
32
|
+
#
|
|
33
|
+
# @param worker [Object] the worker instance
|
|
34
|
+
# @param queue [String] the queue name
|
|
35
|
+
# @param sqs_msg [Shoryuken::Message, Array<Shoryuken::Message>] the message or batch
|
|
36
|
+
# @param _body [Object] the parsed message body (unused)
|
|
37
|
+
# @yield continues to the next middleware in the chain
|
|
38
|
+
# @return [void]
|
|
39
|
+
def call(worker, queue, sqs_msg, _body)
|
|
40
|
+
yield
|
|
41
|
+
rescue => e
|
|
42
|
+
non_retryable_exceptions = worker.class.get_shoryuken_options['non_retryable_exceptions']
|
|
43
|
+
|
|
44
|
+
return raise unless non_retryable_exceptions
|
|
45
|
+
|
|
46
|
+
if non_retryable_exceptions.respond_to?(:call)
|
|
47
|
+
return raise unless non_retryable_exceptions.call(e)
|
|
48
|
+
else
|
|
49
|
+
exception_classes = Array(non_retryable_exceptions)
|
|
50
|
+
return raise unless exception_classes.any? { |klass| e.is_a?(klass) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Handle batch messages
|
|
54
|
+
messages = sqs_msg.is_a?(Array) ? sqs_msg : [sqs_msg]
|
|
55
|
+
|
|
56
|
+
logger.warn do
|
|
57
|
+
"Non-retryable exception #{e.class} occurred for message(s) #{messages.map(&:message_id).join(', ')}. " \
|
|
58
|
+
"Deleting message(s) immediately. Error: #{e.message}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
logger.debug { e.backtrace.join("\n") } if e.backtrace
|
|
62
|
+
|
|
63
|
+
# Delete the message(s) immediately
|
|
64
|
+
entries = messages.map.with_index { |message, i| { id: i.to_s, receipt_handle: message.receipt_handle } }
|
|
65
|
+
|
|
66
|
+
begin
|
|
67
|
+
queue_client = Shoryuken::Client.queues(queue)
|
|
68
|
+
delete_failed = queue_client.delete_messages(entries: entries)
|
|
69
|
+
|
|
70
|
+
# Check if deletion reported failures (returns true if any failed)
|
|
71
|
+
if delete_failed
|
|
72
|
+
logger.warn do
|
|
73
|
+
'Failed to delete some messages for non-retryable exception on queue ' \
|
|
74
|
+
"'#{queue}'. " \
|
|
75
|
+
"Entries: #{entries.map { |e| { id: e[:id] } }.inspect}. " \
|
|
76
|
+
'Some messages may remain in the queue and could be reprocessed.'
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
rescue => delete_error
|
|
80
|
+
logger.error do
|
|
81
|
+
'Error deleting messages for non-retryable exception on queue ' \
|
|
82
|
+
"'#{queue}': #{delete_error.class} - #{delete_error.message}. " \
|
|
83
|
+
"Entries: #{entries.map { |e| { id: e[:id] } }.inspect}. " \
|
|
84
|
+
'Messages may remain in the queue and could be reprocessed.'
|
|
85
|
+
end
|
|
86
|
+
logger.debug { delete_error.backtrace.join("\n") } if delete_error.backtrace
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Don't re-raise - the exception has been handled by deleting the message
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
2
4
|
module Middleware
|
|
3
5
|
module Server
|
|
6
|
+
# Middleware that logs timing information for message processing.
|
|
7
|
+
# Records start time, completion time, and warns if processing
|
|
8
|
+
# exceeds the queue's visibility timeout.
|
|
4
9
|
class Timing
|
|
5
10
|
include Util
|
|
6
11
|
|
|
12
|
+
# Processes a message while logging timing information
|
|
13
|
+
#
|
|
14
|
+
# @param _worker [Object] the worker instance (unused)
|
|
15
|
+
# @param queue [String] the queue name
|
|
16
|
+
# @param _sqs_msg [Shoryuken::Message] the message being processed (unused)
|
|
17
|
+
# @param _body [Object] the parsed message body (unused)
|
|
18
|
+
# @yield continues to the next middleware in the chain
|
|
19
|
+
# @return [void]
|
|
7
20
|
def call(_worker, queue, _sqs_msg, _body)
|
|
8
21
|
started_at = Time.now
|
|
9
22
|
|
data/lib/shoryuken/options.rb
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Shoryuken
|
|
4
|
+
# Stores and manages all Shoryuken configuration options.
|
|
5
|
+
# This class is used internally to hold settings for workers, queues,
|
|
6
|
+
# middleware, and other runtime configurations.
|
|
2
7
|
class Options
|
|
8
|
+
# Default configuration values for Shoryuken
|
|
3
9
|
DEFAULTS = {
|
|
10
|
+
thread_priority: -1,
|
|
4
11
|
concurrency: 25,
|
|
5
12
|
queues: [],
|
|
6
13
|
aws: {},
|
|
@@ -16,12 +23,31 @@ module Shoryuken
|
|
|
16
23
|
}
|
|
17
24
|
}.freeze
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
# @return [Boolean] whether to enable ActiveJob queue name prefixing
|
|
27
|
+
# @return [Boolean] whether to cache SQS visibility timeout
|
|
28
|
+
# @return [Hash{String => Hash}] the configured processing groups
|
|
29
|
+
# @return [Object] the executor used to launch workers
|
|
30
|
+
# @return [Proc] the code reloader proc for development environments
|
|
31
|
+
# @return [Boolean] whether code reloading is enabled
|
|
32
|
+
# @return [Proc, nil] callback to execute when server starts
|
|
33
|
+
# @return [Proc, nil] callback to execute when server stops
|
|
34
|
+
# @return [Class] the executor class for running workers
|
|
35
|
+
# @return [Shoryuken::WorkerRegistry] the registry for worker classes
|
|
36
|
+
# @return [Array<#call>] handlers for processing exceptions
|
|
37
|
+
attr_accessor :active_job_queue_name_prefixing, :cache_visibility_timeout,
|
|
38
|
+
:groups, :launcher_executor, :reloader, :enable_reloading,
|
|
39
|
+
:start_callback, :stop_callback, :worker_executor, :worker_registry,
|
|
40
|
+
:exception_handlers
|
|
41
|
+
|
|
42
|
+
# @return [Hash] the default options for workers
|
|
43
|
+
# @return [Aws::SQS::Client] the SQS client instance
|
|
44
|
+
# @return [Logger] the logger instance
|
|
45
|
+
attr_writer :default_worker_options, :sqs_client, :logger
|
|
46
|
+
|
|
47
|
+
# @return [Hash] options passed to SQS receive_message calls
|
|
23
48
|
attr_reader :sqs_client_receive_message_opts
|
|
24
49
|
|
|
50
|
+
# Initializes a new Options instance with default values
|
|
25
51
|
def initialize
|
|
26
52
|
self.groups = {}
|
|
27
53
|
self.worker_registry = DefaultWorkerRegistry.new
|
|
@@ -35,33 +61,63 @@ module Shoryuken
|
|
|
35
61
|
@sqs_client_receive_message_opts ||= {}
|
|
36
62
|
end
|
|
37
63
|
|
|
64
|
+
# Checks if ActiveJob is available
|
|
65
|
+
#
|
|
66
|
+
# @return [Boolean] true if ActiveJob is defined
|
|
38
67
|
def active_job?
|
|
39
68
|
defined?(::ActiveJob)
|
|
40
69
|
end
|
|
41
70
|
|
|
42
|
-
|
|
71
|
+
# Adds a processing group with the specified concurrency and delay
|
|
72
|
+
#
|
|
73
|
+
# @param group [String] the name of the group
|
|
74
|
+
# @param concurrency [Integer, nil] the number of concurrent workers for the group
|
|
75
|
+
# @param delay [Float, nil] the delay between polling cycles
|
|
76
|
+
# @param polling_strategy [Class, String, nil] the polling strategy class for the group
|
|
77
|
+
# @return [Hash] the group configuration
|
|
78
|
+
# @raise [Errors::InvalidPollingStrategyError] if polling_strategy is not a Class, String, or nil
|
|
79
|
+
def add_group(group, concurrency = nil, delay: nil, polling_strategy: nil)
|
|
80
|
+
unless polling_strategy.nil? || polling_strategy.is_a?(Class) || polling_strategy.is_a?(String)
|
|
81
|
+
raise Errors::InvalidPollingStrategyError, "#{polling_strategy} is not a valid polling_strategy"
|
|
82
|
+
end
|
|
83
|
+
|
|
43
84
|
concurrency ||= options[:concurrency]
|
|
44
85
|
delay ||= options[:delay]
|
|
45
86
|
|
|
46
87
|
groups[group] ||= {
|
|
47
88
|
concurrency: concurrency,
|
|
48
89
|
delay: delay,
|
|
90
|
+
polling_strategy: polling_strategy,
|
|
49
91
|
queues: []
|
|
50
92
|
}
|
|
51
93
|
end
|
|
52
94
|
|
|
95
|
+
# Adds a queue to a processing group with the specified weight
|
|
96
|
+
#
|
|
97
|
+
# @param queue [String] the name of the queue
|
|
98
|
+
# @param weight [Integer] the weight (priority) of the queue
|
|
99
|
+
# @param group [String] the name of the group to add the queue to
|
|
100
|
+
# @return [void]
|
|
53
101
|
def add_queue(queue, weight, group)
|
|
54
102
|
weight.times do
|
|
55
103
|
groups[group][:queues] << queue
|
|
56
104
|
end
|
|
57
105
|
end
|
|
58
106
|
|
|
107
|
+
# Returns all queues from all groups
|
|
108
|
+
#
|
|
109
|
+
# @return [Array<String>] flat array of all queue names
|
|
59
110
|
def ungrouped_queues
|
|
60
111
|
groups.values.flat_map { |options| options[:queues] }
|
|
61
112
|
end
|
|
62
113
|
|
|
114
|
+
# Returns the polling strategy class for a group
|
|
115
|
+
#
|
|
116
|
+
# @param group [String] the name of the group
|
|
117
|
+
# @return [Class] the polling strategy class to use
|
|
63
118
|
def polling_strategy(group)
|
|
64
|
-
strategy =
|
|
119
|
+
strategy = groups[group].to_h[:polling_strategy] ||
|
|
120
|
+
(group == 'default' ? options : options[:groups].to_h[group]).to_h[:polling_strategy]
|
|
65
121
|
case strategy
|
|
66
122
|
when 'WeightedRoundRobin', nil # Default case
|
|
67
123
|
Polling::WeightedRoundRobin
|
|
@@ -71,57 +127,111 @@ module Shoryuken
|
|
|
71
127
|
begin
|
|
72
128
|
Object.const_get(strategy)
|
|
73
129
|
rescue NameError
|
|
74
|
-
raise
|
|
130
|
+
raise Errors::InvalidPollingStrategyError, "#{strategy} is not a valid polling_strategy"
|
|
75
131
|
end
|
|
76
132
|
when Class
|
|
77
133
|
strategy
|
|
78
134
|
end
|
|
79
135
|
end
|
|
80
136
|
|
|
137
|
+
# Returns the polling delay for a group
|
|
138
|
+
#
|
|
139
|
+
# @param group [String] the name of the group
|
|
140
|
+
# @return [Float] the delay in seconds
|
|
81
141
|
def delay(group)
|
|
82
142
|
groups[group].to_h.fetch(:delay, options[:delay]).to_f
|
|
83
143
|
end
|
|
84
144
|
|
|
145
|
+
# Returns the SQS client, initializing a default one if needed.
|
|
146
|
+
# Uses AWS configuration from options[:aws] if available.
|
|
147
|
+
#
|
|
148
|
+
# @return [Aws::SQS::Client] the SQS client
|
|
85
149
|
def sqs_client
|
|
86
|
-
@sqs_client ||= Aws::SQS::Client.new
|
|
150
|
+
@sqs_client ||= Aws::SQS::Client.new(options[:aws])
|
|
87
151
|
end
|
|
88
152
|
|
|
153
|
+
# Sets the SQS client receive message options for the default group
|
|
154
|
+
#
|
|
155
|
+
# @param sqs_client_receive_message_opts [Hash] the options hash
|
|
156
|
+
# @return [Hash] the options hash
|
|
89
157
|
def sqs_client_receive_message_opts=(sqs_client_receive_message_opts)
|
|
90
158
|
@sqs_client_receive_message_opts['default'] = sqs_client_receive_message_opts
|
|
91
159
|
end
|
|
92
160
|
|
|
161
|
+
# Returns the global options hash
|
|
162
|
+
#
|
|
163
|
+
# @return [Hash] the options hash
|
|
93
164
|
def options
|
|
94
165
|
@options ||= DEFAULTS.dup
|
|
95
166
|
end
|
|
96
167
|
|
|
168
|
+
# Returns the logger instance
|
|
169
|
+
#
|
|
170
|
+
# @return [Logger] the logger
|
|
97
171
|
def logger
|
|
98
|
-
Shoryuken::Logging.logger
|
|
172
|
+
@logger ||= Shoryuken::Logging.logger
|
|
99
173
|
end
|
|
100
174
|
|
|
175
|
+
# Returns the thread priority setting
|
|
176
|
+
#
|
|
177
|
+
# @return [Integer] the thread priority
|
|
178
|
+
def thread_priority
|
|
179
|
+
@thread_priority ||= options[:thread_priority]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Sets the thread priority
|
|
183
|
+
#
|
|
184
|
+
# @param value [Integer] the thread priority value
|
|
185
|
+
# @return [Integer] the thread priority
|
|
186
|
+
attr_writer :thread_priority
|
|
187
|
+
|
|
188
|
+
# Registers a worker class with the worker registry
|
|
189
|
+
#
|
|
190
|
+
# @param args [Array] arguments to pass to the registry
|
|
191
|
+
# @return [void]
|
|
101
192
|
def register_worker(*args)
|
|
102
193
|
worker_registry.register_worker(*args)
|
|
103
194
|
end
|
|
104
195
|
|
|
196
|
+
# Yields self if running as a server for server-specific configuration
|
|
197
|
+
#
|
|
198
|
+
# @yield [Shoryuken::Options] the options instance
|
|
199
|
+
# @return [void]
|
|
105
200
|
def configure_server
|
|
106
201
|
yield self if server?
|
|
107
202
|
end
|
|
108
203
|
|
|
204
|
+
# Returns the server middleware chain
|
|
205
|
+
#
|
|
206
|
+
# @yield [Shoryuken::Middleware::Chain] the middleware chain for configuration
|
|
207
|
+
# @return [Shoryuken::Middleware::Chain] the server middleware chain
|
|
109
208
|
def server_middleware
|
|
110
209
|
@_server_chain ||= default_server_middleware
|
|
111
210
|
yield @_server_chain if block_given?
|
|
112
211
|
@_server_chain
|
|
113
212
|
end
|
|
114
213
|
|
|
214
|
+
# Yields self unless running as a server for client-specific configuration
|
|
215
|
+
#
|
|
216
|
+
# @yield [Shoryuken::Options] the options instance
|
|
217
|
+
# @return [void]
|
|
115
218
|
def configure_client
|
|
116
219
|
yield self unless server?
|
|
117
220
|
end
|
|
118
221
|
|
|
222
|
+
# Returns the client middleware chain
|
|
223
|
+
#
|
|
224
|
+
# @yield [Shoryuken::Middleware::Chain] the middleware chain for configuration
|
|
225
|
+
# @return [Shoryuken::Middleware::Chain] the client middleware chain
|
|
119
226
|
def client_middleware
|
|
120
227
|
@_client_chain ||= default_client_middleware
|
|
121
228
|
yield @_client_chain if block_given?
|
|
122
229
|
@_client_chain
|
|
123
230
|
end
|
|
124
231
|
|
|
232
|
+
# Returns the default worker options hash
|
|
233
|
+
#
|
|
234
|
+
# @return [Hash{String => Object}] the default worker options
|
|
125
235
|
def default_worker_options
|
|
126
236
|
@default_worker_options ||= {
|
|
127
237
|
'queue' => 'default',
|
|
@@ -133,46 +243,74 @@ module Shoryuken
|
|
|
133
243
|
}
|
|
134
244
|
end
|
|
135
245
|
|
|
246
|
+
# Registers a callback to run when the server starts
|
|
247
|
+
#
|
|
248
|
+
# @param block [Proc] the block to execute on start
|
|
249
|
+
# @return [void]
|
|
250
|
+
# @yield the block to execute on start
|
|
136
251
|
def on_start(&block)
|
|
137
252
|
self.start_callback = block
|
|
138
253
|
end
|
|
139
254
|
|
|
255
|
+
# Registers a callback to run when the server stops
|
|
256
|
+
#
|
|
257
|
+
# @param block [Proc] the block to execute on stop
|
|
258
|
+
# @return [void]
|
|
259
|
+
# @yield the block to execute on stop
|
|
140
260
|
def on_stop(&block)
|
|
141
261
|
self.stop_callback = block
|
|
142
262
|
end
|
|
143
263
|
|
|
144
|
-
#
|
|
145
|
-
# :startup, :quiet, :shutdown or :stopped are valid events.
|
|
264
|
+
# Registers a block to run at a point in the Shoryuken lifecycle.
|
|
146
265
|
#
|
|
266
|
+
# @param event [Symbol] the lifecycle event (:startup, :quiet, :shutdown, or :stopped)
|
|
267
|
+
# @param block [Proc] the block to execute for the event
|
|
268
|
+
# @return [void]
|
|
269
|
+
# @raise [ArgumentError] if event is not a Symbol or not a valid event name
|
|
270
|
+
# @yield the block to execute for the event
|
|
271
|
+
# @example
|
|
147
272
|
# Shoryuken.configure_server do |config|
|
|
148
273
|
# config.on(:shutdown) do
|
|
149
274
|
# puts "Goodbye cruel world!"
|
|
150
275
|
# end
|
|
151
276
|
# end
|
|
152
277
|
def on(event, &block)
|
|
153
|
-
|
|
154
|
-
|
|
278
|
+
raise Errors::InvalidEventError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
|
279
|
+
raise Errors::InvalidEventError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
|
155
280
|
|
|
156
281
|
options[:lifecycle_events][event] << block
|
|
157
282
|
end
|
|
158
283
|
|
|
284
|
+
# Checks if running as a server (CLI mode)
|
|
285
|
+
#
|
|
286
|
+
# @return [Boolean] true if Shoryuken::CLI is defined
|
|
159
287
|
def server?
|
|
160
288
|
defined?(Shoryuken::CLI)
|
|
161
289
|
end
|
|
162
290
|
|
|
291
|
+
# Checks if visibility timeout caching is enabled
|
|
292
|
+
#
|
|
293
|
+
# @return [Boolean] true if caching is enabled
|
|
163
294
|
def cache_visibility_timeout?
|
|
164
295
|
@cache_visibility_timeout
|
|
165
296
|
end
|
|
166
297
|
|
|
298
|
+
# Checks if ActiveJob queue name prefixing is enabled
|
|
299
|
+
#
|
|
300
|
+
# @return [Boolean] true if prefixing is enabled
|
|
167
301
|
def active_job_queue_name_prefixing?
|
|
168
302
|
@active_job_queue_name_prefixing
|
|
169
303
|
end
|
|
170
304
|
|
|
171
305
|
private
|
|
172
306
|
|
|
307
|
+
# Creates the default server middleware chain
|
|
308
|
+
#
|
|
309
|
+
# @return [Shoryuken::Middleware::Chain] the default middleware chain
|
|
173
310
|
def default_server_middleware
|
|
174
311
|
Middleware::Chain.new do |m|
|
|
175
312
|
m.add Middleware::Server::Timing
|
|
313
|
+
m.add Middleware::Server::NonRetryableException
|
|
176
314
|
m.add Middleware::Server::ExponentialBackoffRetry
|
|
177
315
|
m.add Middleware::Server::AutoDelete
|
|
178
316
|
m.add Middleware::Server::AutoExtendVisibility
|
|
@@ -183,6 +321,9 @@ module Shoryuken
|
|
|
183
321
|
end
|
|
184
322
|
end
|
|
185
323
|
|
|
324
|
+
# Creates the default client middleware chain
|
|
325
|
+
#
|
|
326
|
+
# @return [Shoryuken::Middleware::Chain] an empty middleware chain
|
|
186
327
|
def default_client_middleware
|
|
187
328
|
Middleware::Chain.new
|
|
188
329
|
end
|