pause 0.5.0 → 0.5.1

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: 24edf9a7ae6f6e5556c6dea257d89e8bfa5dd1a4b7115436162758bf259ca36d
4
- data.tar.gz: 0f90ae2d8f9dd8678e3e1e8e9dbdbbfd0cbcde8cbf28cf35780924dc3e654b71
3
+ metadata.gz: 5e50b977e8a0291be3ffa4c7c3cd29e7e7dd4d35d7eaabf7135a50e285ba4e6e
4
+ data.tar.gz: 29090acb4bd36888191ecb05e5f233a87cf3d2f44e1c83ef5929406dee6b7568
5
5
  SHA512:
6
- metadata.gz: 2b2a54352c815d7c884a64b9953b0ea053b267903d667cceb0503e82756e4459ba766789e1fb85a5f6f079c7d9095aa720f35b464b051da7bc3818058073d91e
7
- data.tar.gz: 2a9a41a61e6402516d0f243189af152d170decd6f5e5c5831b2b5d5758d243fe02ab4840e25237b18a557be081819264ed84e70ba1ffa7e524f49a36bd7bae3a
6
+ metadata.gz: '09db81cdc48b8bc669a1a138cc00f1a2c7d230eee954551e15c09261d1caf7f2a0f465d4559e1cf0337dc5257c50585e85839365e59da35173737eed537625c5'
7
+ data.tar.gz: ade37423f09768bf16fc55c80d0252f412808b86457b4fc792efc1d86b499fcc9e346d5547f43d2a058d3f916075cf00b5e8d3fc4ad33c0232521e985ae3bc94
data/.rubocop.yml CHANGED
@@ -17,6 +17,7 @@ inherit_from: .rubocop_todo.yml
17
17
  #
18
18
  AllCops:
19
19
  NewCops: enable
20
+ TargetRubyVersion: 3.2
20
21
 
21
22
  RSpec/MultipleMemoizedHelpers:
22
23
  Enabled: false
@@ -26,3 +27,9 @@ RSpec/ExampleLength:
26
27
 
27
28
  RSpec/MultipleExpectations:
28
29
  Enabled: false
30
+
31
+ RSpec/IndexedLet:
32
+ Enabled: false
33
+
34
+ Naming/VariableNumber:
35
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased](https://github.com/kigster/pause/tree/HEAD)
4
+
5
+ [Full Changelog](https://github.com/kigster/pause/compare/v0.5.0...HEAD)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Improving test coverage by adding missing tests [\#3](https://github.com/kigster/pause/pull/3) ([kigster](https://github.com/kigster))
10
+
11
+ ## [v0.5.0](https://github.com/kigster/pause/tree/v0.5.0) (2025-02-07)
12
+
13
+ [Full Changelog](https://github.com/kigster/pause/compare/2bad44d9026e4bd24c35384d28f5945187a061f5...v0.5.0)
14
+
15
+ **Merged pull requests:**
16
+
17
+ - Adding Guthub Actions and removing Travis [\#2](https://github.com/kigster/pause/pull/2) ([kigster](https://github.com/kigster))
18
+
19
+
20
+
21
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile CHANGED
@@ -7,7 +7,6 @@ source 'https://rubygems.org'
7
7
 
8
8
  group :development, :test do
9
9
  gem 'fakeredis'
10
- gem 'guard-rspec'
11
10
  gem 'rake'
12
11
  gem 'rspec'
13
12
  gem 'rubocop'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pause (0.5.0)
4
+ pause (0.5.1)
5
5
  colored2
6
6
  redis
7
7
 
@@ -9,66 +9,20 @@ GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  ast (2.4.2)
12
- coderay (1.1.3)
13
12
  colored2 (4.0.3)
14
13
  diff-lcs (1.5.1)
15
14
  docile (1.4.1)
16
15
  fakeredis (0.9.2)
17
16
  redis (~> 4.8)
18
- ffi (1.17.1)
19
- ffi (1.17.1-aarch64-linux-gnu)
20
- ffi (1.17.1-aarch64-linux-musl)
21
- ffi (1.17.1-arm-linux-gnu)
22
- ffi (1.17.1-arm-linux-musl)
23
- ffi (1.17.1-arm64-darwin)
24
- ffi (1.17.1-x86-linux-gnu)
25
- ffi (1.17.1-x86-linux-musl)
26
- ffi (1.17.1-x86_64-darwin)
27
- ffi (1.17.1-x86_64-linux-gnu)
28
- ffi (1.17.1-x86_64-linux-musl)
29
- formatador (1.1.0)
30
- guard (2.19.1)
31
- formatador (>= 0.2.4)
32
- listen (>= 2.7, < 4.0)
33
- logger (~> 1.6)
34
- lumberjack (>= 1.0.12, < 2.0)
35
- nenv (~> 0.1)
36
- notiffany (~> 0.0)
37
- ostruct (~> 0.6)
38
- pry (>= 0.13.0)
39
- shellany (~> 0.0)
40
- thor (>= 0.18.1)
41
- guard-compat (1.2.1)
42
- guard-rspec (4.7.3)
43
- guard (~> 2.1)
44
- guard-compat (~> 1.1)
45
- rspec (>= 2.99.0, < 4.0)
46
17
  json (2.9.1)
47
18
  language_server-protocol (3.17.0.4)
48
- listen (3.9.0)
49
- rb-fsevent (~> 0.10, >= 0.10.3)
50
- rb-inotify (~> 0.9, >= 0.9.10)
51
- logger (1.6.5)
52
- lumberjack (1.2.10)
53
- method_source (1.1.0)
54
- nenv (0.3.0)
55
- notiffany (0.1.3)
56
- nenv (~> 0.1)
57
- shellany (~> 0.0)
58
- ostruct (0.6.1)
59
19
  parallel (1.26.3)
60
20
  parser (3.3.7.1)
61
21
  ast (~> 2.4.1)
62
22
  racc
63
- pry (0.15.2)
64
- coderay (~> 1.1)
65
- method_source (~> 1.0)
66
23
  racc (1.8.1)
67
24
  rainbow (3.1.1)
68
25
  rake (13.2.1)
69
- rb-fsevent (0.11.2)
70
- rb-inotify (0.11.1)
71
- ffi (~> 1.0)
72
26
  redis (4.8.1)
73
27
  regexp_parser (2.10.0)
74
28
  rspec (3.13.0)
@@ -101,14 +55,12 @@ GEM
101
55
  rubocop-rspec (3.4.0)
102
56
  rubocop (~> 1.61)
103
57
  ruby-progressbar (1.13.0)
104
- shellany (0.0.1)
105
58
  simplecov (0.22.0)
106
59
  docile (~> 1.1)
107
60
  simplecov-html (~> 0.11)
108
61
  simplecov_json_formatter (~> 0.1)
109
62
  simplecov-html (0.13.1)
110
63
  simplecov_json_formatter (0.1.4)
111
- thor (1.3.2)
112
64
  timecop (0.9.10)
113
65
  unicode-display_width (3.1.4)
114
66
  unicode-emoji (~> 4.0, >= 4.0.4)
@@ -130,7 +82,6 @@ PLATFORMS
130
82
 
131
83
  DEPENDENCIES
132
84
  fakeredis
133
- guard-rspec
134
85
  pause!
135
86
  rake
136
87
  rspec
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2018 Konstantin Gredeskoul, Atasay Gokkaya, Eric Saxby, Paul Henry
1
+ Copyright © 2013-2025 Konstantin Gredeskoul, Atasay Gokkaya, Eric Saxby, Paul Henry
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -7,11 +7,11 @@
7
7
  [![Downloads](https://img.shields.io/gem/dt/pause.svg?style=for-the-badge&color=0AF)](https://rubygems.org/gems/pause)
8
8
  [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge&color=0AF)](https://opensource.org/licenses/MIT)
9
9
 
10
- # Pause
10
+ # Pause — A Redis-backed Rate Limiter
11
11
 
12
- ## In a Nutshell
12
+ ## Overview
13
13
 
14
- **Pause** is a fast and very flexible Redis-backed rate-limiter. You can use it to track events, with
14
+ **Pause** is a fast and very flexible Redis-backed rate-limiter, written originally at [Wanelo.com](https://www.crunchbase.com/organization/wanelo). You can use it to track events, with
15
15
  rules around how often they are allowed to occur within configured time checks.
16
16
 
17
17
  Sample applications include:
@@ -139,12 +139,17 @@ Or install it yourself as:
139
139
 
140
140
  ### Configuration
141
141
 
142
- Configure Pause. This could be in a Rails initializer.
142
+ Configure Pause. This could be in a Rails initializer. At the moment, pause can only be used as a singleton, i.e. you can not use `pause` with multiple configurations, or multiple redis backends. This is something that can be rather easily fixed, if necessary.
143
143
 
144
- * resolution - The time resolution (in seconds) defining the minimum period into which action counts are
144
+ Therefore, you configure the Pause singleton with the following options:
145
+
146
+ * **redis connection parameters** - The host, port and db of the Redis instance to use.
147
+
148
+ * **resolution** - the length of time (in seconds) defining the minimum period into which action counts are
145
149
  aggregated. This defines the size of the persistent store. The higher the number, the less data needs
146
150
  to be persisted in Redis.
147
- * history - The maximum amount of time (in seconds) that data is persisted
151
+
152
+ * **history** - The maximum amount of time (in seconds) that data is persisted.
148
153
 
149
154
  ```ruby
150
155
  Pause.configure do |config|
@@ -156,12 +161,10 @@ Pause.configure do |config|
156
161
  end
157
162
  ```
158
163
 
164
+
159
165
  ### Actions
160
166
 
161
- Define local actions for your application. Actions define a scope by
162
- which they are identified in the persistent store (aka "namespace"), and a set of checks. Checks define various
163
- thresholds (`max_allowed`) against periods of time (`period_seconds`). When a threshold it triggered,
164
- the action is rate limited, and stays rate limited for the duration of `block_ttl` seconds.
167
+ Define local actions for your application. Actions define a scope by which they are identified in the persistent store (aka "namespace"), and a set of checks. Checks define various thresholds (`max_allowed`) against periods of time (`period_seconds`). When a threshold it triggered, the action is rate limited, and stays rate limited for the duration of `block_ttl` seconds.
165
168
 
166
169
  #### Checks
167
170
 
@@ -205,6 +208,7 @@ When an event occurs, you increment an instance of your action, optionally with
205
208
  In the example at the top of the README you saw how we used `#unless_rate_limited` and `#if_rate_limited` methods. These are the recommended API methods, but if you must get a finer-grained control over the actions, you can also use methods such as `#ok?`, `#rate_limited?`, `#increment!` to do manually what the block methods do already. Below is an example of this "manual" implementation:
206
209
 
207
210
  ```ruby
211
+ # app/controllers/follows_controller.rb
208
212
  class FollowsController < ApplicationController
209
213
  def create
210
214
  action = FollowAction.new(user.id)
@@ -216,6 +220,7 @@ class FollowsController < ApplicationController
216
220
  end
217
221
  end
218
222
 
223
+ # app/controlers/other_controller.rb
219
224
  class OtherController < ApplicationController
220
225
  def index
221
226
  action = OtherAction.new(params[:thing])d
@@ -237,11 +242,16 @@ while true
237
242
  action.increment!
238
243
 
239
244
  rate_limit_event = action.analyze
240
- if rate_limit_event
241
- puts rate_limit_event.identifier # which key got rate limited ("thing")
242
- puts rate_limit_event.sum # total count that triggered a rate limit
243
- puts rate_limit_event.timestamp # timestamp when rate limiting occurred
244
- puts rate_limit_event.period_check # period check object, that triggered this rate limiting event
245
+
246
+ if rate_limit_event # or action.ok?
247
+ # which key got rate limited ("thing")
248
+ rate_limit_event.identifier
249
+ # total count that triggered a rate limit
250
+ rate_limit_event.sum
251
+ # timestamp when rate limiting occurred
252
+ rate_limit_event.timestamp
253
+ # period check object, that triggered this rate limiting event
254
+ rate_limit_event.period_check
245
255
  else
246
256
  # not rate-limited, same as action.ok?
247
257
  end
@@ -327,13 +337,13 @@ The action block list is implemented as a sorted set, so it should still be usab
327
337
 
328
338
  ## Testing
329
339
 
330
- By default, `fakeredis` gem is used to emulate Redis in development. However, the same test-suite should be able to run against a real redis — however, be aware that it will flush the current db during spec run. In order to run specs against real redis, make sure you have Redis running locally on the default port, and that you are able to connect to it using `redis-cli`.
340
+ By default, `fakeredis` gem is used to emulate Redis in development.
331
341
 
332
- Please note that Travis suite, as well as the default rake task, run both.
342
+ However, the same test-suite runs against a real redis, just be aware that using real redis server running locally on 127.0.0.1 will result in a `flush` operation on the current redis db during the spec run. In order to run specs against real redis, please make sure you have Redis running locally on the default port (6379), and that you are able to connect to it using `redis-cli -p 6379 -h 127.0.0.1`.
333
343
 
334
- ### Unit Testing with Fakeredis
344
+ ### Unit Testing with FakeRedis
335
345
 
336
- Fakeredis is the default, and is also run whenever `bundle exec rspec` is executed, or `rake spec` task invoked.
346
+ The gem `fakeredis` is the default for testing, and is also run whenever `bundle exec rspec` is executed, or `rake spec` task invoked.
337
347
 
338
348
  ```bash
339
349
  bundle exec rake spec:unit
@@ -345,6 +355,16 @@ bundle exec rake spec:unit
345
355
  bundle exec rake spec:integration
346
356
  ```
347
357
 
358
+ OR
359
+
360
+ ```bash
361
+ PAUSE_REAL_REDIS=1 bundle exec rspec
362
+ ```
363
+
364
+ ### Test Coverage
365
+
366
+ At the time of this writing the gem has 100% test coverage. Please keep it that way ;)
367
+
348
368
  ## Contributing
349
369
 
350
370
  Want to make it better? Cool. Here's how:
@@ -357,9 +377,15 @@ Want to make it better? Cool. Here's how:
357
377
 
358
378
  ## Authors
359
379
 
360
- * This gem was written by Eric Saxby, Atasay Gokkaya and Konstantin Gredeskoul at Wanelo, Inc.
361
- * It's been updated and refreshed by Konstantin Gredeskoul.
380
+ * This gem was donated to Open Source by [Wanelo, Inc](https://www.crunchbase.com/organization/wanelo)
362
381
 
382
+ * The original authors are:
383
+ * [Atasay Gökkaya](https://github.com/atasay)
384
+ * [Konstantin Gredeskoul](https://github.com/kigster)
385
+ * [Eric Saxby](https://github.com/sax)
386
+ * Paul Henry
387
+
388
+ * The gem is currently maintained and kept up to date by [Konstantin Gredeskoul](https://kig.re/)
363
389
 
364
390
  Please see the [LICENSE.txt](LICENSE.txt) file for further details.
365
391
 
data/lib/pause/action.rb CHANGED
@@ -117,7 +117,7 @@ module Pause
117
117
  end
118
118
  end
119
119
 
120
- def if_rate_limited(&_block)
120
+ def if_rate_limited(&)
121
121
  check_result = analyze(recalculate: true)
122
122
  yield(check_result) unless check_result.nil?
123
123
  end
data/lib/pause/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pause
4
- VERSION = '0.5.0'
4
+ VERSION = '0.5.1'
5
5
  end
data/lib/pause.rb CHANGED
@@ -13,6 +13,14 @@ require 'pause/rate_limited_event'
13
13
 
14
14
  module Pause
15
15
  PeriodCheck = Struct.new(:period_seconds, :max_allowed, :block_ttl) do
16
+ def initialize(*args, period_seconds: nil, max_allowed: nil, block_ttl: nil)
17
+ if args.any?
18
+ super(*args)
19
+ else
20
+ super(period_seconds, max_allowed, block_ttl)
21
+ end
22
+ end
23
+
16
24
  def <=>(other)
17
25
  period_seconds <=> other.period_seconds
18
26
  end
@@ -39,12 +47,12 @@ module Pause
39
47
 
40
48
  attr_writer :adapter
41
49
 
42
- def configure(&block)
43
- @configure ||= Pause::Configuration.new.configure(&block)
50
+ def configure(&)
51
+ @configure ||= Pause::Configuration.new.configure(&)
44
52
  end
45
53
 
46
- def config(&block)
47
- configure(&block)
54
+ def config(&)
55
+ configure(&)
48
56
  end
49
57
  end
50
58
  end
@@ -42,6 +42,10 @@ describe Pause::Analyzer do
42
42
  expect(analyzer.check(action)).to be_nil
43
43
  end
44
44
 
45
+ it 'returns nil if action is NOT rate limited' do
46
+ expect(action).not_to be_rate_limited
47
+ end
48
+
45
49
  it 'returns blocked action if action is blocked' do
46
50
  Timecop.freeze Time.now do
47
51
  5.times do
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Pause
6
+ RSpec.describe PeriodCheck do
7
+ let(:period_seconds) { 10 }
8
+ let(:max_allowed) { 2 }
9
+ let(:block_ttl) { 10 }
10
+
11
+ let(:period_check_1) do
12
+ described_class.new(
13
+ period_seconds: period_seconds,
14
+ max_allowed: max_allowed,
15
+ block_ttl: block_ttl
16
+ )
17
+ end
18
+
19
+ let(:period_check_2) do
20
+ described_class.new(
21
+ period_seconds: 2 * period_seconds,
22
+ max_allowed: 1.5 * max_allowed,
23
+ block_ttl:
24
+ )
25
+ end
26
+
27
+ describe '#==' do
28
+ let(:period_check_3) do
29
+ described_class.new(
30
+ period_seconds: 2 * period_seconds,
31
+ max_allowed: 1.5 * max_allowed,
32
+ block_ttl:
33
+ )
34
+ end
35
+
36
+ it 'is equal' do
37
+ expect(period_check_3).to eq(period_check_2)
38
+ end
39
+
40
+ it 'is not equal' do
41
+ expect(period_check_3).not_to eq(period_check_1)
42
+ end
43
+
44
+ describe '#sort' do
45
+ let(:list) { [period_check_2, period_check_1] }
46
+
47
+ it 'sorts' do
48
+ expect(list.sort).to eq([period_check_1, period_check_2])
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pause
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
@@ -10,7 +10,7 @@ authors:
10
10
  - Eric Saxby
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2025-02-07 00:00:00.000000000 Z
13
+ date: 2025-02-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: colored2
@@ -61,9 +61,9 @@ files:
61
61
  - ".rubocop.yml"
62
62
  - ".rubocop_todo.yml"
63
63
  - ".rvmrc"
64
+ - CHANGELOG.md
64
65
  - Gemfile
65
66
  - Gemfile.lock
66
- - Guardfile
67
67
  - LICENSE.txt
68
68
  - README.md
69
69
  - Rakefile
@@ -84,6 +84,7 @@ files:
84
84
  - spec/pause/configuration_spec.rb
85
85
  - spec/pause/logger_spec.rb
86
86
  - spec/pause/pause_spec.rb
87
+ - spec/pause/period_check_spec.rb
87
88
  - spec/pause/redis/adapter_spec.rb
88
89
  - spec/pause/redis/sharded_adapter_spec.rb
89
90
  - spec/spec_helper.rb
data/Guardfile DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # ^syntax detection
5
-
6
- # A sample Guardfile
7
- # More info at https://github.com/guard/guard#readme
8
-
9
- guard 'rspec' do
10
- watch(/^spanx\.gemspec/) { 'spec' }
11
- watch(%r{^lib/(.+)\.rb$}) { 'spec' }
12
-
13
- watch(%r{^spec/.+_spec\.rb$})
14
- watch('spec/spec_helper.rb') { 'spec' }
15
- watch(%r{spec/support/.*}) { 'spec' }
16
- end