sidekiq-throttled 0.10.0.beta → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6c32e77b9ca7aa1dd0bdad2b74c6fa795f4f660b5d7e7a8f92b16f6b419112e
4
- data.tar.gz: 8d8b4ca63ae59d184846e297fc6281f3b67f282b4f546d1ada0a002e84f65232
3
+ metadata.gz: a204bc340965b64fe16f9b896815c9b3fbf383418b0774871d90c35d4c8fb061
4
+ data.tar.gz: bb2b9681a7caf33d3418ab2f475bc0ab2f6141ed9e6609d55d680815da71c4e6
5
5
  SHA512:
6
- metadata.gz: 24159823a56f6765079ebb27b16b2a2288950a4bab13f628f2d48bd45939400c29d2c640db5af69dd2320e5b973d0a5afeda15cceb457fe90db1b69f8f81fa53
7
- data.tar.gz: 60c65d079962a86fdd02787d1ff2262ace7a31c16a751835038f9d06031f5af8d3d1bb65ec2bfd97ccf542a83cfa97da0ea2a1a70b8993c6793c8bf50fb2ab64
6
+ metadata.gz: '0801102f967a02d3a023b9d8bfe04b8d44280c5f2986182ef4a5cc6e971091afcb3fb1b6c845f382829de071e11d6a3111cb04a21b040b022b61ecac76d5a422'
7
+ data.tar.gz: 243ceeb9a791417edc07a7f697660035e52a61f3db4aefbe93508be5037d1af1932d2b3ad81886ee1b9ef8408e97f1bef8cac03b9a78d8e4c29a2197f9f927f6
@@ -8,7 +8,7 @@ require:
8
8
 
9
9
  AllCops:
10
10
  DisplayCopNames: true
11
- TargetRubyVersion: 2.3
11
+ TargetRubyVersion: 2.4
12
12
  Exclude:
13
13
  - "gemfiles/*"
14
14
 
@@ -9,8 +9,9 @@ cache: bundler
9
9
  before_install:
10
10
  - gem update --system
11
11
  - gem --version
12
- - gem install bundler --no-rdoc --no-ri
12
+ - gem install bundler
13
13
  - bundle --version
14
+ # Install pahantomjs
14
15
  - mkdir travis-phantomjs
15
16
  - wget https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2
16
17
  - tar -xvf $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -C $PWD/travis-phantomjs
@@ -19,15 +20,15 @@ before_install:
19
20
  install: bundle install --without development
20
21
 
21
22
  rvm:
22
- - 2.3
23
23
  - 2.4
24
24
  - 2.5
25
+ - 2.6
25
26
 
26
27
  matrix:
27
28
  fast_finish: true
28
29
  include:
29
30
  -
30
- rvm: 2.3
31
+ rvm: 2.4
31
32
  env: SUITE="rubocop"
32
33
  gemfile: Gemfile
33
34
 
data/CHANGES.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.10.0 (2019-06-22)
2
+
3
+ * [#60](https://github.com/sensortower/sidekiq-throttled/pull/60)
4
+ Skip throttling check in redis if limit is 0.
5
+ ([@mstruve])
6
+
7
+ * [#58](https://github.com/sensortower/sidekiq-throttled/pull/58)
8
+ Improve documentation bout TTL.
9
+ ([@ziaulrehman40])
10
+
11
+ * Improve reliability of paused queues, by resyncing list of paused queues
12
+ on schedule.
13
+ ([@ixti])
14
+
15
+
1
16
  ## 0.9.0 (2018-09-11)
2
17
 
3
18
  * Add support of Sidekiq 5.2.x
@@ -176,3 +191,5 @@
176
191
  [@palanglung]: https://github.com/palanglung
177
192
  [@azach]: https://github.com/azach
178
193
  [@iporsut]: https://github.com/iporsut
194
+ [@mstruve]: https://github.com/mstruve
195
+ [@ziaulrehman40]: https://github.com/ziaulrehman40
data/README.md CHANGED
@@ -117,6 +117,25 @@ if you are using dynamic limit/period options. Otherwise you risk getting into
117
117
  some trouble.
118
118
 
119
119
 
120
+ ### Concurrency throttling fine-tuning
121
+
122
+ Concurrency throttling is based on distributed locks. Those locks have default
123
+ time to live (TTL) set to 15 minutes. If your job takes more than 15 minutes
124
+ to finish, lock will be released and you might end up with more jobs running
125
+ concurrently than you expect.
126
+
127
+ This is done to avoid deadlocks - when by any reason (e.g. Sidekiq process was
128
+ OOM-killed) cleanup middleware wasn't executed and locks were not released.
129
+
130
+ If your job takes more than 15 minutes to complete, you can tune concurrency
131
+ lock TTL to fit your needs:
132
+
133
+ ``` ruby
134
+ # Set concurrency strategy lock TTL to 1 hour.
135
+ sidekiq_throttle(:concurrency => { :limit => 20, :ttl => 1.hour.to_i })
136
+ ```
137
+
138
+
120
139
  ## Enhanced Queues list
121
140
 
122
141
  This gem provides ability to pause/resume queues from processing by workers.
@@ -155,9 +174,9 @@ end
155
174
  This library aims to support and is [tested against][travis] the following Ruby
156
175
  versions:
157
176
 
158
- * Ruby 2.3.x
159
177
  * Ruby 2.4.x
160
178
  * Ruby 2.5.x
179
+ * Ruby 2.6.x
161
180
 
162
181
  If something doesn't work on one of these versions, it's a bug.
163
182
 
@@ -6,9 +6,11 @@ require "sidekiq"
6
6
  # internal
7
7
  require "sidekiq/throttled/version"
8
8
  require "sidekiq/throttled/communicator"
9
+ require "sidekiq/throttled/configuration"
9
10
  require "sidekiq/throttled/queues_pauser"
10
11
  require "sidekiq/throttled/registry"
11
12
  require "sidekiq/throttled/worker"
13
+ require "sidekiq/throttled/utils"
12
14
 
13
15
  # @see https://github.com/mperham/sidekiq/
14
16
  module Sidekiq
@@ -44,6 +46,13 @@ module Sidekiq
44
46
  private_constant :MUTEX
45
47
 
46
48
  class << self
49
+ include Utils
50
+
51
+ # @return [Configuration]
52
+ def configuration
53
+ @configuration ||= Configuration.new
54
+ end
55
+
47
56
  # Hooks throttler into sidekiq.
48
57
  #
49
58
  # @return [void]
@@ -99,16 +108,6 @@ module Sidekiq
99
108
  @preloaded[job] ||= constantize(job) || true
100
109
  end
101
110
  end
102
-
103
- # Resolve constant from it's name
104
- def constantize(str)
105
- str.sub(/^::/, "").split("::").inject(Object) do |const, name|
106
- const.const_get(name)
107
- end
108
- rescue
109
- Sidekiq.logger.warn { "Failed to constantize: #{str}" }
110
- nil
111
- end
112
111
  end
113
112
  end
114
113
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Throttled
5
+ # Configuration holder.
6
+ class Configuration
7
+ # Class constructor.
8
+ def initialize
9
+ reset!
10
+ end
11
+
12
+ # Reset configuration to defaults.
13
+ #
14
+ # @return [self]
15
+ def reset!
16
+ @inherit_strategies = false
17
+
18
+ self
19
+ end
20
+
21
+ # Instructs throttler to lookup strategies in parent classes, if there's
22
+ # no own strategy:
23
+ #
24
+ # class Foo
25
+ # include Sidekiq::Worker
26
+ # include Sidekiq::Worker::Throttled
27
+ #
28
+ # sidekiq_throttle :concurrency => { :limit => 42 }
29
+ # end
30
+ #
31
+ # class Bar < Foo
32
+ # end
33
+ #
34
+ # By default in the example above, `Bar` won't have throttling options.
35
+ # Set this flag to `true` to enable this lookup in initializer, after
36
+ # that `Bar` will use `Foo` throttling bucket.
37
+ def inherit_strategies=(value)
38
+ @inherit_strategies = value ? true : false
39
+ end
40
+
41
+ # Whenever throttled workers should inherit parent's strategies or not.
42
+ # Default: `false`.
43
+ #
44
+ # @return [Boolean]
45
+ def inherit_strategies?
46
+ @inherit_strategies
47
+ end
48
+ end
49
+ end
50
+ end
@@ -27,7 +27,7 @@ module Sidekiq
27
27
  # @param [#to_s]
28
28
  # @return [String]
29
29
  def normalize(queue)
30
- queue.to_s.sub(QUEUE_NAME_PREFIX_RE, "")
30
+ -queue.to_s.sub(QUEUE_NAME_PREFIX_RE, "")
31
31
  end
32
32
 
33
33
  # Prepends `queue:` prefix to given `queue` name.
@@ -38,7 +38,7 @@ module Sidekiq
38
38
  # @param [#to_s] queue Queue name
39
39
  # @return [String]
40
40
  def expand(queue)
41
- "queue:#{queue}"
41
+ -"queue:#{queue}"
42
42
  end
43
43
  end
44
44
  end
@@ -65,7 +65,10 @@ module Sidekiq
65
65
  # @private
66
66
  # @return [Array<String>]
67
67
  def filter(queues)
68
- queues - @paused_queues.to_a
68
+ @mutex.synchronize { queues - @paused_queues.to_a }
69
+ rescue => e
70
+ Sidekiq.logger.error { "[#{self.class}] Failed filter queues: #{e}" }
71
+ queues
69
72
  end
70
73
 
71
74
  # Returns list of paused queues.
@@ -2,6 +2,7 @@
2
2
 
3
3
  # internal
4
4
  require "sidekiq/throttled/strategy"
5
+ require "sidekiq/throttled/utils"
5
6
 
6
7
  module Sidekiq
7
8
  module Throttled
@@ -13,6 +14,8 @@ module Sidekiq
13
14
  @aliases = {}
14
15
 
15
16
  class << self
17
+ include Utils
18
+
16
19
  # Adds strategy to the registry.
17
20
  #
18
21
  # @note prints a warning to STDERR upon duplicate strategy name
@@ -49,12 +52,15 @@ module Sidekiq
49
52
  #
50
53
  # @overload get(name, &block)
51
54
  # Yields control to the block if requested strategy was found.
55
+ # @param [#to_s] name
52
56
  # @yieldparam [Strategy] strategy
53
57
  # @yield [strategy] Gives found strategy to the block
54
58
  # @return result of a block
55
59
  def get(name)
56
- strategy = @strategies[name.to_s] || @aliases[name.to_s]
60
+ strategy = find(name.to_s) || find_by_class(name)
61
+
57
62
  return yield strategy if strategy && block_given?
63
+
58
64
  strategy
59
65
  end
60
66
 
@@ -86,6 +92,34 @@ module Sidekiq
86
92
  yield(name, strategy) unless strategy.dynamic?
87
93
  end
88
94
  end
95
+
96
+ private
97
+
98
+ # Find strategy by it's name.
99
+ #
100
+ # @param name [String]
101
+ # @return [Strategy, nil]
102
+ def find(name)
103
+ @strategies[name] || @aliases[name]
104
+ end
105
+
106
+ # Find strategy by class or it's parents.
107
+ #
108
+ # @param name [Class, #to_s]
109
+ # @return [Strategy, nil]
110
+ def find_by_class(name)
111
+ return unless Throttled.configuration.inherit_strategies?
112
+
113
+ const = name.is_a?(Class) ? name : constantize(name)
114
+ return unless const.is_a?(Class)
115
+
116
+ const.ancestors.each do |m|
117
+ strategy = find(m.name)
118
+ return strategy if strategy
119
+ end
120
+
121
+ nil
122
+ end
89
123
  end
90
124
  end
91
125
  end
@@ -42,7 +42,9 @@ module Sidekiq
42
42
 
43
43
  # @return [Boolean] whenever job is throttled or not
44
44
  def throttled?(jid, *job_args)
45
- return false unless (job_limit = limit(job_args))
45
+ job_limit = limit(job_args)
46
+ return false unless job_limit
47
+ return true if job_limit <= 0
46
48
 
47
49
  kwargs = {
48
50
  :keys => [key(job_args)],
@@ -58,7 +58,9 @@ module Sidekiq
58
58
 
59
59
  # @return [Boolean] whenever job is throttled or not
60
60
  def throttled?(*job_args)
61
- return false unless (job_limit = limit(job_args))
61
+ job_limit = limit(job_args)
62
+ return false unless job_limit
63
+ return true if job_limit <= 0
62
64
 
63
65
  kwargs = {
64
66
  :keys => [key(job_args)],
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Throttled
5
+ module Utils
6
+ module_function
7
+
8
+ # Resolve constant from it's name
9
+ # @param name [#to_s] Constant name
10
+ # @return [Object, nil] Resolved constant or nil if failed.
11
+ def constantize(name)
12
+ name.to_s.sub(/^::/, "").split("::").inject(Object, &:const_get)
13
+ rescue NameError
14
+ Sidekiq.logger.warn { "Failed to constantize: #{name}" }
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
@@ -3,6 +3,6 @@
3
3
  module Sidekiq
4
4
  module Throttled
5
5
  # Gem version
6
- VERSION = "0.10.0.beta"
6
+ VERSION = "0.10.0"
7
7
  end
8
8
  end
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_runtime_dependency "redis-prescription"
29
29
  spec.add_runtime_dependency "sidekiq"
30
30
 
31
- spec.add_development_dependency "bundler", "~> 1.10"
31
+ spec.add_development_dependency "bundler", "~> 2.0"
32
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-throttled
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0.beta
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey V Zapparov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-27 00:00:00.000000000 Z
11
+ date: 2019-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.10'
61
+ version: '2.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.10'
68
+ version: '2.0'
69
69
  description: Concurrency and threshold throttling for Sidekiq.
70
70
  email:
71
71
  - ixti@member.fsf.org
@@ -94,6 +94,7 @@ files:
94
94
  - lib/sidekiq/throttled/communicator.rb
95
95
  - lib/sidekiq/throttled/communicator/callbacks.rb
96
96
  - lib/sidekiq/throttled/communicator/listener.rb
97
+ - lib/sidekiq/throttled/configuration.rb
97
98
  - lib/sidekiq/throttled/errors.rb
98
99
  - lib/sidekiq/throttled/expirable_list.rb
99
100
  - lib/sidekiq/throttled/fetch.rb
@@ -110,6 +111,7 @@ files:
110
111
  - lib/sidekiq/throttled/strategy/threshold.lua
111
112
  - lib/sidekiq/throttled/strategy/threshold.rb
112
113
  - lib/sidekiq/throttled/testing.rb
114
+ - lib/sidekiq/throttled/utils.rb
113
115
  - lib/sidekiq/throttled/version.rb
114
116
  - lib/sidekiq/throttled/web.rb
115
117
  - lib/sidekiq/throttled/web/queues.html.erb
@@ -134,12 +136,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
136
  version: '0'
135
137
  required_rubygems_version: !ruby/object:Gem::Requirement
136
138
  requirements:
137
- - - ">"
139
+ - - ">="
138
140
  - !ruby/object:Gem::Version
139
- version: 1.3.1
141
+ version: '0'
140
142
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.7.6
143
+ rubygems_version: 3.0.3
143
144
  signing_key:
144
145
  specification_version: 4
145
146
  summary: Concurrency and threshold throttling for Sidekiq.