sidekiq-tamer 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e76000c7eadffdb865f4040feb9d17a98287efe2362f6005f2dbd4de14bfed92
4
+ data.tar.gz: 020e0c46cc617649cae0349a70fec7bca5691caf50f1b561e6c8fe6b99d45859
5
+ SHA512:
6
+ metadata.gz: aa908135bae11522b65f9d7f17ee638c61bd8de76065af8a991cb1e5a8862f8b306247105123ed6099518266591c4b0f51420df6f61bcfe13d0ba9b9365bcb2d
7
+ data.tar.gz: da3de8d73ebf24e1fed060d290b600f9e18ac797df194a2238d1def54fc085d239ec4306cc2a2a0c83616f6fcc88f40d9b9270722c90dd45025cb88d8f3276af
data/.DS_Store ADDED
Binary file
@@ -0,0 +1,2 @@
1
+ # Validate the PR title, and ignore all commit messages
2
+ titleOnly: true
@@ -0,0 +1,62 @@
1
+ name: Gem Testing
2
+ on: push
3
+ jobs:
4
+ test_2_7_0:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v3
8
+ - name: Build the images
9
+ run: RUBY_VERSION=2.7.0 docker-compose build
10
+ - name: Run the tests
11
+ run: RUBY_VERSION=2.7.0 docker-compose up --exit-code-from tests --attach tests
12
+ test_latest:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+ - name: Build the images
17
+ run: RUBY_VERSION=latest docker-compose build
18
+ - name: Run the tests
19
+ run: RUBY_VERSION=latest docker-compose up --exit-code-from tests --attach tests
20
+ release:
21
+ runs-on: ubuntu-latest
22
+ container:
23
+ image: ruby:3.0.4
24
+ if: github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip-ci]')
25
+ env:
26
+ RUBY_GEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set git info
30
+ run: |
31
+ git config --global user.email "leandrogoe@gmail.com"
32
+ git config --global user.name "Leandro Gomez"
33
+ - name: Bundle install
34
+ run: |
35
+ git config --global --add safe.directory /sidekiq_tamer; \
36
+ gem install bundler --version 2.4.10; \
37
+ bundle install
38
+ - name: Determine version bump type
39
+ run: |
40
+ message=$(git log -1 --pretty=format:'%s')
41
+ if echo "$message" | grep -iq "fix:"; then
42
+ echo bump=patch >> $GITHUB_ENV
43
+ elif echo "$message" | grep -iq "feat:"; then
44
+ echo bump=minor >> $GITHUB_ENV
45
+ elif echo "$message" | grep -iq "BREAKING CHANGE:"; then
46
+ echo bump=major >> $GITHUB_ENV
47
+ else
48
+ echo bump=patch >> $GITHUB_ENV
49
+ fi
50
+ - name: Release
51
+ run: |
52
+ mkdir ~/.gem
53
+ echo "---\\n:rubygems_api_key: ${RUBY_GEMS_API_KEY}\\n:status: :ok\\n" > ~/.gem/credentials
54
+ chmod 0600 ~/.gem/credentials
55
+ # DEBUG: output any git changes
56
+ git status
57
+ bundle exec gem bump -v ${{ env.bump }} --file lib/sidekiq_tamer/version.rb --no-commit
58
+ bundle install; # Update Gemfile.lock with new version
59
+ git commit -am "Bumping gem version [skip-ci]"
60
+ bundle exec gem release -t
61
+ git push
62
+ needs: [test_2_7_0, test_latest]
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ .ruby_version
13
+ sidekiq-tamer-*.gem
14
+ TODO.txt
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sidekiq-tamer.gemspec
4
+ gemspec
5
+
6
+ gem "rspec", "~> 3.0"
7
+ gem "pry-byebug", "~> 3.9"
8
+ gem "timecop"
9
+ gem "pry", "~> 0.14.1"
10
+ gem "gem-release"
data/Gemfile.lock ADDED
@@ -0,0 +1,67 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sidekiq-tamer (0.2.0)
5
+ mongo (>= 2.0.0, < 3.0.0)
6
+ sidekiq (>= 5.0.0, < 7.0.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ bson (4.15.0)
12
+ byebug (11.1.3)
13
+ coderay (1.1.3)
14
+ connection_pool (2.4.0)
15
+ diff-lcs (1.5.0)
16
+ gem-release (2.2.2)
17
+ method_source (1.0.0)
18
+ mongo (2.18.2)
19
+ bson (>= 4.14.1, < 5.0.0)
20
+ pry (0.14.2)
21
+ coderay (~> 1.1)
22
+ method_source (~> 1.0)
23
+ pry-byebug (3.10.1)
24
+ byebug (~> 11.0)
25
+ pry (>= 0.13, < 0.15)
26
+ rack (3.0.7)
27
+ rack-protection (3.0.5)
28
+ rack
29
+ redis (5.0.6)
30
+ redis-client (>= 0.9.0)
31
+ redis-client (0.14.1)
32
+ connection_pool
33
+ rspec (3.12.0)
34
+ rspec-core (~> 3.12.0)
35
+ rspec-expectations (~> 3.12.0)
36
+ rspec-mocks (~> 3.12.0)
37
+ rspec-core (3.12.1)
38
+ rspec-support (~> 3.12.0)
39
+ rspec-expectations (3.12.2)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.12.0)
42
+ rspec-mocks (3.12.5)
43
+ diff-lcs (>= 1.2.0, < 2.0)
44
+ rspec-support (~> 3.12.0)
45
+ rspec-support (3.12.0)
46
+ sidekiq (6.0.4)
47
+ connection_pool (>= 2.2.2)
48
+ rack (>= 2.0.0)
49
+ rack-protection (>= 2.0.0)
50
+ redis (>= 4.1.0)
51
+ timecop (0.9.6)
52
+
53
+ PLATFORMS
54
+ aarch64-linux
55
+ arm64-darwin-22
56
+ x86_64-linux
57
+
58
+ DEPENDENCIES
59
+ gem-release
60
+ pry (~> 0.14.1)
61
+ pry-byebug (~> 3.9)
62
+ rspec (~> 3.0)
63
+ sidekiq-tamer!
64
+ timecop
65
+
66
+ BUNDLED WITH
67
+ 2.4.10
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Leandro Gomez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # Sidekiq Tamer
2
+ Do you ever worry about your Sidekiq jobs consuming too many resources, causing your system to slow down or even crash? When you don't have specific throttling requirements, Sidekiq Tamer can help you to easily protect your resources and prevent them from being overwhelmed by Sidekiq overscaling.
3
+
4
+ ## Installation
5
+ Getting started with Sidekiq Tamer is a breeze. Simply add the gem to your Gemfile:
6
+
7
+ ```ruby
8
+ gem 'sidekiq-tamer'
9
+ ```
10
+
11
+ Then, run bundle install or gem install sidekiq-tamer to install the gem.
12
+
13
+ ## Usage
14
+ With Sidekiq Tamer, you can delay the execution of jobs that depend on particular resources when those are on an stressed state. While Sidekiq Tamer was initially built to help handling the load over MongoDB, its actually a generic framework which you can use to protect any kind of resource, such as a database or an API endpoint.
15
+
16
+ ### Protecting a MongoDB cluster
17
+ Sidekiq Tamer includes an off-the-shelf implementation to handle MongoDB clusters. To use it, simply execute the following line during your initialization code:
18
+
19
+ ```ruby
20
+ SidekiqTamer::Mongo::Configuration.setup(user: 'your_user', password: 'your_password')
21
+ ```
22
+ Note that in order for the health monitor to work, you'll need to supply a user that has the clusterMonitor role enabled on the admin database of your cluster.
23
+
24
+ ### Defining Your Own Resources
25
+ To define a new resource, simply create a class that implements the `is_consumed_by?`, `name`, and `is_healthy?` methods. For example, if you have a database that has been hammered by background jobs in the past and you want to protect it, you might define a MyDatabaseResource class like this:
26
+
27
+ ```ruby
28
+ class MyDatabaseResource
29
+ def is_consumed_by?(job)
30
+ true
31
+ end
32
+
33
+ def name
34
+ "My Database"
35
+ end
36
+
37
+ def is_healthy?
38
+ # Add some logic to assess whether it's safe to use the resource
39
+ end
40
+ end
41
+ ```
42
+
43
+ Then, add an instance of your new class to the resource vault:
44
+
45
+ ```ruby
46
+ SidekiqTamer::Resource::Vault.add_resources(MyDatabaseResource.new)
47
+ ```
48
+
49
+ Now, whenever the `is_healthy?` method returns false for a job that depends on this resource, the Sidekiq middleware that Sidekiq Tamer introduces will raise an exception, causing the job to be retried later.
50
+
51
+ ## Contributing
52
+ We welcome bug reports and pull requests on GitHub at https://github.com/leandrogoe/sidekiq-tamer.
53
+
54
+ ## License
55
+ Sidekiq Tamer is available as open source under the terms of the MIT License.
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sidekiq_tamer"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/rspec ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ TEST_ARGS="$@" docker-compose up -d && docker attach sidekiq-tamer-tests && docker-compose down
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,38 @@
1
+ require "sidekiq/job_retry"
2
+ require_relative "resource/vault"
3
+
4
+ class SidekiqTamer::Middleware
5
+ class ResourceUnhealthy < StandardError; end;
6
+
7
+ def call(worker, job, queue)
8
+ Thread.current[:sidekiq_tamer_job_name] = job["class"]
9
+ if job_allows_retries?(job)
10
+ SidekiqTamer::Resource::Vault.get_resources_for(Object.const_get(job["class"])).each { |resource|
11
+ unless resource.is_healthy?
12
+ raise ResourceUnhealthy, "#{resource.name} is not healthy"
13
+ end
14
+ }
15
+ end
16
+ yield
17
+ end
18
+
19
+ def job_allows_retries?(job)
20
+ # Retry count is handled a bit weirdly in Sidekiq:
21
+ # retry_count = nil -> No retries actually took place
22
+ # retry_count = 0 -> This is the first retry
23
+ # retry_count > 0 -> This is retry_count - 1
24
+ (job["retry_count"] || -1) + 1 < max_retries_for(job)
25
+ end
26
+
27
+ def max_retries_for(job)
28
+ if job["retry"] == true || job["retry"] == nil
29
+ Sidekiq.options[:max_retries] || 25
30
+ elsif job["retry"] == false
31
+ 0
32
+ elsif job["retry"].is_a?(Integer)
33
+ job["retry"]
34
+ else
35
+ raise StandardError, "Unrecognized retry option"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,44 @@
1
+ module SidekiqTamer::Mongo
2
+ class CommandSubscriber
3
+ # https://github.com/mongodb/mongo-ruby-driver/blob/413555d553148d8bbf8bea2855cbd9929f3ba587/docs/reference/monitoring.txt#L27
4
+
5
+ DATA_MODIFICATION_COMMANDS=Set.new([
6
+ 'insert',
7
+ 'delete',
8
+ 'replace',
9
+ 'update',
10
+ 'drop',
11
+ 'rename',
12
+ 'dropDatabase',
13
+ 'invalidate',
14
+ 'createIndexes',
15
+ 'dropIndexes',
16
+ 'create',
17
+ 'modify',
18
+ 'shardCollection',
19
+ ]).freeze
20
+
21
+ def started(event)
22
+ unless event.command.keys.any?
23
+ return
24
+ end
25
+
26
+ operation = event.command.keys.any? { |key| DATA_MODIFICATION_COMMANDS.include?(key) } ? :write : :read
27
+ mongo_server_operation = SidekiqTamer::Mongo::ServerOperation.server_operation_for(
28
+ event.address.host, event.address.port, operation
29
+ )
30
+ if job_name = Thread.current[:sidekiq_tamer_job_name]
31
+ mongo_server_operation.add_job(Object.const_get(job_name))
32
+ end
33
+ end
34
+
35
+ def succeeded(event)
36
+ # No implementation, just provided to fullfil the expected interface.
37
+ end
38
+
39
+ def failed(event)
40
+ # No implementation, just provided to fullfil the expected interface.
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,40 @@
1
+ module SidekiqTamer::Mongo
2
+ class Configuration
3
+ MIN_TICKET_THRESHOLD = 80
4
+
5
+ class << self
6
+ def setup(user:, password:, ticket_threshold: MIN_TICKET_THRESHOLD)
7
+ @options = { user: user, password: password, ticket_threshold: ticket_threshold }
8
+ subscriber = SidekiqTamer::Mongo::CommandSubscriber.new
9
+ ::Mongo::Monitoring::Global.subscribe(::Mongo::Monitoring::COMMAND, subscriber)
10
+ end
11
+
12
+ def clear()
13
+ ::Mongo::Monitoring::Global.unsubscribe(::Mongo::Monitoring::COMMAND, self)
14
+ @options = {}
15
+ end
16
+
17
+ def user
18
+ get_option_value(:user)
19
+ end
20
+
21
+ def password
22
+ get_option_value(:password)
23
+ end
24
+
25
+ def ticket_threshold
26
+ get_option_value(:ticket_threshold)
27
+ end
28
+
29
+ private
30
+
31
+ def get_option_value(option)
32
+ if @options[option].is_a?(Proc)
33
+ @options[option].call()
34
+ else
35
+ @options[option]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,58 @@
1
+ require 'mongo'
2
+ require_relative 'command_subscriber'
3
+ require_relative 'configuration'
4
+
5
+ module SidekiqTamer::Mongo
6
+ class Server
7
+ def self.server_for(host, port)
8
+ key = "#{host}:#{port}"
9
+ servers[key] ||= Server.new(host, port)
10
+ servers[key]
11
+ end
12
+
13
+ def self.servers
14
+ @servers ||= {}
15
+ end
16
+
17
+ def self.clear_servers
18
+ @servers = {}
19
+ end
20
+
21
+ attr_reader :host, :port
22
+ def initialize(host, port)
23
+ @host = host
24
+ @port = port
25
+ end
26
+
27
+ def is_operation_safe?(operation)
28
+ average = wired_tiger_history.map { |entry|
29
+ entry[:concurrentTransactions][operation.to_s]['available']
30
+ }.sum / wired_tiger_history.count.to_f
31
+
32
+ average >= Configuration.ticket_threshold
33
+ end
34
+
35
+ def wired_tiger_history
36
+ @wired_tiger_history ||= []
37
+ if !@wiredtiger_tickets_read_at || @wiredtiger_tickets_read_at < Time.now - 30
38
+ @wired_tiger_history.push({ concurrentTransactions: available_tickets, read_at: Time.now })
39
+ @wiredtiger_tickets_read_at = Time.now
40
+ end
41
+ @wired_tiger_history = @wired_tiger_history.select { |entry| entry[:read_at] >= Time.now - 60 * 2 }
42
+ end
43
+
44
+ def available_tickets
45
+ client.database.command('serverStatus'=> 1).documents[0]['wiredTiger']['concurrentTransactions']
46
+ end
47
+
48
+ def client
49
+ @client ||= Mongo::Client.new(
50
+ [ "#{host}:#{port}" ], database: 'admin', user: Configuration.user, password: Configuration.password, auth_source: 'admin',
51
+ )
52
+ end
53
+
54
+ def clean_wired_tiger_tickets
55
+ @wiredtiger_tickets_read_at = nil
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ require 'mongo'
2
+ require_relative 'command_subscriber'
3
+ require_relative '../resource/resource_dependencies'
4
+ require_relative 'server'
5
+
6
+ module SidekiqTamer::Mongo
7
+ class ServerOperation
8
+ include SidekiqTamer::Resource::ResourceDependencies
9
+
10
+ def self.server_operation_for(host, port, operation)
11
+ key = "#{host}:#{port}:#{operation}"
12
+ server_operations[key] ||= ServerOperation.new(host, port, operation)
13
+ server_operations[key]
14
+ end
15
+
16
+ def self.clear_server_operations
17
+ @server_operations = {}
18
+ end
19
+
20
+ def self.server_operations
21
+ @server_operations ||= {}
22
+ end
23
+
24
+ attr_reader :operation, :server
25
+ def initialize(host, port, operation)
26
+ @server = Server.server_for(host, port)
27
+ @operation = operation
28
+ SidekiqTamer::Resource::Vault.add_resources(self)
29
+ end
30
+
31
+ def name
32
+ "MongoDB cluster #{operation}"
33
+ end
34
+
35
+ def is_healthy?
36
+ server.is_operation_safe?(@operation)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module SidekiqTamer::Resource
2
+ module ResourceDependencies
3
+ def jobs
4
+ @jobs ||= Set.new()
5
+ end
6
+
7
+ def add_job(job)
8
+ jobs.add(job)
9
+ end
10
+
11
+ def is_consumed_by?(job)
12
+ jobs.include?(job)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module SidekiqTamer::Resource
2
+ class Vault
3
+ def self.get_resources
4
+ resources
5
+ end
6
+
7
+ def self.get_resources_of_type(klass)
8
+ resources.select { |resource| resource.is_a?(klass) }
9
+ end
10
+
11
+ def self.resources
12
+ @resources ||= []
13
+ end
14
+
15
+ def self.clean_resources
16
+ @resources = []
17
+ end
18
+
19
+ def self.add_resources(*resources)
20
+ self.resources.push(*resources)
21
+ end
22
+
23
+ def self.get_resources_for(job)
24
+ get_resources.select { |resource| resource.is_consumed_by?(job) }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module SidekiqTamer
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,16 @@
1
+ require "sidekiq_tamer/version"
2
+ require "sidekiq_tamer/middleware"
3
+ require "sidekiq_tamer/mongo/server_operation"
4
+ require "sidekiq"
5
+
6
+ module SidekiqTamer
7
+ def self.setup
8
+ Sidekiq.configure_server do |config|
9
+ config.server_middleware do |chain|
10
+ chain.add SidekiqTamer::Middleware
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ SidekiqTamer.setup
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/sidekiq_tamer/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sidekiq-tamer"
5
+ spec.version = SidekiqTamer::VERSION
6
+ spec.authors = ["Leandro Gomez"]
7
+ spec.email = ["leandrogoe@gmail.com"]
8
+
9
+ spec.summary = %q{A simple way to protect your resources from Sidekiq scaling}
10
+ spec.homepage = "https://github.com/leandrogoe/sidekiq-tamer"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
13
+
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/leandrogoe/sidekiq-tamer.git"
17
+
18
+ # Specify which files should be added to the gem when it is released.
19
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test/|spec/|features/|docker|Docker)}) }
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_runtime_dependency 'sidekiq', '>= 5.0.0', '< 7.0.0'
28
+ spec.add_runtime_dependency 'mongo', '>= 2.0.0', '< 3.0.0'
29
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-tamer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Leandro Gomez
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sidekiq
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 7.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 5.0.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 7.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: mongo
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 2.0.0
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: 3.0.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 2.0.0
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: 3.0.0
53
+ description:
54
+ email:
55
+ - leandrogoe@gmail.com
56
+ executables: []
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - ".DS_Store"
61
+ - ".github/semantic.yml"
62
+ - ".github/workflows/github-actions.yml"
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE.txt
68
+ - README.md
69
+ - bin/console
70
+ - bin/rspec
71
+ - bin/setup
72
+ - lib/sidekiq_tamer.rb
73
+ - lib/sidekiq_tamer/middleware.rb
74
+ - lib/sidekiq_tamer/mongo/command_subscriber.rb
75
+ - lib/sidekiq_tamer/mongo/configuration.rb
76
+ - lib/sidekiq_tamer/mongo/server.rb
77
+ - lib/sidekiq_tamer/mongo/server_operation.rb
78
+ - lib/sidekiq_tamer/resource/resource_dependencies.rb
79
+ - lib/sidekiq_tamer/resource/vault.rb
80
+ - lib/sidekiq_tamer/version.rb
81
+ - sidekiq-tamer.gemspec
82
+ homepage: https://github.com/leandrogoe/sidekiq-tamer
83
+ licenses:
84
+ - MIT
85
+ metadata:
86
+ homepage_uri: https://github.com/leandrogoe/sidekiq-tamer
87
+ source_code_uri: https://github.com/leandrogoe/sidekiq-tamer.git
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.7.0
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubygems_version: 3.2.33
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: A simple way to protect your resources from Sidekiq scaling
107
+ test_files: []