sidekiq-recycler 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb953e946bdabfda52012df96add214084291736
4
+ data.tar.gz: 74e8809c6ae424ba44927c0c84509a7784bd1066
5
+ SHA512:
6
+ metadata.gz: 558a89279d337b8f4d9fea71c9e561b49e24a509bf35500e64f26ae54144e9e5e062757e9e331e67732d4097e8a82de8a6338a304b2ef685fd8885b5b4312385
7
+ data.tar.gz: e86bb903e9188e6ce52e1df1706841d96d27491a4433977ef20b3a8d45d48c9299c9e783a4e794ba2655124db90e7be42176579b152d713829256d40c2865891
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+
2
+ source "https://rubygems.org"
3
+
4
+ gem "sidekiq"
5
+
6
+ group :local do
7
+ gem "sidekiq-recycler", :path => "."
8
+ end
9
+
10
+ group :development do
11
+ gem "rake"
12
+ gem "jeweler"
13
+ gem "yard"
14
+ gem "logging"
15
+ gem "easycov"
16
+ gem "micron", :github => "chetan/micron"
17
+ end
@@ -0,0 +1,107 @@
1
+ GIT
2
+ remote: git://github.com/chetan/micron.git
3
+ revision: d722ad58ca390cdaf01d27d77aea1fbe951d0bca
4
+ specs:
5
+ micron (0.1.0)
6
+ colorize
7
+ easycov
8
+ hitimes
9
+
10
+ PATH
11
+ remote: .
12
+ specs:
13
+ sidekiq-recycler (0.1.0)
14
+ sidekiq
15
+
16
+ GEM
17
+ remote: https://rubygems.org/
18
+ specs:
19
+ addressable (2.3.5)
20
+ builder (3.2.2)
21
+ celluloid (0.15.2)
22
+ timers (~> 1.1.0)
23
+ colorize (0.6.0)
24
+ connection_pool (1.1.0)
25
+ easycov (0.3.1)
26
+ multi_json
27
+ simplecov
28
+ simplecov-console
29
+ simplecov-html
30
+ faraday (0.8.8)
31
+ multipart-post (~> 1.2.0)
32
+ git (1.2.6)
33
+ github_api (0.10.1)
34
+ addressable
35
+ faraday (~> 0.8.1)
36
+ hashie (>= 1.2)
37
+ multi_json (~> 1.4)
38
+ nokogiri (~> 1.5.2)
39
+ oauth2
40
+ hashie (2.0.5)
41
+ highline (1.6.19)
42
+ hirb (0.7.1)
43
+ hitimes (1.2.1)
44
+ httpauth (0.2.0)
45
+ jeweler (1.8.8)
46
+ builder
47
+ bundler (~> 1.0)
48
+ git (>= 1.2.5)
49
+ github_api (= 0.10.1)
50
+ highline (>= 1.6.15)
51
+ nokogiri (= 1.5.10)
52
+ rake
53
+ rdoc
54
+ json (1.8.0)
55
+ jwt (0.1.8)
56
+ multi_json (>= 1.5)
57
+ little-plugger (1.1.3)
58
+ logging (1.8.1)
59
+ little-plugger (>= 1.1.3)
60
+ multi_json (>= 1.3.6)
61
+ multi_json (1.8.1)
62
+ multi_xml (0.5.5)
63
+ multipart-post (1.2.0)
64
+ nokogiri (1.5.10)
65
+ oauth2 (0.9.2)
66
+ faraday (~> 0.8)
67
+ httpauth (~> 0.2)
68
+ jwt (~> 0.1.4)
69
+ multi_json (~> 1.0)
70
+ multi_xml (~> 0.5)
71
+ rack (~> 1.2)
72
+ rack (1.5.2)
73
+ rake (10.1.0)
74
+ rdoc (4.0.1)
75
+ json (~> 1.4)
76
+ redis (3.0.5)
77
+ redis-namespace (1.3.1)
78
+ redis (~> 3.0.0)
79
+ sidekiq (2.15.1)
80
+ celluloid (>= 0.15.1)
81
+ connection_pool (>= 1.0.0)
82
+ json
83
+ redis (>= 3.0.4)
84
+ redis-namespace (>= 1.3.1)
85
+ simplecov (0.7.1)
86
+ multi_json (~> 1.0)
87
+ simplecov-html (~> 0.7.1)
88
+ simplecov-console (0.1.3)
89
+ colorize
90
+ hirb
91
+ simplecov
92
+ simplecov-html (0.7.1)
93
+ timers (1.1.0)
94
+ yard (0.8.7.2)
95
+
96
+ PLATFORMS
97
+ ruby
98
+
99
+ DEPENDENCIES
100
+ easycov
101
+ jeweler
102
+ logging
103
+ micron!
104
+ rake
105
+ sidekiq
106
+ sidekiq-recycler!
107
+ yard
@@ -0,0 +1,34 @@
1
+ # Sidekiq Recycler
2
+ Gracefully recycle sidekiq processes that use too much memory
3
+
4
+ sidekiq-recycler is a simple middleware which checks the process's RSS usage on
5
+ the completion of each job. When the usage surpasses a predefined limit, the process
6
+ will gracefully terminate. If any jobs are still running beyond a further time threshold,
7
+ they will be killed and requeued.
8
+
9
+
10
+ ## Quickstart
11
+
12
+ ```
13
+ $ gem install sidekiq-recycler
14
+ ```
15
+
16
+ ```ruby
17
+ # Add the middleware
18
+ require "sidekiq"
19
+ require "sidekiq/recycler"
20
+
21
+ Sidekiq.configure_server do |config|
22
+ config.server_middleware do |chain|
23
+ chain.add Sidekiq::Recycler, :mem_limit => 300_000, :hard_limit_sec => 300
24
+ end
25
+ end
26
+ ```
27
+
28
+
29
+ ## Configuration
30
+
31
+ Two options are exposed by the middleware:
32
+
33
+ * mem_limit: RSS usage limit, in megabytes
34
+ * hard_limit_sec: time in seconds to wait for jobs to finish, after graceful shutdown initiated
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'jeweler'
14
+
15
+ Jeweler::Tasks.new do |gemspec|
16
+ gemspec.name = "sidekiq-recycler"
17
+ gemspec.summary = "Recycle large sidekiq processes"
18
+ gemspec.description = "Gracefully recycle sidekiq processes that use too much memory"
19
+ gemspec.email = "chetan@pixelcop.net"
20
+ gemspec.homepage = "http://github.com/chetan/sidekiq-recycler"
21
+ gemspec.authors = ["Chetan Sarva"]
22
+ gemspec.license = "MIT"
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
27
+
28
+ task :default => :test
29
+
30
+ require 'yard'
31
+ YARD::Rake::YardocTask.new
32
+
33
+ require "easycov/rake"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,78 @@
1
+
2
+ module Sidekiq
3
+ class Recycler
4
+
5
+ # used to avoid race conditions when recycling
6
+ @@mutex = Mutex.new
7
+
8
+ # avoid extra spam after hard limit reached
9
+ @@recycled = false
10
+
11
+ def initialize(opts={})
12
+ @mem_limit = opts[:mem_limit] || 300_000 # default is 300mb
13
+ @hard_limit_sec = opts[:hard_limit_sec] || 300 # default to 300 sec
14
+ end
15
+
16
+ def call(worker, job, queue)
17
+ begin
18
+ yield
19
+
20
+ ensure
21
+ # check mem usage here
22
+ rss = `ps -o rss= -p #{$$}`.to_i
23
+ if rss > @mem_limit then
24
+
25
+ # handle race conditions with many jobs/threads completing
26
+ # at the same time
27
+ return if !@@mutex.try_lock or @@recycled
28
+ @@recycled = true
29
+
30
+ Sidekiq.logger.warn "Recycler threshold reached: #{rss} > #{@mem_limit}"
31
+ Sidekiq.logger.warn "Attempting to stop gracefully"
32
+
33
+ # soft_limit_sec = @soft_limit_sec
34
+ hard_limit_sec = @hard_limit_sec
35
+ launcher = nil
36
+
37
+ Thread.new do
38
+ Celluloid::Actor.all.each do |actor|
39
+ # tell sidekiq to exit gracefully
40
+ # stops accepting new work and kills all waiting ("ready") threads
41
+ if actor.kind_of? Sidekiq::Launcher then
42
+ launcher = actor
43
+ Thread.new do
44
+ actor.manager.async.stop
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Thread.new do
51
+ # wait until all threads have exited
52
+ while true do
53
+ sleep 1
54
+ next if launcher.nil?
55
+ if launcher.manager.ready.empty? and launcher.manager.busy.empty? then
56
+ Sidekiq.logger.info "All threads stopped; exiting now!"
57
+ exit
58
+ end
59
+ end
60
+ end
61
+
62
+ Thread.new do
63
+ # wait for hard limit sec then kill
64
+ sleep hard_limit_sec
65
+ Sidekiq.logger.warn "Hard limit of #{hard_limit_sec}sec reached; sending TERM signal"
66
+ if !launcher.nil? then
67
+ launcher.stop
68
+ else
69
+ Process.kill("TERM", $$)
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: sidekiq-recycler 0.1.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "sidekiq-recycler"
9
+ s.version = "0.1.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Chetan Sarva"]
13
+ s.date = "2013-10-14"
14
+ s.description = "Gracefully recycle sidekiq processes that use too much memory"
15
+ s.email = "chetan@pixelcop.net"
16
+ s.extra_rdoc_files = [
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "README.md",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "lib/sidekiq/recycler.rb",
26
+ "sidekiq-recycler.gemspec",
27
+ "test/helper.rb",
28
+ "test/support/create_jobs.rb",
29
+ "test/support/sidekiq_mock_fetcher.rb",
30
+ "test/support/workers.rb",
31
+ "test/test_recycler.rb"
32
+ ]
33
+ s.homepage = "http://github.com/chetan/sidekiq-recycler"
34
+ s.licenses = ["MIT"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = "2.1.5"
37
+ s.summary = "Recycle large sidekiq processes"
38
+
39
+ if s.respond_to? :specification_version then
40
+ s.specification_version = 4
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<sidekiq>, [">= 0"])
44
+ s.add_development_dependency(%q<rake>, [">= 0"])
45
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
46
+ s.add_development_dependency(%q<yard>, [">= 0"])
47
+ s.add_development_dependency(%q<logging>, [">= 0"])
48
+ s.add_development_dependency(%q<easycov>, [">= 0"])
49
+ s.add_development_dependency(%q<micron>, [">= 0"])
50
+ else
51
+ s.add_dependency(%q<sidekiq>, [">= 0"])
52
+ s.add_dependency(%q<rake>, [">= 0"])
53
+ s.add_dependency(%q<jeweler>, [">= 0"])
54
+ s.add_dependency(%q<yard>, [">= 0"])
55
+ s.add_dependency(%q<logging>, [">= 0"])
56
+ s.add_dependency(%q<easycov>, [">= 0"])
57
+ s.add_dependency(%q<micron>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<sidekiq>, [">= 0"])
61
+ s.add_dependency(%q<rake>, [">= 0"])
62
+ s.add_dependency(%q<jeweler>, [">= 0"])
63
+ s.add_dependency(%q<yard>, [">= 0"])
64
+ s.add_dependency(%q<logging>, [">= 0"])
65
+ s.add_dependency(%q<easycov>, [">= 0"])
66
+ s.add_dependency(%q<micron>, [">= 0"])
67
+ end
68
+ end
69
+
@@ -0,0 +1,22 @@
1
+
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require "logging"
13
+ require "micron"
14
+
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
17
+ EasyCov.path = "coverage"
18
+ EasyCov.filters << EasyCov::IGNORE_GEMS << EasyCov::IGNORE_STDLIB
19
+ EasyCov.filters << lambda { |filename|
20
+ filename =~ %r(#{EasyCov.root}/test/)
21
+ }
22
+ EasyCov.start
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../workers", __FILE__)
4
+
5
+ ForeverWorker.perform_async()
6
+
7
+ 10.times do
8
+ HardWorker.perform_async(Time.now.to_f.to_s)
9
+ end
@@ -0,0 +1,91 @@
1
+
2
+ require "thread"
3
+ require "securerandom"
4
+
5
+ class MockFetcher
6
+
7
+ UnitOfWork = Struct.new(:queue, :message) do
8
+ def acknowledge
9
+ end
10
+ def queue_name
11
+ "jobs"
12
+ end
13
+ def requeue
14
+ end
15
+ end
16
+
17
+ attr_accessor :reader, :writer
18
+
19
+ def self.instance(opts=nil)
20
+ if @inst.nil? then
21
+ @inst = self.allocate
22
+ @inst.setup
23
+ end
24
+ @inst
25
+ end
26
+
27
+ class << self
28
+ alias_method :new, :instance
29
+ end
30
+
31
+ def setup
32
+ @reader, @writer = IO.pipe
33
+ @mutex = Mutex.new
34
+ end
35
+
36
+ def retrieve_work
37
+ @mutex.synchronize {
38
+ begin
39
+ return internal_fetch()
40
+ rescue Exception => ex
41
+ $stderr.puts ex
42
+ end
43
+ }
44
+ end
45
+
46
+ def self.bulk_requeue(*args)
47
+ # noop
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def internal_fetch
54
+
55
+ data = case reader.readline.strip
56
+ when "forever"
57
+ {:jid => SecureRandom.hex(4),
58
+ :class => ForeverWorker.name, :args => []}
59
+
60
+ when "hard"
61
+ {:jid => SecureRandom.hex(4),
62
+ :class => HardWorker.name, :args => ["test"]}
63
+ end
64
+
65
+ return UnitOfWork.new("foobar", MultiJson.dump(data))
66
+ end
67
+
68
+ end
69
+
70
+ module Sidekiq
71
+ class Fetcher
72
+ def self.strategy
73
+ MockFetcher
74
+ end
75
+ end
76
+ end
77
+
78
+ Sidekiq::Logging.logger = Logging.logger[Sidekiq]
79
+
80
+ module Sidekiq
81
+ module Logging
82
+ def self.with_context(msg)
83
+ begin
84
+ ::Logging.mdc["sidekiq"] = msg
85
+ yield
86
+ ensure
87
+ ::Logging.mdc["sidekiq"] = nil
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,40 @@
1
+
2
+ require "sidekiq"
3
+ require "sidekiq/recycler"
4
+
5
+ Sidekiq.configure_server do |config|
6
+ config.server_middleware do |chain|
7
+ chain.add Sidekiq::Recycler, :mem_limit => 100_000, :hard_limit_sec => 30
8
+ end
9
+ end
10
+
11
+ class ForeverWorker
12
+ @@worked = 0
13
+ include Sidekiq::Worker
14
+ def perform()
15
+ @@worked += 1
16
+ puts "working forever!"
17
+ while true
18
+ sleep 1
19
+ end
20
+ end
21
+
22
+ def self.times_worked
23
+ @@worked
24
+ end
25
+ end
26
+
27
+ class HardWorker
28
+ @@worked = 0
29
+ @@foo = []
30
+ include Sidekiq::Worker
31
+ def perform(msg)
32
+ @@foo << "hello world" * (4**10)
33
+ puts "perform.."
34
+ @@worked += 1
35
+ end
36
+
37
+ def self.times_worked
38
+ @@worked
39
+ end
40
+ end
@@ -0,0 +1,62 @@
1
+
2
+ require "helper"
3
+
4
+ require 'celluloid'
5
+ require 'sidekiq'
6
+ require 'sidekiq'
7
+ require 'sidekiq/cli'
8
+ require 'sidekiq/launcher'
9
+ require 'support/sidekiq_mock_fetcher'
10
+ require 'support/workers'
11
+
12
+ require 'micron/test_case/redir_logging'
13
+
14
+ class TestRecycler < Micron::TestCase
15
+
16
+ include Micron::TestCase::RedirLogging
17
+ @@redir_logger = Logging.logger.root
18
+
19
+ def setup
20
+ end
21
+
22
+ def teardown
23
+ @launcher.stop
24
+ Celluloid.shutdown
25
+ end
26
+
27
+ def test_recycler
28
+
29
+ opts = {
30
+ :timeout => 0,
31
+ }
32
+ @launcher = Sidekiq::Launcher.new(opts)
33
+ @launcher.run
34
+
35
+ # do something..
36
+ MockFetcher.instance.writer.puts "forever"
37
+
38
+ sleep 1
39
+ assert_equal 1, ForeverWorker.times_worked
40
+
41
+ 2.times do
42
+ MockFetcher.instance.writer.puts "hard"
43
+ end
44
+ sleep 1
45
+ assert_equal 2, HardWorker.times_worked
46
+
47
+ 5.times do
48
+ MockFetcher.instance.writer.puts "hard"
49
+ end
50
+
51
+ while HardWorker.times_worked < 7 do
52
+ sleep 0.1
53
+ Thread.pass
54
+ end
55
+
56
+ puts "over limit?!"
57
+ sleep 1
58
+ assert_equal 0, @launcher.manager.ready.size, "waiting threads should have been stopped"
59
+ assert_equal 1, @launcher.manager.busy.size, "only one thread still busy (sleeping forever)"
60
+ end
61
+
62
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-recycler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chetan Sarva
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-14 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: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jeweler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: logging
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: easycov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: micron
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Gracefully recycle sidekiq processes that use too much memory
112
+ email: chetan@pixelcop.net
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files:
116
+ - README.md
117
+ files:
118
+ - Gemfile
119
+ - Gemfile.lock
120
+ - README.md
121
+ - Rakefile
122
+ - VERSION
123
+ - lib/sidekiq/recycler.rb
124
+ - sidekiq-recycler.gemspec
125
+ - test/helper.rb
126
+ - test/support/create_jobs.rb
127
+ - test/support/sidekiq_mock_fetcher.rb
128
+ - test/support/workers.rb
129
+ - test/test_recycler.rb
130
+ homepage: http://github.com/chetan/sidekiq-recycler
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.1.5
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: Recycle large sidekiq processes
154
+ test_files: []