rapidity 0.0.3.59007 → 0.0.4.88264

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: 40693850bff25145da969b8f51894fbb7b01dc774ab6534e38cad3c4c461cbc7
4
- data.tar.gz: be8657014c79b06a6e7191d3e2aff293720ac5e9418591d3a4e962de4e4774eb
3
+ metadata.gz: b1ce2b9094e761e73932f6a5c4e249a54ab971fc89ee735b04c7748c68d562af
4
+ data.tar.gz: b33de26c3a4c10d18b087ba4ac168a9136764429b2a988be2814a591c7b82c5a
5
5
  SHA512:
6
- metadata.gz: f18ecca6be2877265cfa7d2afa434d515668502ea820a7fa0a41c805ab59e6163acda6c52b46dddc2c8396265e05ea8947c6b2f48e4c8c4dec3544ee23ac33e0
7
- data.tar.gz: 28869c4c007d2dba9012c006c5b09ab7157d0ce592a4ad891f365c5036096c28a9b9ddb1d85d17ecf31c744be07f09cdf924a6a4d73e594f200e416e8ce24e8c
6
+ metadata.gz: 4cc96ac7a6f910293ff9d1ca0218894a04605253fb41caa627dea3593850b4e4b1bb6d9bd892733353cdcde73a23f151c08aa0b55e473a8e5533497c23876ca9
7
+ data.tar.gz: 79db7352433e17fce63344856da58107b0fd87215b1d5f5e1207ff250cb2a73e8d8f5afb8287b13f7538269ec3df061dc783f632eeb98fa6b964ae485822a6eb
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rapidity (0.0.3.59007)
4
+ rapidity (0.0.4.88264)
5
5
  activesupport
6
6
  connection_pool
7
7
  redis
@@ -58,7 +58,7 @@ GEM
58
58
  psych (3.3.2)
59
59
  public_suffix (4.0.6)
60
60
  rainbow (3.0.0)
61
- redis (4.4.0)
61
+ redis (4.7.0)
62
62
  reek (6.0.4)
63
63
  kwalify (~> 0.7.0)
64
64
  parser (~> 3.0.0)
@@ -142,4 +142,4 @@ DEPENDENCIES
142
142
  timeouter
143
143
 
144
144
  BUNDLED WITH
145
- 2.2.14
145
+ 2.2.27
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # Rapidity
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rapidity.svg)](https://rubygems.org/gems/rapidity)
4
+ [![Gem](https://img.shields.io/gem/dt/rapidity.svg)](https://rubygems.org/gems/rapidity/versions)
5
+ [![YARD](https://badgen.net/badge/YARD/doc/blue)](http://www.rubydoc.info/gems/rapidity)
6
+
7
+ [![Coverage](https://lysander.rnds.pro/api/v1/badges/rapidity_coverage.svg)](https://lysander.rnds.pro/api/v1/badges/rapidity_coverage.html)
8
+ [![Quality](https://lysander.rnds.pro/api/v1/badges/rapidity_quality.svg)](https://lysander.rnds.pro/api/v1/badges/rapidity_quality.html)
9
+ [![Outdated](https://lysander.rnds.pro/api/v1/badges/rapidity_outdated.svg)](https://lysander.rnds.pro/api/v1/badges/rapidity_outdated.html)
10
+ [![Vulnerabilities](https://lysander.rnds.pro/api/v1/badges/rapidity_vulnerable.svg)](https://lysander.rnds.pro/api/v1/badges/rapidity_vulnerable.html)
11
+
12
+ Simple but fast Redis-backed distributed rate limiter. Allows you to specify time interval and count within to limit distributed operations.
13
+
14
+ Features:
15
+
16
+ - extremly simple
17
+ - safe
18
+ - fast
19
+
20
+ ## Usage
21
+
22
+ Rapidity has two variants:
23
+
24
+ - simple `Rapidity::Limiter` to handle single distibuted counter
25
+ - complex `Rapidity::Composer` to handle multiple counters at once
26
+
27
+ ### Single conter with concurrent access
28
+
29
+ ```ruby
30
+ pool = ConnectionPool.new(size: 10) do
31
+ Redis.new(url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379'))
32
+ end
33
+
34
+ # allow no more 10 requests within 5 seconds
35
+ limiter = Rapidity::Limiter.new(pool, name: 'requests', threshold: 10, interval: 5)
36
+
37
+ loop do
38
+ # try to obtain 3 requests at once
39
+ quota = limiter.obtain(3).times do
40
+ make_request
41
+ end
42
+
43
+ if quota == 0
44
+ # no more requests allowed within interval
45
+ sleep 1
46
+ end
47
+ end
48
+
49
+ ```
50
+
51
+ ### Multiple counters
52
+
53
+ ```ruby
54
+ pool = ConnectionPool.new(size: 10) do
55
+ Redis.new(url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379'))
56
+ end
57
+
58
+ LIMITS = [
59
+ { interval: 1, threshold: 2 }, # no more 2 requests per second
60
+ { interval: 60, threshold: 200 }, # no more 200 requests per minute
61
+ { interval: 86400, threshold: 10000 } # no more 10k requests per day
62
+ ]
63
+
64
+ limiter = Rapidity::Composer.new(pool, name: 'requests', limits: LIMITS)
65
+
66
+ loop do
67
+ # try to obtain 3 requests at once
68
+ quota = limiter.obtain(3).times do
69
+ make_request
70
+ end
71
+
72
+ if quota == 0
73
+ # no more requests allowed within interval
74
+ puts limiter.remains # inspect current limits
75
+ sleep 1
76
+ end
77
+ end
78
+
79
+ ```
80
+
81
+ ## Installation
82
+
83
+ It's a gem:
84
+ ```bash
85
+ gem install rapidity
86
+ ```
87
+ There's also the wonders of [the Gemfile](http://bundler.io):
88
+ ```ruby
89
+ gem 'rapidity'
90
+ ```
91
+
92
+
@@ -29,13 +29,13 @@ module Rapidity
29
29
  # Get current counter
30
30
  # @return remaining counter value
31
31
  def remains
32
- _, result = @pool.with do |conn|
32
+ results = @pool.with do |conn|
33
33
  conn.multi do
34
34
  conn.set(key('remains'), threshold, ex: interval, nx: true)
35
35
  conn.get(key('remains'))
36
36
  end
37
37
  end
38
- result.to_i
38
+ results[1].to_i #=> conn.get(key('remains'))
39
39
  end
40
40
 
41
41
  # Obtain values from counter
@@ -43,24 +43,35 @@ module Rapidity
43
43
  def obtain(count = 5)
44
44
  count = count.abs
45
45
 
46
- _, taken = @pool.with do |conn|
46
+ results = @pool.with do |conn|
47
47
  conn.multi do
48
48
  conn.set(key('remains'), threshold, ex: interval, nx: true)
49
49
  conn.decrby(key('remains'), count)
50
50
  end
51
51
  end
52
52
 
53
+ taken = results[1].to_i #=> conn.decrby(key('remains'), count)
54
+
53
55
  if taken < 0
54
56
  overflow = taken.abs
55
57
  to_return = [count, overflow].min
56
58
 
57
- @pool.with do |conn|
59
+ results = @pool.with do |conn|
58
60
  conn.multi do
59
61
  conn.set(key('remains'), threshold - to_return, ex: interval, nx: true)
60
62
  conn.incrby(key('remains'), to_return)
63
+ conn.ttl(key('remains'))
61
64
  end
62
65
  end
63
66
 
67
+ ttl = results[2].to_i #=> conn.ttl(key('remains'))
68
+
69
+ # reset if no ttl present
70
+ if ttl == -1
71
+ STDERR.puts "ERROR[#{Time.now}]: TTL for key #{key('remains').inspect} disappeared!"
72
+ @pool.with {|c| c.expire(key('remains'), interval) }
73
+ end
74
+
64
75
  count - to_return
65
76
  else
66
77
  count
@@ -1,6 +1,6 @@
1
1
  module Rapidity
2
2
 
3
- VERSION = '0.0.3'.freeze
3
+ VERSION = '0.0.4'.freeze
4
4
 
5
5
  end
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapidity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.59007
4
+ version: 0.0.4.88264
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yurusov Vlad
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-08-04 00:00:00.000000000 Z
12
+ date: 2022-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -232,6 +232,7 @@ files:
232
232
  - Gemfile
233
233
  - Gemfile.lock
234
234
  - LICENSE
235
+ - README.md
235
236
  - lib/rapidity.rb
236
237
  - lib/rapidity/composer.rb
237
238
  - lib/rapidity/limiter.rb