ruby-limiter 2.2.2 → 2.3.0

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
2
  SHA256:
3
- metadata.gz: 8414ef377bee89d172c77d547a9cc0468bbfbf5a4a2b775ffa8faa137fdbed5b
4
- data.tar.gz: 9065acd27f48647174b0cce72bb919869addb4dca0e53e8b5e5d446dfaff53d0
3
+ metadata.gz: b2f455d4d68023ae8d22bffc74ea4b6ad7abff350d6eb907e64c8e7db7c46caf
4
+ data.tar.gz: 18b08614e86f69ae5f3d1cb8209b2f9a3c70364567366fd27464d3a27cad37ee
5
5
  SHA512:
6
- metadata.gz: 58dbd481ed08a6ed0ab24664c94488acb2206590de98f6cc06b4770acd797d1744a39d51a362893b7162381edc6da005ee7ec247cdec1fab4f7d9d4686da8355
7
- data.tar.gz: 90c28e01feb7964814da473d1bddbaca86a0167f9d580aa9ac3281fafff73bca8c8e7dbda4147a56fc53ad56b8f424f523c881294e888f810760ad6c47f44624
6
+ metadata.gz: 6a2e10e3516975acd55786d335431a51f85946000d35fcc4c7bc18b22dcd59d9d651d09f8c4b0af597452b8a737e797cff7d1ca141e6d8ebbc0e2e5f05b96466
7
+ data.tar.gz: '08c8276f451020a58782ac27d030be523cab952a22db219c01ee1fde303a2d3df1eb7a76a6013a5418d0986a41bfc24794a5fb2a31c1cff9e90bc4c416227b00'
@@ -0,0 +1,61 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: CI
9
+
10
+ on:
11
+ push:
12
+ branches: [ "main" ]
13
+ pull_request:
14
+ branches: [ "main" ]
15
+
16
+ permissions:
17
+ actions: read
18
+ contents: read
19
+ security-events: write
20
+
21
+ jobs:
22
+ rubocop:
23
+
24
+ runs-on: ubuntu-latest
25
+ strategy:
26
+ fail-fast: false
27
+
28
+ steps:
29
+ - uses: actions/checkout@v3
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: 3.2
34
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
35
+ - name: Rubocop run
36
+ run: |
37
+ bash -c "
38
+ bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif
39
+ [[ $? -ne 2 ]]
40
+ "
41
+ - name: Upload Sarif output
42
+ uses: github/codeql-action/upload-sarif@v2
43
+ with:
44
+ sarif_file: rubocop.sarif
45
+
46
+ tests:
47
+
48
+ runs-on: ubuntu-latest
49
+ strategy:
50
+ matrix:
51
+ ruby-version: ['3.0', '3.1', '3.2']
52
+
53
+ steps:
54
+ - uses: actions/checkout@v3
55
+ - name: Set up Ruby
56
+ uses: ruby/setup-ruby@v1
57
+ with:
58
+ ruby-version: ${{ matrix.ruby-version }}
59
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
60
+ - name: Run tests
61
+ run: bundle exec rake
@@ -0,0 +1,31 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ push:
5
+ tags: [ "v*" ]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build + Publish
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ packages: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v3
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: 3.2
21
+
22
+ - name: Publish to RubyGems
23
+ run: |
24
+ mkdir -p $HOME/.gem
25
+ touch $HOME/.gem/credentials
26
+ chmod 0600 $HOME/.gem/credentials
27
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
28
+ gem build *.gemspec
29
+ gem push *.gem
30
+ env:
31
+ RUBYGEMS_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
data/.rubocop.yml CHANGED
@@ -1,5 +1,14 @@
1
- inherit_from:
2
- - https://shopify.github.io/ruby-style-guide/rubocop.yml
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
+
4
+ require:
5
+ - rubocop-minitest
6
+ - rubocop-rake
3
7
 
4
8
  AllCops:
5
- TargetRubyVersion: 2.7
9
+ NewCops: enable
10
+ TargetRubyVersion: 3.2
11
+
12
+ Naming/FileName:
13
+ Exclude:
14
+ - 'lib/ruby-limiter.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v2.3.0
4
+
5
+ - add support for resetting RateQueue
6
+ - add support for resetting mixin-limited method
7
+
3
8
  ## v2.2.2
4
9
 
5
10
  - security update to rake 13.0.6 [CVE-2020-8130]
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source 'https://rubygems.org'
3
+ source "https://rubygems.org"
4
4
 
5
5
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Limiter [![Build Status](https://travis-ci.org/Shopify/limiter.svg?branch=master)](https://travis-ci.org/Shopify/limiter)
1
+ # Limiter [![Build Status](https://github.com/Shopify/limiter/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Shopify/limiter/actions/workflows/ci.yml)
2
2
 
3
3
  This gem implements a simple mechanism to throttle or rate-limit operations in Ruby.
4
4
 
@@ -75,6 +75,23 @@ For example: with an interval of 60 seconds and a rate of 60:
75
75
  `balanced: true`
76
76
  : We interleave each call with 1 second so we call this method every second.
77
77
 
78
+ #### Resetting a rate-limited method
79
+
80
+ There are times when it may be necessary to reset the rate limiter for a method, for example during testing.
81
+
82
+ This can be done by calling `reset_method_limit!` on the class, where "method" is replaced with the name of the method being limited.
83
+
84
+ Given the example above, the following would reset the rate limit for the `tick` method during test setup:
85
+
86
+ ``` ruby
87
+ class WidgetTest < Minitest::Test
88
+ def setup
89
+ Widget.reset_tick_limit!
90
+ end
91
+
92
+ ...
93
+ end
94
+ ```
78
95
 
79
96
  ### Advanced Usage
80
97
 
@@ -99,6 +116,18 @@ class Widget
99
116
  end
100
117
  ```
101
118
 
119
+ #### Resetting a RateQueue
120
+
121
+ In some circumstances it may be desirable to reset a rate queue, for example after invoking an API that resets an external rate limit.
122
+
123
+ This can be done by calling `reset` on the queue.
124
+
125
+ ``` ruby
126
+ ...
127
+ @queue.reset
128
+ ...
129
+ ```
130
+
102
131
  ## Development
103
132
 
104
133
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Rakefile CHANGED
@@ -10,4 +10,4 @@ Rake::TestTask.new(:test) do |t|
10
10
  t.warning = true
11
11
  end
12
12
 
13
- task default: :test
13
+ task default: :test
data/bin/console CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bundler/setup'
5
- require 'limiter'
4
+ require "bundler/setup"
5
+ require "limiter"
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
@@ -11,5 +11,5 @@ require 'limiter'
11
11
  # require 'pry'
12
12
  # Pry.start
13
13
 
14
- require 'irb'
14
+ require "irb"
15
15
  IRB.start(__FILE__)
data/bin/rake CHANGED
@@ -9,8 +9,10 @@
9
9
  #
10
10
 
11
11
  require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
13
+ "../../Gemfile",
14
+ Pathname.new(__FILE__).realpath,
15
+ )
14
16
 
15
17
  bundle_binstub = File.expand_path("../bundle", __FILE__)
16
18
 
data/bin/rubocop ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rubocop", "rubocop")
data/dev.yml CHANGED
@@ -3,8 +3,9 @@
3
3
  name: limiter
4
4
 
5
5
  up:
6
- - ruby: 2.7.3
6
+ - ruby: 3.2.2
7
7
  - bundler
8
8
 
9
9
  commands:
10
10
  test: bin/rake test
11
+ style: bin/rubocop -a
data/lib/limiter/clock.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
4
- require 'forwardable'
3
+ require "singleton"
4
+ require "forwardable"
5
5
 
6
6
  module Limiter
7
7
  class Clock
data/lib/limiter/mixin.rb CHANGED
@@ -12,7 +12,11 @@ module Limiter
12
12
  end
13
13
  end
14
14
 
15
- prepend mixin
15
+ define_singleton_method("reset_#{method}_limit!") do
16
+ queue.reset
17
+ end
18
+
19
+ prepend(mixin)
16
20
  end
17
21
  end
18
22
  end
@@ -8,10 +8,19 @@ module Limiter
8
8
  @size = size
9
9
  @interval = interval
10
10
 
11
- @ring = balanced ? balanced_ring : unbalanced_ring
12
- @head = 0
11
+ @balanced = balanced
12
+
13
13
  @mutex = Mutex.new
14
14
  @blk = blk
15
+
16
+ reset
17
+ end
18
+
19
+ def reset
20
+ @mutex.synchronize do
21
+ @ring = @balanced ? balanced_ring : unbalanced_ring
22
+ @head = 0
23
+ end
15
24
  end
16
25
 
17
26
  def shift
@@ -34,7 +43,8 @@ module Limiter
34
43
  def sleep_until(time)
35
44
  interval = time - clock.time
36
45
  return unless interval.positive?
37
- @blk.call if @blk
46
+
47
+ @blk&.call
38
48
  clock.sleep(interval)
39
49
  end
40
50
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Limiter
4
- VERSION = '2.2.2'
4
+ VERSION = "2.3.0"
5
5
  end
data/lib/limiter.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'limiter/clock'
4
- require 'limiter/mixin'
5
- require 'limiter/rate_queue'
6
- require 'limiter/version'
3
+ require "limiter/clock"
4
+ require "limiter/mixin"
5
+ require "limiter/rate_queue"
6
+ require "limiter/version"
data/lib/ruby-limiter.rb CHANGED
@@ -1 +1,3 @@
1
- require 'limiter'
1
+ # frozen_string_literal: true
2
+
3
+ require "limiter"
data/limiter.gemspec CHANGED
@@ -1,37 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'limiter/version'
5
+ require "limiter/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = 'ruby-limiter'
8
+ spec.name = "ruby-limiter"
9
9
  spec.version = Limiter::VERSION
10
- spec.authors = ['S. Brent Faulkner']
11
- spec.email = ['brent.faulkner@shopify.com']
10
+ spec.authors = ["S. Brent Faulkner"]
11
+ spec.email = ["brent.faulkner@shopify.com"]
12
12
 
13
- spec.summary = 'Simple Ruby rate limiting mechanism.'
14
- spec.homepage = 'https://github.com/Shopify/limiter'
15
- spec.license = 'MIT'
13
+ spec.summary = "Simple Ruby rate limiting mechanism."
14
+ spec.homepage = "https://github.com/Shopify/limiter"
15
+ spec.license = "MIT"
16
16
  spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
17
17
 
18
18
  if spec.respond_to?(:metadata)
19
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
20
  else
21
21
  raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
22
  end
23
23
 
24
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
+ spec.files = %x(git ls-files -z).split("\x0").reject do |f|
25
25
  f.match(%r{^(test|spec|features)/})
26
26
  end
27
- spec.bindir = 'exe'
27
+ spec.bindir = "exe"
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
- spec.require_paths = %w(lib)
29
+ spec.require_paths = ["lib"]
30
30
 
31
- spec.add_development_dependency 'bundler'
32
- spec.add_development_dependency 'minitest', '~> 5.0'
33
- spec.add_development_dependency 'minitest-focus', '~> 1.3'
34
- spec.add_development_dependency 'mocha', '~> 1.11'
35
- spec.add_development_dependency 'rake', '~> 13.0'
36
- spec.add_development_dependency 'rubocop', '~> 0.56'
31
+ spec.add_development_dependency("bundler")
32
+ spec.add_development_dependency("code-scanning-rubocop", "~> 0.6.1")
33
+ spec.add_development_dependency("minitest", "~> 5.20")
34
+ spec.add_development_dependency("minitest-focus", "~> 1.4")
35
+ spec.add_development_dependency("mocha", "~> 2.1")
36
+ spec.add_development_dependency("rake", "~> 13.0")
37
+ spec.add_development_dependency("rubocop", "~> 1.57")
38
+ spec.add_development_dependency("rubocop-minitest", "~> 0.33.0")
39
+ spec.add_development_dependency("rubocop-rake", "~> 0.6.0")
40
+ spec.add_development_dependency("rubocop-shopify", "~> 2.14")
37
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-limiter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.2
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - S. Brent Faulkner
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-15 00:00:00.000000000 Z
11
+ date: 2023-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,48 +24,62 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: code-scanning-rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.6.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: minitest
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '5.0'
47
+ version: '5.20'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '5.0'
54
+ version: '5.20'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: minitest-focus
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '1.3'
61
+ version: '1.4'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '1.3'
68
+ version: '1.4'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: mocha
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.11'
75
+ version: '2.1'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '1.11'
82
+ version: '2.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +100,56 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '0.56'
103
+ version: '1.57'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.57'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-minitest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.33.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.33.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.6.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.6.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-shopify
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '2.14'
90
146
  type: :development
91
147
  prerelease: false
92
148
  version_requirements: !ruby/object:Gem::Requirement
93
149
  requirements:
94
150
  - - "~>"
95
151
  - !ruby/object:Gem::Version
96
- version: '0.56'
152
+ version: '2.14'
97
153
  description:
98
154
  email:
99
155
  - brent.faulkner@shopify.com
@@ -101,9 +157,10 @@ executables: []
101
157
  extensions: []
102
158
  extra_rdoc_files: []
103
159
  files:
160
+ - ".github/workflows/ci.yml"
161
+ - ".github/workflows/gem-push.yml"
104
162
  - ".gitignore"
105
163
  - ".rubocop.yml"
106
- - ".travis.yml"
107
164
  - CHANGELOG.md
108
165
  - Gemfile
109
166
  - LICENSE.txt
@@ -111,6 +168,7 @@ files:
111
168
  - Rakefile
112
169
  - bin/console
113
170
  - bin/rake
171
+ - bin/rubocop
114
172
  - bin/setup
115
173
  - dev.yml
116
174
  - lib/limiter.rb
@@ -140,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
198
  - !ruby/object:Gem::Version
141
199
  version: '0'
142
200
  requirements: []
143
- rubygems_version: 3.2.20
201
+ rubygems_version: 3.4.10
144
202
  signing_key:
145
203
  specification_version: 4
146
204
  summary: Simple Ruby rate limiting mechanism.
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.6
5
- - 2.7
6
- - 3.0