shoryuken 5.2.3 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +17 -0
- data/.devcontainer/base.Dockerfile +43 -0
- data/.devcontainer/devcontainer.json +35 -0
- data/.github/workflows/stale.yml +20 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +27 -0
- data/Gemfile +1 -1
- data/lib/shoryuken/environment_loader.rb +15 -3
- data/lib/shoryuken/launcher.rb +18 -0
- data/lib/shoryuken/manager.rb +27 -10
- data/lib/shoryuken/message.rb +11 -28
- data/lib/shoryuken/polling/strict_priority.rb +4 -2
- data/lib/shoryuken/polling/weighted_round_robin.rb +3 -5
- data/lib/shoryuken/runner.rb +4 -3
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken.rb +4 -0
- data/spec/shoryuken/environment_loader_spec.rb +42 -9
- data/spec/shoryuken/launcher_spec.rb +60 -0
- data/spec/shoryuken/manager_spec.rb +32 -6
- data/spec/shoryuken/polling/weighted_round_robin_spec.rb +31 -6
- data/spec/shoryuken/queue_spec.rb +10 -5
- data/spec/shoryuken/worker/default_executor_spec.rb +48 -48
- data/spec/shoryuken_spec.rb +9 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47b6564c21a283ca5d0cd71f7f59b36b9c99776a541b2a51c61a9fd5b590be08
|
4
|
+
data.tar.gz: cf94b4ba4d9b296e0af112704cbe0ecd201f57726c284c790351f79a23680c7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d037b9887326e63ba1c8659a56e7707cf07b7a1a7d9f5027df7fb759d2896035335bc877487a346d7cac59e7b1916a8f5dc967e4431445b1e7ca9f6778282f7b
|
7
|
+
data.tar.gz: 4e0dd25a40a86a09ea87b0187d7f9f3d8525031b40830b47b29b434b688459e60209d7f8e4adb7d6c5deeedfb63b4139bceb0e38762b7fbf0dab884c1023063c
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
|
2
|
+
ARG VARIANT=2-bullseye
|
3
|
+
FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}
|
4
|
+
|
5
|
+
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
|
6
|
+
ARG NODE_VERSION="none"
|
7
|
+
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
8
|
+
|
9
|
+
# [Optional] Uncomment this section to install additional OS packages.
|
10
|
+
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
11
|
+
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
12
|
+
|
13
|
+
# [Optional] Uncomment this line to install additional gems.
|
14
|
+
# RUN gem install <your-gem-names-here>
|
15
|
+
|
16
|
+
# [Optional] Uncomment this line to install global node packages.
|
17
|
+
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
|
2
|
+
ARG VARIANT=2-bullseye
|
3
|
+
FROM ruby:${VARIANT}
|
4
|
+
|
5
|
+
# Copy library scripts to execute
|
6
|
+
COPY library-scripts/*.sh library-scripts/*.env /tmp/library-scripts/
|
7
|
+
|
8
|
+
# [Option] Install zsh
|
9
|
+
ARG INSTALL_ZSH="true"
|
10
|
+
# [Option] Upgrade OS packages to their latest versions
|
11
|
+
ARG UPGRADE_PACKAGES="true"
|
12
|
+
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
|
13
|
+
ARG USERNAME=vscode
|
14
|
+
ARG USER_UID=1000
|
15
|
+
ARG USER_GID=$USER_UID
|
16
|
+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
17
|
+
# Remove imagemagick due to https://security-tracker.debian.org/tracker/CVE-2019-10131
|
18
|
+
&& apt-get purge -y imagemagick imagemagick-6-common \
|
19
|
+
# Install common packages, non-root user, rvm, core build tools
|
20
|
+
&& bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" "true" "true" \
|
21
|
+
&& bash /tmp/library-scripts/ruby-debian.sh "none" "${USERNAME}" "true" "true" \
|
22
|
+
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
|
23
|
+
|
24
|
+
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
|
25
|
+
ARG NODE_VERSION="none"
|
26
|
+
ENV NVM_DIR=/usr/local/share/nvm
|
27
|
+
ENV NVM_SYMLINK_CURRENT=true \
|
28
|
+
PATH=${NVM_DIR}/current/bin:${PATH}
|
29
|
+
RUN bash /tmp/library-scripts/node-debian.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}" \
|
30
|
+
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
|
31
|
+
|
32
|
+
# Remove library scripts for final image
|
33
|
+
RUN rm -rf /tmp/library-scripts
|
34
|
+
|
35
|
+
# [Optional] Uncomment this section to install additional OS packages.
|
36
|
+
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
37
|
+
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
38
|
+
|
39
|
+
# [Optional] Uncomment this line to install additional gems.
|
40
|
+
# RUN gem install <your-gem-names-here>
|
41
|
+
|
42
|
+
# [Optional] Uncomment this line to install global node packages.
|
43
|
+
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
@@ -0,0 +1,35 @@
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
2
|
+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/ruby
|
3
|
+
{
|
4
|
+
"name": "Ruby",
|
5
|
+
"build": {
|
6
|
+
"dockerfile": "Dockerfile",
|
7
|
+
"args": {
|
8
|
+
// Update 'VARIANT' to pick a Ruby version: 3, 3.1, 3.0, 2, 2.7, 2.6
|
9
|
+
// Append -bullseye or -buster to pin to an OS version.
|
10
|
+
// Use -bullseye variants on local on arm64/Apple Silicon.
|
11
|
+
"VARIANT": "3-bullseye",
|
12
|
+
// Options
|
13
|
+
"NODE_VERSION": "none"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
|
17
|
+
// Set *default* container specific settings.json values on container create.
|
18
|
+
"settings": {},
|
19
|
+
|
20
|
+
// Add the IDs of extensions you want installed when the container is created.
|
21
|
+
"extensions": ["rebornix.Ruby"],
|
22
|
+
|
23
|
+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
24
|
+
// "forwardPorts": [],
|
25
|
+
|
26
|
+
// Use 'postCreateCommand' to run commands after the container is created.
|
27
|
+
// "postCreateCommand": "ruby --version",
|
28
|
+
|
29
|
+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
30
|
+
"remoteUser": "vscode",
|
31
|
+
"features": {
|
32
|
+
"github-cli": "latest",
|
33
|
+
"aws-cli": "latest"
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,20 @@
|
|
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@v4
|
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/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
## [v6.0.0] - 2022-02-18
|
2
|
+
|
3
|
+
- Breaking changes: Initialize Rails before parsing config file
|
4
|
+
- [#686](https://github.com/ruby-shoryuken/shoryuken/pull/686)
|
5
|
+
- Previously, Shoryuken read its configuration from an optional YAML file, then allowed CLI arguments to override those, then initialized the Rails application (provided that `--rails` or `-R` was specified). This behavior meant that the config file did not have access to things like environment variables that were initialized by Rails (such as when using `dotenv`). With this change, Rails is initialized much earlier in the process. After Rails is initialized, the YAML configuration file is interpreted, and CLI arguments are finally interpreted last. Most applications will not need to undergo changes in order to upgrade, but the new load order could technically result in different behavior depending on the application's YAML configuration file or Rails initializers.
|
6
|
+
|
7
|
+
## [v5.3.2] - 2022-01-19
|
8
|
+
|
9
|
+
- (Bugfix) Preserve queue weights when unpausing queues
|
10
|
+
- [#687](https://github.com/ruby-shoryuken/shoryuken/pull/687)
|
11
|
+
|
12
|
+
- Improve error message on startup when shoryuken has insufficient permissions to access a queue
|
13
|
+
- [#691](https://github.com/ruby-shoryuken/shoryuken/pull/691)
|
14
|
+
|
15
|
+
## [v5.3.1] - 2022-01-07
|
16
|
+
|
17
|
+
- (Bugfix) Fix issue where, when using the TSTP or USR1 signals for soft shutdowns, it was possible for shoryuken to terminate without first attempting to handle all messages it fetched from SQS
|
18
|
+
- [#676](https://github.com/ruby-shoryuken/shoryuken/pull/676)
|
19
|
+
|
20
|
+
## [v5.3.0] - 2021-10-31
|
21
|
+
|
22
|
+
- (Refactor) Use Forwardable within Message to avoid method boilerplate
|
23
|
+
- [#681](https://github.com/ruby-shoryuken/shoryuken/pull/681)
|
24
|
+
|
25
|
+
- Add basic health check API
|
26
|
+
- [#679](https://github.com/ruby-shoryuken/shoryuken/pull/679)
|
27
|
+
|
1
28
|
## [v5.2.3] - 2021-07-29
|
2
29
|
|
3
30
|
- Fire new `:utilization_update` event any time a worker pool's utilization changes
|
data/Gemfile
CHANGED
@@ -18,12 +18,12 @@ module Shoryuken
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def setup_options
|
21
|
+
initialize_rails if load_rails?
|
21
22
|
initialize_options
|
22
23
|
initialize_logger
|
23
24
|
end
|
24
25
|
|
25
26
|
def load
|
26
|
-
load_rails if Shoryuken.options[:rails]
|
27
27
|
prefix_active_job_queue_names
|
28
28
|
parse_queues
|
29
29
|
require_workers
|
@@ -55,7 +55,7 @@ module Shoryuken
|
|
55
55
|
Shoryuken.logger.level = Logger::DEBUG if Shoryuken.options[:verbose]
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
58
|
+
def initialize_rails
|
59
59
|
# Adapted from: https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/cli.rb
|
60
60
|
|
61
61
|
require 'rails'
|
@@ -79,6 +79,10 @@ module Shoryuken
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
def load_rails?
|
83
|
+
options[:rails]
|
84
|
+
end
|
85
|
+
|
82
86
|
def prefix_active_job_queue_name(queue_name, weight)
|
83
87
|
return [queue_name, weight] if queue_name.start_with?('https://', 'arn:')
|
84
88
|
|
@@ -159,9 +163,17 @@ module Shoryuken
|
|
159
163
|
|
160
164
|
return if non_existent_queues.none?
|
161
165
|
|
166
|
+
# NOTE: HEREDOC's ~ operator removes indents, but is only available Ruby 2.3+
|
167
|
+
# See github PR: https://github.com/ruby-shoryuken/shoryuken/pull/691#issuecomment-1007653595
|
168
|
+
error_msg = <<-MSG.gsub(/^\s+/, '')
|
169
|
+
The specified queue(s) #{non_existent_queues.join(', ')} do not exist.
|
170
|
+
Try 'shoryuken sqs create QUEUE-NAME' for creating a queue with default settings.
|
171
|
+
It's also possible that you don't have permission to access the specified queues.
|
172
|
+
MSG
|
173
|
+
|
162
174
|
fail(
|
163
175
|
ArgumentError,
|
164
|
-
|
176
|
+
error_msg
|
165
177
|
)
|
166
178
|
end
|
167
179
|
|
data/lib/shoryuken/launcher.rb
CHANGED
@@ -28,12 +28,30 @@ module Shoryuken
|
|
28
28
|
|
29
29
|
initiate_stop
|
30
30
|
|
31
|
+
stop_new_dispatching
|
32
|
+
await_dispatching_in_progress
|
33
|
+
|
31
34
|
executor.shutdown
|
32
35
|
executor.wait_for_termination
|
33
36
|
end
|
34
37
|
|
38
|
+
def healthy?
|
39
|
+
Shoryuken.groups.keys.all? do |group|
|
40
|
+
manager = @managers.find { |m| m.group == group }
|
41
|
+
manager && manager.running?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
35
45
|
private
|
36
46
|
|
47
|
+
def stop_new_dispatching
|
48
|
+
@managers.each(&:stop_new_dispatching)
|
49
|
+
end
|
50
|
+
|
51
|
+
def await_dispatching_in_progress
|
52
|
+
@managers.each(&:await_dispatching_in_progress)
|
53
|
+
end
|
54
|
+
|
37
55
|
def executor
|
38
56
|
@_executor ||= Shoryuken.launcher_executor || Concurrent.global_io_executor
|
39
57
|
end
|
data/lib/shoryuken/manager.rb
CHANGED
@@ -6,14 +6,18 @@ module Shoryuken
|
|
6
6
|
# See https://github.com/phstc/shoryuken/issues/348#issuecomment-292847028
|
7
7
|
MIN_DISPATCH_INTERVAL = 0.1
|
8
8
|
|
9
|
+
attr_reader :group
|
10
|
+
|
9
11
|
def initialize(group, fetcher, polling_strategy, concurrency, executor)
|
10
|
-
@group
|
11
|
-
@fetcher
|
12
|
-
@polling_strategy
|
13
|
-
@max_processors
|
14
|
-
@busy_processors
|
15
|
-
@executor
|
16
|
-
@running
|
12
|
+
@group = group
|
13
|
+
@fetcher = fetcher
|
14
|
+
@polling_strategy = polling_strategy
|
15
|
+
@max_processors = concurrency
|
16
|
+
@busy_processors = Concurrent::AtomicFixnum.new(0)
|
17
|
+
@executor = executor
|
18
|
+
@running = Concurrent::AtomicBoolean.new(true)
|
19
|
+
@stop_new_dispatching = Concurrent::AtomicBoolean.new(false)
|
20
|
+
@dispatching_release_signal = ::Queue.new
|
17
21
|
end
|
18
22
|
|
19
23
|
def start
|
@@ -21,14 +25,28 @@ module Shoryuken
|
|
21
25
|
dispatch_loop
|
22
26
|
end
|
23
27
|
|
24
|
-
|
28
|
+
def stop_new_dispatching
|
29
|
+
@stop_new_dispatching.make_true
|
30
|
+
end
|
31
|
+
|
32
|
+
def await_dispatching_in_progress
|
33
|
+
# There might still be a dispatching on-going, as the response from SQS could take some time
|
34
|
+
# We don't want to stop the process before processing incoming messages, as they would stay "in-flight" for some time on SQS
|
35
|
+
# We use a queue, as the dispatch_loop is running on another thread, and this is a efficient way of communicating between threads.
|
36
|
+
@dispatching_release_signal.pop
|
37
|
+
end
|
25
38
|
|
26
39
|
def running?
|
27
40
|
@running.true? && @executor.running?
|
28
41
|
end
|
29
42
|
|
43
|
+
private
|
44
|
+
|
30
45
|
def dispatch_loop
|
31
|
-
|
46
|
+
if @stop_new_dispatching.true? || !running?
|
47
|
+
@dispatching_release_signal << 1
|
48
|
+
return
|
49
|
+
end
|
32
50
|
|
33
51
|
@executor.post { dispatch }
|
34
52
|
end
|
@@ -92,7 +110,6 @@ module Shoryuken
|
|
92
110
|
|
93
111
|
def dispatch_single_messages(queue)
|
94
112
|
messages = @fetcher.fetch(queue, ready)
|
95
|
-
|
96
113
|
@polling_strategy.messages_found(queue.name, messages.size)
|
97
114
|
messages.each { |message| assign(queue.name, message) }
|
98
115
|
end
|
data/lib/shoryuken/message.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
module Shoryuken
|
2
2
|
class Message
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators(:data,
|
6
|
+
:message_id,
|
7
|
+
:receipt_handle,
|
8
|
+
:md5_of_body,
|
9
|
+
:body,
|
10
|
+
:attributes,
|
11
|
+
:md5_of_message_attributes,
|
12
|
+
:message_attributes)
|
13
|
+
|
3
14
|
attr_accessor :client, :queue_url, :queue_name, :data
|
4
15
|
|
5
16
|
def initialize(client, queue, data)
|
@@ -29,33 +40,5 @@ module Shoryuken
|
|
29
40
|
visibility_timeout: timeout
|
30
41
|
)
|
31
42
|
end
|
32
|
-
|
33
|
-
def message_id
|
34
|
-
data.message_id
|
35
|
-
end
|
36
|
-
|
37
|
-
def receipt_handle
|
38
|
-
data.receipt_handle
|
39
|
-
end
|
40
|
-
|
41
|
-
def md5_of_body
|
42
|
-
data.md5_of_body
|
43
|
-
end
|
44
|
-
|
45
|
-
def body
|
46
|
-
data.body
|
47
|
-
end
|
48
|
-
|
49
|
-
def attributes
|
50
|
-
data.attributes
|
51
|
-
end
|
52
|
-
|
53
|
-
def md5_of_message_attributes
|
54
|
-
data.md5_of_message_attributes
|
55
|
-
end
|
56
|
-
|
57
|
-
def message_attributes
|
58
|
-
data.message_attributes
|
59
|
-
end
|
60
43
|
end
|
61
44
|
end
|
@@ -39,8 +39,10 @@ module Shoryuken
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def message_processed(queue)
|
42
|
-
|
43
|
-
|
42
|
+
if queue_paused?(queue)
|
43
|
+
logger.debug "Unpausing #{queue}"
|
44
|
+
@paused_until[queue] = Time.at 0
|
45
|
+
end
|
44
46
|
end
|
45
47
|
|
46
48
|
private
|
@@ -36,12 +36,10 @@ module Shoryuken
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def message_processed(queue)
|
39
|
-
|
39
|
+
paused_queue = @paused_queues.find { |_time, name| name == queue }
|
40
|
+
return unless paused_queue
|
40
41
|
|
41
|
-
|
42
|
-
@paused_queues.reject! { |_time, name| name == queue }
|
43
|
-
@queues << queue
|
44
|
-
@queues.uniq!
|
42
|
+
paused_queue[0] = Time.at 0
|
45
43
|
end
|
46
44
|
|
47
45
|
private
|
data/lib/shoryuken/runner.rb
CHANGED
@@ -30,9 +30,6 @@ module Shoryuken
|
|
30
30
|
|
31
31
|
loader = EnvironmentLoader.setup_options(options)
|
32
32
|
|
33
|
-
# When cli args exist, override options in config file
|
34
|
-
Shoryuken.options.merge!(options)
|
35
|
-
|
36
33
|
daemonize(Shoryuken.options)
|
37
34
|
write_pid(Shoryuken.options)
|
38
35
|
|
@@ -55,6 +52,10 @@ module Shoryuken
|
|
55
52
|
end
|
56
53
|
end
|
57
54
|
|
55
|
+
def healthy?
|
56
|
+
(@launcher && @launcher.healthy?) || false
|
57
|
+
end
|
58
|
+
|
58
59
|
private
|
59
60
|
|
60
61
|
def initialize_concurrent_logger
|
data/lib/shoryuken/version.rb
CHANGED
data/lib/shoryuken.rb
CHANGED
@@ -4,11 +4,41 @@ require 'active_job'
|
|
4
4
|
RSpec.describe Shoryuken::EnvironmentLoader do
|
5
5
|
subject { described_class.new({}) }
|
6
6
|
|
7
|
-
describe '#
|
7
|
+
describe '#load' do
|
8
8
|
before do
|
9
|
+
Shoryuken.groups.clear
|
10
|
+
# See issue: https://stackoverflow.com/a/63699568 for stubbing AWS errors
|
11
|
+
allow(Shoryuken::Client)
|
12
|
+
.to receive(:queues)
|
13
|
+
.with('stubbed_queue')
|
14
|
+
.and_raise(Aws::SQS::Errors::NonExistentQueue.new(nil, nil))
|
9
15
|
allow(subject).to receive(:load_rails)
|
10
16
|
allow(subject).to receive(:prefix_active_job_queue_names)
|
11
17
|
allow(subject).to receive(:require_workers)
|
18
|
+
allow(subject).to receive(:validate_workers)
|
19
|
+
allow(subject).to receive(:patch_deprecated_workers)
|
20
|
+
Shoryuken.options[:groups] = [['custom', { queues: ['stubbed_queue'] }]]
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when given queues don't exist" do
|
24
|
+
specify do
|
25
|
+
expect { subject.load }.to raise_error(
|
26
|
+
ArgumentError,
|
27
|
+
<<-MSG.gsub(/^\s+/, '')
|
28
|
+
The specified queue(s) stubbed_queue do not exist.
|
29
|
+
Try 'shoryuken sqs create QUEUE-NAME' for creating a queue with default settings.
|
30
|
+
It's also possible that you don't have permission to access the specified queues.
|
31
|
+
MSG
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#parse_queues loads default queues' do
|
38
|
+
before do
|
39
|
+
allow(subject).to receive(:initialize_rails)
|
40
|
+
allow(subject).to receive(:prefix_active_job_queue_names)
|
41
|
+
allow(subject).to receive(:require_workers)
|
12
42
|
allow(subject).to receive(:validate_queues)
|
13
43
|
allow(subject).to receive(:validate_workers)
|
14
44
|
allow(subject).to receive(:patch_deprecated_workers)
|
@@ -24,7 +54,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
24
54
|
|
25
55
|
describe '#parse_queues includes delay per groups' do
|
26
56
|
before do
|
27
|
-
allow(subject).to receive(:
|
57
|
+
allow(subject).to receive(:initialize_rails)
|
28
58
|
allow(subject).to receive(:prefix_active_job_queue_names)
|
29
59
|
allow(subject).to receive(:require_workers)
|
30
60
|
allow(subject).to receive(:validate_queues)
|
@@ -34,7 +64,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
34
64
|
|
35
65
|
specify do
|
36
66
|
Shoryuken.options[:queues] = ['queue1', 'queue2'] # default queues
|
37
|
-
Shoryuken.options[:groups] = [[
|
67
|
+
Shoryuken.options[:groups] = [['custom', { queues: ['queue3'], delay: 25 }]]
|
38
68
|
subject.load
|
39
69
|
|
40
70
|
expect(Shoryuken.groups['default'][:queues]).to eq(%w[queue1 queue2])
|
@@ -44,10 +74,9 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
44
74
|
end
|
45
75
|
end
|
46
76
|
|
47
|
-
|
48
77
|
describe '#prefix_active_job_queue_names' do
|
49
78
|
before do
|
50
|
-
allow(subject).to receive(:
|
79
|
+
allow(subject).to receive(:initialize_rails)
|
51
80
|
allow(subject).to receive(:require_workers)
|
52
81
|
allow(subject).to receive(:validate_queues)
|
53
82
|
allow(subject).to receive(:validate_workers)
|
@@ -76,7 +105,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
76
105
|
|
77
106
|
it 'does not prefix url-based queues' do
|
78
107
|
Shoryuken.options[:queues] = ['https://example.com/test_queue1']
|
79
|
-
Shoryuken.options[:groups] = {'group1' => {queues: ['https://example.com/test_group1_queue1']}}
|
108
|
+
Shoryuken.options[:groups] = { 'group1' => { queues: ['https://example.com/test_group1_queue1'] } }
|
80
109
|
|
81
110
|
subject.load
|
82
111
|
|
@@ -86,7 +115,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
86
115
|
|
87
116
|
it 'does not prefix arn-based queues' do
|
88
117
|
Shoryuken.options[:queues] = ['arn:aws:sqs:fake-region-1:1234:test_queue1']
|
89
|
-
Shoryuken.options[:groups] = {'group1' => {queues: ['arn:aws:sqs:fake-region-1:1234:test_group1_queue1']}}
|
118
|
+
Shoryuken.options[:groups] = { 'group1' => { queues: ['arn:aws:sqs:fake-region-1:1234:test_group1_queue1'] } }
|
90
119
|
|
91
120
|
subject.load
|
92
121
|
|
@@ -94,9 +123,11 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
94
123
|
expect(Shoryuken.groups['group1'][:queues]).to(eq(['arn:aws:sqs:fake-region-1:1234:test_group1_queue1']))
|
95
124
|
end
|
96
125
|
end
|
126
|
+
|
97
127
|
describe "#setup_options" do
|
98
|
-
let
|
99
|
-
let
|
128
|
+
let(:cli_queues) { { "queue1" => 10, "queue2" => 20 } }
|
129
|
+
let(:config_queues) { [["queue1", 8], ["queue2", 4]] }
|
130
|
+
|
100
131
|
context "when given queues through config and CLI" do
|
101
132
|
specify do
|
102
133
|
allow_any_instance_of(Shoryuken::EnvironmentLoader).to receive(:config_file_options).and_return({ queues: config_queues })
|
@@ -104,6 +135,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
104
135
|
expect(Shoryuken.options[:queues]).to eq(cli_queues)
|
105
136
|
end
|
106
137
|
end
|
138
|
+
|
107
139
|
context "when given queues through config only" do
|
108
140
|
specify do
|
109
141
|
allow_any_instance_of(Shoryuken::EnvironmentLoader).to receive(:config_file_options).and_return({ queues: config_queues })
|
@@ -111,6 +143,7 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
111
143
|
expect(Shoryuken.options[:queues]).to eq(config_queues)
|
112
144
|
end
|
113
145
|
end
|
146
|
+
|
114
147
|
context "when given queues through CLI only" do
|
115
148
|
specify do
|
116
149
|
Shoryuken::EnvironmentLoader.setup_options(queues: cli_queues)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shoryuken/launcher'
|
3
|
+
|
4
|
+
RSpec.describe Shoryuken::Launcher do
|
5
|
+
let(:executor) do
|
6
|
+
# We can't use Concurrent.global_io_executor in these tests since once you
|
7
|
+
# shut down a thread pool, you can't start it back up. Instead, we create
|
8
|
+
# one new thread pool executor for each spec. We use a new
|
9
|
+
# CachedThreadPool, since that most closely resembles
|
10
|
+
# Concurrent.global_io_executor
|
11
|
+
Concurrent::CachedThreadPool.new auto_terminate: true
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:first_group_manager) { double(:first_group_manager, group: 'first_group') }
|
15
|
+
let(:second_group_manager) { double(:second_group_manager, group: 'second_group') }
|
16
|
+
let(:first_queue) { "launcher_spec_#{SecureRandom.uuid}" }
|
17
|
+
let(:second_queue) { "launcher_spec_#{SecureRandom.uuid}" }
|
18
|
+
|
19
|
+
before do
|
20
|
+
Shoryuken.add_group('first_group', 1)
|
21
|
+
Shoryuken.add_group('second_group', 1)
|
22
|
+
Shoryuken.add_queue(first_queue, 1, 'first_group')
|
23
|
+
Shoryuken.add_queue(second_queue, 1, 'second_group')
|
24
|
+
allow(Shoryuken).to receive(:launcher_executor).and_return(executor)
|
25
|
+
allow(Shoryuken::Manager).to receive(:new).with('first_group', any_args).and_return(first_group_manager)
|
26
|
+
allow(Shoryuken::Manager).to receive(:new).with('second_group', any_args).and_return(second_group_manager)
|
27
|
+
allow(first_group_manager).to receive(:running?).and_return(true)
|
28
|
+
allow(second_group_manager).to receive(:running?).and_return(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#healthy?' do
|
32
|
+
context 'when all groups have managers' do
|
33
|
+
context 'when all managers are running' do
|
34
|
+
it 'returns true' do
|
35
|
+
expect(subject.healthy?).to be true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when one manager is not running' do
|
40
|
+
before do
|
41
|
+
allow(second_group_manager).to receive(:running?).and_return(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns false' do
|
45
|
+
expect(subject.healthy?).to be false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when all groups do not have managers' do
|
51
|
+
before do
|
52
|
+
allow(second_group_manager).to receive(:group).and_return('some_random_group')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns false' do
|
56
|
+
expect(subject.healthy?).to be false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -73,9 +73,11 @@ RSpec.describe Shoryuken::Manager do
|
|
73
73
|
expect(subject).to receive(:fire_event).with(:dispatch, false, queue_name: q.name)
|
74
74
|
expect(subject).to receive(:fire_event).with(:utilization_update,
|
75
75
|
false,
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
{
|
77
|
+
group: 'default',
|
78
|
+
busy_processors: 1,
|
79
|
+
max_processors: 1
|
80
|
+
})
|
79
81
|
expect(Shoryuken::Processor).to receive(:process).with(q, message)
|
80
82
|
expect(Shoryuken.logger).to receive(:info).never
|
81
83
|
|
@@ -106,9 +108,11 @@ RSpec.describe Shoryuken::Manager do
|
|
106
108
|
expect(fetcher).to receive(:fetch).with(q, described_class::BATCH_LIMIT).and_return(messages)
|
107
109
|
expect(subject).to receive(:fire_event).with(:utilization_update,
|
108
110
|
false,
|
109
|
-
|
110
|
-
|
111
|
-
|
111
|
+
{
|
112
|
+
group: 'default',
|
113
|
+
busy_processors: 1,
|
114
|
+
max_processors: 1
|
115
|
+
})
|
112
116
|
expect(subject).to receive(:fire_event).with(:dispatch, false, queue_name: q.name)
|
113
117
|
allow(subject).to receive(:batched_queue?).with(q).and_return(true)
|
114
118
|
expect(Shoryuken::Processor).to receive(:process).with(q, messages)
|
@@ -173,4 +177,26 @@ RSpec.describe Shoryuken::Manager do
|
|
173
177
|
end
|
174
178
|
end
|
175
179
|
end
|
180
|
+
|
181
|
+
describe '#running?' do
|
182
|
+
context 'when the executor is running' do
|
183
|
+
before do
|
184
|
+
allow(executor).to receive(:running?).and_return(true)
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'returns true' do
|
188
|
+
expect(subject.running?).to be true
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'when the executor is not running' do
|
193
|
+
before do
|
194
|
+
allow(executor).to receive(:running?).and_return(false)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'returns false' do
|
198
|
+
expect(subject.running?).to be false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
176
202
|
end
|
@@ -106,12 +106,37 @@ RSpec.describe Shoryuken::Polling::WeightedRoundRobin do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
describe '#message_processed' do
|
109
|
-
it 'removes paused queue
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
109
|
+
it 'removes delay from paused queue' do
|
110
|
+
queues << queue1
|
111
|
+
queues << queue2
|
112
|
+
|
113
|
+
expect(subject.next_queue).to eq(queue1)
|
114
|
+
subject.messages_found(queue1, 0) # pauses queue1
|
115
|
+
|
116
|
+
expect(subject.active_queues).to eq([[queue2, 1]])
|
117
|
+
|
118
|
+
subject.message_processed(queue1) # marks queue1 to be unpaused
|
119
|
+
|
120
|
+
expect(subject.next_queue).to eq(queue2) # implicitly unpauses queue1
|
121
|
+
expect(subject.active_queues).to eq([[queue1, 1], [queue2, 1]])
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'preserves weight of queues when unpausing' do
|
125
|
+
queues << queue1
|
126
|
+
queues << queue1
|
127
|
+
queues << queue2
|
128
|
+
|
129
|
+
expect(subject.next_queue).to eq(queue1)
|
130
|
+
subject.messages_found(queue1, 1)
|
131
|
+
|
132
|
+
expect(subject.next_queue).to eq(queue2)
|
133
|
+
subject.messages_found(queue2, 0) # pauses queue2
|
134
|
+
|
135
|
+
expect(subject.active_queues).to eq([[queue1, 2]])
|
136
|
+
subject.message_processed(queue2) # marks queue2 to be unpaused
|
137
|
+
|
138
|
+
expect(subject.next_queue).to eq(queue1) # implicitly unpauses queue2
|
139
|
+
expect(subject.active_queues).to eq([[queue1, 2], [queue2, 1]])
|
115
140
|
end
|
116
141
|
end
|
117
142
|
end
|
@@ -80,7 +80,8 @@ RSpec.describe Shoryuken::Queue do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'deletes' do
|
83
|
-
expect(sqs).to receive(:delete_message_batch).with(entries: entries,
|
83
|
+
expect(sqs).to receive(:delete_message_batch).with({ entries: entries,
|
84
|
+
queue_url: queue_url }).and_return(double(failed: []))
|
84
85
|
|
85
86
|
subject.delete_messages(entries: entries)
|
86
87
|
end
|
@@ -91,7 +92,8 @@ RSpec.describe Shoryuken::Queue do
|
|
91
92
|
logger = double 'Logger'
|
92
93
|
|
93
94
|
expect(sqs).to(
|
94
|
-
receive(:delete_message_batch).with(entries: entries,
|
95
|
+
receive(:delete_message_batch).with({ entries: entries,
|
96
|
+
queue_url: queue_url }).and_return(double(failed: [failure]))
|
95
97
|
)
|
96
98
|
expect(subject).to receive(:logger).and_return(logger)
|
97
99
|
expect(logger).to receive(:error)
|
@@ -157,7 +159,8 @@ RSpec.describe Shoryuken::Queue do
|
|
157
159
|
it 'accepts SQS request parameters' do
|
158
160
|
# https://docs.aws.amazon.com/sdkforruby/api/Aws/SQS/Client.html#send_message_batch-instance_method
|
159
161
|
expect(sqs).to(
|
160
|
-
receive(:send_message_batch).with(hash_including(entries: [{ id: '0', message_body: 'msg1' },
|
162
|
+
receive(:send_message_batch).with(hash_including(entries: [{ id: '0', message_body: 'msg1' },
|
163
|
+
{ id: '1', message_body: 'msg2' }]))
|
161
164
|
)
|
162
165
|
|
163
166
|
subject.send_messages(entries: [{ id: '0', message_body: 'msg1' }, { id: '1', message_body: 'msg2' }])
|
@@ -286,7 +289,8 @@ RSpec.describe Shoryuken::Queue do
|
|
286
289
|
Shoryuken.cache_visibility_timeout = false
|
287
290
|
|
288
291
|
expect(sqs).to(
|
289
|
-
receive(:get_queue_attributes).with(queue_url: queue_url,
|
292
|
+
receive(:get_queue_attributes).with(queue_url: queue_url,
|
293
|
+
attribute_names: ['All']).and_return(attribute_response).exactly(3).times
|
290
294
|
)
|
291
295
|
expect(subject.visibility_timeout).to eq(30)
|
292
296
|
expect(subject.visibility_timeout).to eq(30)
|
@@ -299,7 +303,8 @@ RSpec.describe Shoryuken::Queue do
|
|
299
303
|
Shoryuken.cache_visibility_timeout = true
|
300
304
|
|
301
305
|
expect(sqs).to(
|
302
|
-
receive(:get_queue_attributes).with(queue_url: queue_url,
|
306
|
+
receive(:get_queue_attributes).with({ queue_url: queue_url,
|
307
|
+
attribute_names: ['All'] }).and_return(attribute_response).once
|
303
308
|
)
|
304
309
|
expect(subject.visibility_timeout).to eq(30)
|
305
310
|
expect(subject.visibility_timeout).to eq(30)
|
@@ -10,16 +10,16 @@ RSpec.describe Shoryuken::Worker::DefaultExecutor do
|
|
10
10
|
|
11
11
|
describe '.perform_in' do
|
12
12
|
it 'delays a message' do
|
13
|
-
expect(sqs_queue).to receive(:send_message).with(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
expect(sqs_queue).to receive(:send_message).with({
|
14
|
+
message_attributes: {
|
15
|
+
'shoryuken_class' => {
|
16
|
+
string_value: TestWorker.to_s,
|
17
|
+
data_type: 'String'
|
18
|
+
}
|
19
|
+
},
|
20
|
+
message_body: 'message',
|
21
|
+
delay_seconds: 60
|
22
|
+
})
|
23
23
|
|
24
24
|
TestWorker.perform_in(60, 'message')
|
25
25
|
end
|
@@ -33,16 +33,16 @@ RSpec.describe Shoryuken::Worker::DefaultExecutor do
|
|
33
33
|
|
34
34
|
describe '.perform_at' do
|
35
35
|
it 'delays a message' do
|
36
|
-
expect(sqs_queue).to receive(:send_message).with(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
expect(sqs_queue).to receive(:send_message).with({
|
37
|
+
message_attributes: {
|
38
|
+
'shoryuken_class' => {
|
39
|
+
string_value: TestWorker.to_s,
|
40
|
+
data_type: 'String'
|
41
|
+
}
|
42
|
+
},
|
43
|
+
message_body: 'message',
|
44
|
+
delay_seconds: 60
|
45
|
+
})
|
46
46
|
|
47
47
|
TestWorker.perform_in(Time.now + 60, 'message')
|
48
48
|
end
|
@@ -56,30 +56,30 @@ RSpec.describe Shoryuken::Worker::DefaultExecutor do
|
|
56
56
|
|
57
57
|
describe '.perform_async' do
|
58
58
|
it 'enqueues a message' do
|
59
|
-
expect(sqs_queue).to receive(:send_message).with(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
expect(sqs_queue).to receive(:send_message).with({
|
60
|
+
message_attributes: {
|
61
|
+
'shoryuken_class' => {
|
62
|
+
string_value: TestWorker.to_s,
|
63
|
+
data_type: 'String'
|
64
|
+
}
|
65
|
+
},
|
66
|
+
message_body: 'message'
|
67
|
+
})
|
68
68
|
|
69
69
|
TestWorker.perform_async('message')
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'enqueues a message with options' do
|
73
|
-
expect(sqs_queue).to receive(:send_message).with(
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
73
|
+
expect(sqs_queue).to receive(:send_message).with({
|
74
|
+
delay_seconds: 60,
|
75
|
+
message_attributes: {
|
76
|
+
'shoryuken_class' => {
|
77
|
+
string_value: TestWorker.to_s,
|
78
|
+
data_type: 'String'
|
79
|
+
}
|
80
|
+
},
|
81
|
+
message_body: 'delayed message'
|
82
|
+
})
|
83
83
|
|
84
84
|
TestWorker.perform_async('delayed message', delay_seconds: 60)
|
85
85
|
end
|
@@ -89,15 +89,15 @@ RSpec.describe Shoryuken::Worker::DefaultExecutor do
|
|
89
89
|
|
90
90
|
expect(Shoryuken::Client).to receive(:queues).with(new_queue).and_return(sqs_queue)
|
91
91
|
|
92
|
-
expect(sqs_queue).to receive(:send_message).with(
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
92
|
+
expect(sqs_queue).to receive(:send_message).with({
|
93
|
+
message_attributes: {
|
94
|
+
'shoryuken_class' => {
|
95
|
+
string_value: TestWorker.to_s,
|
96
|
+
data_type: 'String'
|
97
|
+
}
|
98
|
+
},
|
99
|
+
message_body: 'delayed message'
|
100
|
+
})
|
101
101
|
|
102
102
|
TestWorker.perform_async('delayed message', queue: new_queue)
|
103
103
|
end
|
data/spec/shoryuken_spec.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe Shoryuken do
|
4
|
+
describe '.healthy?' do
|
5
|
+
before do
|
6
|
+
allow(Shoryuken::Runner).to receive(:instance).and_return(double(:instance, healthy?: :some_result))
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'delegates to the runner instance' do
|
10
|
+
expect(described_class.healthy?).to eq(:some_result)
|
11
|
+
end
|
12
|
+
end
|
4
13
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shoryuken
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pablo Cantero
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|
@@ -103,8 +103,12 @@ extensions: []
|
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
105
|
- ".codeclimate.yml"
|
106
|
+
- ".devcontainer/Dockerfile"
|
107
|
+
- ".devcontainer/base.Dockerfile"
|
108
|
+
- ".devcontainer/devcontainer.json"
|
106
109
|
- ".github/FUNDING.yml"
|
107
110
|
- ".github/workflows/specs.yml"
|
111
|
+
- ".github/workflows/stale.yml"
|
108
112
|
- ".gitignore"
|
109
113
|
- ".reek.yml"
|
110
114
|
- ".rspec"
|
@@ -174,6 +178,7 @@ files:
|
|
174
178
|
- spec/shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb
|
175
179
|
- spec/shoryuken/extensions/active_job_wrapper_spec.rb
|
176
180
|
- spec/shoryuken/fetcher_spec.rb
|
181
|
+
- spec/shoryuken/launcher_spec.rb
|
177
182
|
- spec/shoryuken/manager_spec.rb
|
178
183
|
- spec/shoryuken/middleware/chain_spec.rb
|
179
184
|
- spec/shoryuken/middleware/server/auto_delete_spec.rb
|
@@ -213,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
218
|
- !ruby/object:Gem::Version
|
214
219
|
version: '0'
|
215
220
|
requirements: []
|
216
|
-
rubygems_version: 3.
|
221
|
+
rubygems_version: 3.1.2
|
217
222
|
signing_key:
|
218
223
|
specification_version: 4
|
219
224
|
summary: Shoryuken is a super efficient AWS SQS thread based message processor
|
@@ -231,6 +236,7 @@ test_files:
|
|
231
236
|
- spec/shoryuken/extensions/active_job_concurrent_send_adapter_spec.rb
|
232
237
|
- spec/shoryuken/extensions/active_job_wrapper_spec.rb
|
233
238
|
- spec/shoryuken/fetcher_spec.rb
|
239
|
+
- spec/shoryuken/launcher_spec.rb
|
234
240
|
- spec/shoryuken/manager_spec.rb
|
235
241
|
- spec/shoryuken/middleware/chain_spec.rb
|
236
242
|
- spec/shoryuken/middleware/server/auto_delete_spec.rb
|