ruby-limiter 2.2.2 → 2.3.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: 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