sidekiq-throttled 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8ef8cce2c35072fd109e89066e293074fb125828
4
- data.tar.gz: 575ea548b4594445fd8b2532896bac87149e96ef
2
+ SHA256:
3
+ metadata.gz: 719506019ae06cb2b89b220681ca460b6446965aefd2268c3546c667e5f50fb5
4
+ data.tar.gz: 4e4a2f78b9bb978a20d4971ee9c7a78386405639d3c2a8a194d47c5e55d9ce32
5
5
  SHA512:
6
- metadata.gz: 4f5b3b2b3023f776b247e07db7959ad691990d6dbddf26c662e101b95868440dea2c3f2c81f9ed139b5b471bfdc259b6a52649957f5bd809ec508b2f53fc7488
7
- data.tar.gz: 5a898501386292385f3399ce572ea47110766e72c38dbf9ab5f57f23bca155c66c2e32cdb0c4b9adf31155b48382e96ca4a071294325cec3fc3beaa66ae9178b
6
+ metadata.gz: a0d220ca8d744ff3e211877b3f726305ed66e93a9045c402b569162e2d9d324ba6f00cbddf1f271cd33bba8ab7602bcead13e61f980576de9ec8d801e8814d29
7
+ data.tar.gz: 87b134e30aef111a955df66e48fec23df2152bb90e61063ef9737daf858d5525b5c70648519048d143c4399c47111ade2e84d7212ada43bc203cf2430ae8ad60
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /Gemfile.lock
4
+ /gemfiles/.bundle
4
5
  /gemfiles/*.gemfile.lock
5
6
  /_yardoc/
6
7
  /coverage/
@@ -51,3 +51,4 @@ gemfile:
51
51
  - gemfiles/sidekiq_4.1.gemfile
52
52
  - gemfiles/sidekiq_4.2.gemfile
53
53
  - gemfiles/sidekiq_5.0.gemfile
54
+ - gemfiles/sidekiq_5.1.gemfile
data/Appraisals CHANGED
@@ -15,3 +15,7 @@ end
15
15
  appraise "sidekiq-5.0" do
16
16
  gem "sidekiq", "~> 5.0.0"
17
17
  end
18
+
19
+ appraise "sidekiq-5.1" do
20
+ gem "sidekiq", "~> 5.1.0"
21
+ end
data/CHANGES.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.8.2 (2018-02-14)
2
+
3
+ * Extract redis LUA scripts stored procedures runner to redis-prescription gem.
4
+ ([@ixti])
5
+
6
+ * Switch to Concurrent.monotonic_time to expire elements of ExpirableList.
7
+ ([@ixti])
8
+
9
+
1
10
  ## 0.8.1 (2017-11-02)
2
11
 
3
12
  * Preload job class constant prior trying to get it's throttling strategy.
data/README.md CHANGED
@@ -181,6 +181,7 @@ This library aims to support work with following [Sidekiq][sidekiq] versions:
181
181
  * Sidekiq 4.1.x
182
182
  * Sidekiq 4.2.x
183
183
  * Sidekiq 5.0.x
184
+ * Sidekiq 5.1.x
184
185
 
185
186
 
186
187
  ## Contributing
@@ -197,10 +198,10 @@ This library aims to support work with following [Sidekiq][sidekiq] versions:
197
198
 
198
199
  ```
199
200
  bundle update
200
- appraisal install # install dependencies for all gemfiles
201
- appraisal update # update dependencies for all gemfiles
202
- appraisal rspec # run rspec against each gemfile
203
- bundle exec rubocop # run static code analysis
201
+ bundle exec appraisal install # install dependencies for all gemfiles
202
+ bundle exec appraisal update # update dependencies for all gemfiles
203
+ bundle exec appraisal rspec # run rspec against each gemfile
204
+ bundle exec rubocop # run static code analysis
204
205
  ```
205
206
 
206
207
  Don't forget to run `appraisal update` after any changes to `Gemfile`.
@@ -4,21 +4,21 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "rake"
7
- gem "redis-namespace", :require => false
7
+ gem "redis-namespace", require: false
8
8
  gem "rspec"
9
- gem "rubocop", "~> 0.47.0", :require => false
9
+ gem "rubocop", "~> 0.50.0", require: false
10
10
  gem "sidekiq", "~> 4.0.0"
11
11
 
12
12
  group :development do
13
13
  gem "byebug"
14
- gem "guard", :require => false
15
- gem "guard-rspec", :require => false
16
- gem "guard-rubocop", :require => false
14
+ gem "guard", require: false
15
+ gem "guard-rspec", require: false
16
+ gem "guard-rubocop", require: false
17
17
  end
18
18
 
19
19
  group :test do
20
20
  gem "capybara"
21
- gem "coveralls", :require => false
21
+ gem "coveralls", require: false
22
22
  gem "poltergeist"
23
23
  gem "rack-test"
24
24
  gem "simplecov", ">= 0.9"
@@ -26,4 +26,4 @@ group :test do
26
26
  gem "timecop"
27
27
  end
28
28
 
29
- gemspec :path => "../"
29
+ gemspec path: "../"
@@ -4,21 +4,21 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "rake"
7
- gem "redis-namespace", :require => false
7
+ gem "redis-namespace", require: false
8
8
  gem "rspec"
9
- gem "rubocop", "~> 0.47.0", :require => false
9
+ gem "rubocop", "~> 0.50.0", require: false
10
10
  gem "sidekiq", "~> 4.1.0"
11
11
 
12
12
  group :development do
13
13
  gem "byebug"
14
- gem "guard", :require => false
15
- gem "guard-rspec", :require => false
16
- gem "guard-rubocop", :require => false
14
+ gem "guard", require: false
15
+ gem "guard-rspec", require: false
16
+ gem "guard-rubocop", require: false
17
17
  end
18
18
 
19
19
  group :test do
20
20
  gem "capybara"
21
- gem "coveralls", :require => false
21
+ gem "coveralls", require: false
22
22
  gem "poltergeist"
23
23
  gem "rack-test"
24
24
  gem "simplecov", ">= 0.9"
@@ -26,4 +26,4 @@ group :test do
26
26
  gem "timecop"
27
27
  end
28
28
 
29
- gemspec :path => "../"
29
+ gemspec path: "../"
@@ -4,21 +4,21 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "rake"
7
- gem "redis-namespace", :require => false
7
+ gem "redis-namespace", require: false
8
8
  gem "rspec"
9
- gem "rubocop", "~> 0.47.0", :require => false
9
+ gem "rubocop", "~> 0.50.0", require: false
10
10
  gem "sidekiq", "~> 4.2.0"
11
11
 
12
12
  group :development do
13
13
  gem "byebug"
14
- gem "guard", :require => false
15
- gem "guard-rspec", :require => false
16
- gem "guard-rubocop", :require => false
14
+ gem "guard", require: false
15
+ gem "guard-rspec", require: false
16
+ gem "guard-rubocop", require: false
17
17
  end
18
18
 
19
19
  group :test do
20
20
  gem "capybara"
21
- gem "coveralls", :require => false
21
+ gem "coveralls", require: false
22
22
  gem "poltergeist"
23
23
  gem "rack-test"
24
24
  gem "simplecov", ">= 0.9"
@@ -26,4 +26,4 @@ group :test do
26
26
  gem "timecop"
27
27
  end
28
28
 
29
- gemspec :path => "../"
29
+ gemspec path: "../"
@@ -4,21 +4,21 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "rake"
7
- gem "redis-namespace", :require => false
7
+ gem "redis-namespace", require: false
8
8
  gem "rspec"
9
- gem "rubocop", "~> 0.47.0", :require => false
9
+ gem "rubocop", "~> 0.50.0", require: false
10
10
  gem "sidekiq", "~> 5.0.0"
11
11
 
12
12
  group :development do
13
13
  gem "byebug"
14
- gem "guard", :require => false
15
- gem "guard-rspec", :require => false
16
- gem "guard-rubocop", :require => false
14
+ gem "guard", require: false
15
+ gem "guard-rspec", require: false
16
+ gem "guard-rubocop", require: false
17
17
  end
18
18
 
19
19
  group :test do
20
20
  gem "capybara"
21
- gem "coveralls", :require => false
21
+ gem "coveralls", require: false
22
22
  gem "poltergeist"
23
23
  gem "rack-test"
24
24
  gem "simplecov", ">= 0.9"
@@ -26,4 +26,4 @@ group :test do
26
26
  gem "timecop"
27
27
  end
28
28
 
29
- gemspec :path => "../"
29
+ gemspec path: "../"
@@ -0,0 +1,29 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "rake"
7
+ gem "redis-namespace", require: false
8
+ gem "rspec"
9
+ gem "rubocop", "~> 0.50.0", require: false
10
+ gem "sidekiq", "~> 5.1.0"
11
+
12
+ group :development do
13
+ gem "byebug"
14
+ gem "guard", require: false
15
+ gem "guard-rspec", require: false
16
+ gem "guard-rubocop", require: false
17
+ end
18
+
19
+ group :test do
20
+ gem "capybara"
21
+ gem "coveralls", require: false
22
+ gem "poltergeist"
23
+ gem "rack-test"
24
+ gem "simplecov", ">= 0.9"
25
+ gem "sinatra", "~> 1.4", ">= 1.4.6"
26
+ gem "timecop"
27
+ end
28
+
29
+ gemspec path: "../"
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "monitor"
4
4
 
5
+ require "concurrent/utility/monotonic_time"
6
+
5
7
  module Sidekiq
6
8
  module Throttled
7
9
  # List that tracks when elements were added and enumerates over those not
@@ -10,18 +12,22 @@ module Sidekiq
10
12
  # ## Implementation
11
13
  #
12
14
  # Internally list holds an array of arrays. Thus ecah element is a tuple of
13
- # timestamp (when element was added) and element itself:
15
+ # monotonic timestamp (when element was added) and element itself:
14
16
  #
15
17
  # [
16
- # [ 1234567890.12345, "default" ],
17
- # [ 1234567890.34567, "urgent" ],
18
- # [ 1234579621.56789, "urgent" ],
18
+ # [ 123456.7890, "default" ],
19
+ # [ 123456.7891, "urgent" ],
20
+ # [ 123457.9621, "urgent" ],
19
21
  # ...
20
22
  # ]
21
23
  #
22
24
  # It does not deduplicates elements. Eviction happens only upon elements
23
25
  # retrieval (see {#each}).
24
26
  #
27
+ # @see http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#monotonic_time-class_method
28
+ # @see https://ruby-doc.org/core/Process.html#method-c-clock_gettime
29
+ # @see https://linux.die.net/man/3/clock_gettime
30
+ #
25
31
  # @private
26
32
  class ExpirableList
27
33
  include Enumerable
@@ -38,7 +44,7 @@ module Sidekiq
38
44
  # @params element [Object]
39
45
  # @return [ExpirableList] self
40
46
  def <<(element)
41
- @mon.synchronize { @arr << [Time.now.to_f, element] }
47
+ @mon.synchronize { @arr << [Concurrent.monotonic_time, element] }
42
48
  self
43
49
  end
44
50
 
@@ -52,7 +58,7 @@ module Sidekiq
52
58
  return to_enum __method__ unless block_given?
53
59
 
54
60
  @mon.synchronize do
55
- horizon = Time.now.to_f - @ttl
61
+ horizon = Concurrent.monotonic_time - @ttl
56
62
 
57
63
  # drop all elements older than horizon
58
64
  @arr.shift while @arr[0] && @arr[0][0] < horizon
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "redis/prescription"
4
+
3
5
  require "sidekiq/throttled/strategy/base"
4
- require "sidekiq/throttled/strategy/script"
5
6
 
6
7
  module Sidekiq
7
8
  module Throttled
@@ -19,7 +20,7 @@ module Sidekiq
19
20
  # PUSH(@key, @jid)
20
21
  # return 0
21
22
  # end
22
- SCRIPT = Script.read "#{__dir__}/concurrency.lua"
23
+ SCRIPT = Redis::Prescription.read "#{__dir__}/concurrency.lua"
23
24
  private_constant :SCRIPT
24
25
 
25
26
  # @param [#to_s] strategy_key
@@ -43,10 +44,12 @@ module Sidekiq
43
44
  def throttled?(jid, *job_args)
44
45
  return false unless (job_limit = limit(job_args))
45
46
 
46
- keys = [key(job_args)]
47
- args = [jid.to_s, job_limit, @ttl, Time.now.to_f]
47
+ kwargs = {
48
+ :keys => [key(job_args)],
49
+ :argv => [jid.to_s, job_limit, @ttl, Time.now.to_f]
50
+ }
48
51
 
49
- 1 == SCRIPT.eval(keys, args)
52
+ Sidekiq.redis { |redis| 1 == SCRIPT.eval(redis, kwargs) }
50
53
  end
51
54
 
52
55
  # @return [Integer] Current count of jobs
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "redis/prescription"
4
+
3
5
  require "sidekiq/throttled/strategy/base"
4
- require "sidekiq/throttled/strategy/script"
5
6
 
6
7
  module Sidekiq
7
8
  module Throttled
@@ -29,7 +30,7 @@ module Sidekiq
29
30
  #
30
31
  # increase!
31
32
  # return 0
32
- SCRIPT = Script.read "#{__dir__}/threshold.lua"
33
+ SCRIPT = Redis::Prescription.read "#{__dir__}/threshold.lua"
33
34
  private_constant :SCRIPT
34
35
 
35
36
  # @param [#to_s] strategy_key
@@ -59,10 +60,12 @@ module Sidekiq
59
60
  def throttled?(*job_args)
60
61
  return false unless (job_limit = limit(job_args))
61
62
 
62
- keys = [key(job_args)]
63
- args = [job_limit, period(job_args), Time.now.to_f]
63
+ kwargs = {
64
+ :keys => [key(job_args)],
65
+ :argv => [job_limit, period(job_args), Time.now.to_f]
66
+ }
64
67
 
65
- 1 == SCRIPT.eval(keys, args)
68
+ Sidekiq.redis { |redis| 1 == SCRIPT.eval(redis, kwargs) }
66
69
  end
67
70
 
68
71
  # @return [Integer] Current count of jobs
@@ -3,6 +3,6 @@
3
3
  module Sidekiq
4
4
  module Throttled
5
5
  # Gem version
6
- VERSION = "0.8.1"
6
+ VERSION = "0.8.2"
7
7
  end
8
8
  end
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ["lib"]
26
26
 
27
27
  spec.add_runtime_dependency "sidekiq"
28
+ spec.add_runtime_dependency "redis-prescription"
28
29
 
29
30
  spec.add_development_dependency "bundler", "~> 1.10"
30
31
  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.8.1
4
+ version: 0.8.2
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: 2017-11-02 00:00:00.000000000 Z
11
+ date: 2018-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis-prescription
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,6 +77,7 @@ files:
63
77
  - gemfiles/sidekiq_4.1.gemfile
64
78
  - gemfiles/sidekiq_4.2.gemfile
65
79
  - gemfiles/sidekiq_5.0.gemfile
80
+ - gemfiles/sidekiq_5.1.gemfile
66
81
  - lib/sidekiq/throttled.rb
67
82
  - lib/sidekiq/throttled/communicator.rb
68
83
  - lib/sidekiq/throttled/communicator/callbacks.rb
@@ -80,7 +95,6 @@ files:
80
95
  - lib/sidekiq/throttled/strategy/base.rb
81
96
  - lib/sidekiq/throttled/strategy/concurrency.lua
82
97
  - lib/sidekiq/throttled/strategy/concurrency.rb
83
- - lib/sidekiq/throttled/strategy/script.rb
84
98
  - lib/sidekiq/throttled/strategy/threshold.lua
85
99
  - lib/sidekiq/throttled/strategy/threshold.rb
86
100
  - lib/sidekiq/throttled/testing.rb
@@ -113,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
127
  version: '0'
114
128
  requirements: []
115
129
  rubyforge_project:
116
- rubygems_version: 2.6.13
130
+ rubygems_version: 2.7.3
117
131
  signing_key:
118
132
  specification_version: 4
119
133
  summary: Concurrency and threshold throttling for Sidekiq.
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "digest/sha1"
4
-
5
- require "sidekiq"
6
-
7
- module Sidekiq
8
- module Throttled
9
- class Strategy
10
- # Lua script executor for redis.
11
- #
12
- # Instead of executing script with `EVAL` everytime - loads script once
13
- # and then runs it with `EVALSHA`.
14
- #
15
- # @private
16
- class Script
17
- # Script load command
18
- LOAD = "load"
19
- private_constant :LOAD
20
-
21
- # Redis error fired when script ID is unkown
22
- NOSCRIPT = "NOSCRIPT"
23
- private_constant :NOSCRIPT
24
-
25
- # LUA script source.
26
- # @return [String]
27
- attr_reader :source
28
-
29
- # LUA script SHA1 digest.
30
- # @return [String]
31
- attr_reader :digest
32
-
33
- # @param [#to_s] source Lua script
34
- # @param [Logger] logger
35
- def initialize(source, logger: Sidekiq.logger)
36
- @source = source.to_s.strip.freeze
37
- @digest = Digest::SHA1.hexdigest(@source).freeze
38
- @logger = logger
39
- end
40
-
41
- # Loads script to redis
42
- # @return [void]
43
- def bootstrap!
44
- namespaceless_redis do |conn|
45
- digest = conn.script(LOAD, @source)
46
-
47
- # XXX: this may happen **ONLY** if script digesting will be
48
- # changed in redis, which is not likely gonna happen.
49
- unless @digest == digest
50
- if @logger
51
- @logger.warn "Unexpected script SHA1 digest: " \
52
- "#{digest.inspect} (expected: #{@digest.inspect})"
53
- end
54
-
55
- @digest = digest.freeze
56
- end
57
- end
58
- end
59
-
60
- # Executes script and returns result of execution
61
- # @return Result of script execution
62
- def eval(*args)
63
- Sidekiq.redis do |conn|
64
- begin
65
- conn.evalsha(@digest, *args)
66
- rescue => e
67
- raise unless e.message.include? NOSCRIPT
68
- bootstrap!
69
- conn.evalsha(@digest, *args)
70
- end
71
- end
72
- end
73
-
74
- # Reads given file and returns new {Script} with its contents.
75
- # @return [Script]
76
- def self.read(file)
77
- new File.read file
78
- end
79
-
80
- private
81
-
82
- # Yields real namespace-less redis client.
83
- def namespaceless_redis
84
- Sidekiq.redis do |conn|
85
- if defined?(Redis::Namespace) && conn.is_a?(Redis::Namespace)
86
- conn = conn.redis
87
- end
88
-
89
- yield conn
90
- end
91
- end
92
- end
93
- end
94
- end
95
- end