ruby_rolling_rate_limiter 0.1.1 → 0.1.3

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
  SHA1:
3
- metadata.gz: 7a4d27689f6f0095e817f2ddc39e345e7a0fdb09
4
- data.tar.gz: 974182baa28ce3742660d2cc5996c40fbe19c749
3
+ metadata.gz: 707ecff1e33f4f609cc8399cdebab57ad206daca
4
+ data.tar.gz: 89273199718232705e954c41decdaa1923e10a98
5
5
  SHA512:
6
- metadata.gz: 81fb38c9de11936c994ab72b05c41b9b6679250327b9e9e17499af7b06c4f3d78d5fb69dd54894139f510e73cada103a3374b0eb1800471b3e0d214f0fe3d7ca
7
- data.tar.gz: 1cb014c36c572ce9022021c37adddb1d9500f85c0f0f76bf0e806ec07ca1a2e1bb7501a99859672ad975430b70336c100f417853877dc484e6b90d7f53290eb3
6
+ metadata.gz: 41bd11d653038fb3008c62e15289a031b3390ea797d8f38bfa1c1a602420ae5ca7c38459bc117e600b35eb2db9bc20b328ff71f82c4c91ae7d00b5bd59491a58
7
+ data.tar.gz: f683ecb68d5c63da9aa0eae3b3d1fd648f89d4ea7517f82ab39edf3cd0eb6c15ab3eacd56ecfbe50e9614ff6bce6274c3189e071b0927499f6ff3abe17a5ce6d
@@ -1,7 +1,7 @@
1
1
  require "ruby_rolling_rate_limiter/version"
2
2
  require "ruby_rolling_rate_limiter/errors"
3
3
  require "redis"
4
- require 'redis-lock'
4
+ require 'redlock'
5
5
  require "date"
6
6
 
7
7
  class RubyRollingRateLimiter
@@ -14,12 +14,13 @@ class RubyRollingRateLimiter
14
14
  @max_calls_per_interval = max_calls_per_interval
15
15
  @min_distance_between_calls_in_seconds = min_distance_between_calls_in_seconds
16
16
  @redis_connection = redis_connection
17
-
18
17
  #Check to ensure args are good.
19
18
  validate_arguments
20
19
 
21
20
  # Check Redis is there
22
21
  check_redis_is_available
22
+ # Setup the Lock Manager
23
+ @lock_manager ||= Redlock::Client.new([redis_connection])
23
24
 
24
25
  end
25
26
 
@@ -42,24 +43,40 @@ class RubyRollingRateLimiter
42
43
 
43
44
  clear_before = now - interval
44
45
  # Begin multi redis
45
- @redis_connection.lock("#{key}-lock") do |lock|
46
- @redis_connection.multi
47
- @redis_connection.zremrangebyscore(key, 0, clear_before.to_s)
48
- @redis_connection.zrange(key, 0, -1)
49
- cur = @redis_connection.exec
46
+ max_retry_counter = 0
47
+ begin
48
+ if max_retry_counter <= 100
49
+ @lock_manager.lock("#{key}-lock", 10000) do |locked|
50
+ if locked
51
+ @redis_connection.multi
52
+ @redis_connection.zremrangebyscore(key, 0, clear_before.to_s)
53
+ @redis_connection.zrange(key, 0, -1)
54
+ cur = @redis_connection.exec
50
55
 
51
- if (cur[1].count <= @max_calls_per_interval) && ((cur[1].count+call_size) <= @max_calls_per_interval) && ((@min_distance_between_calls_in_seconds * 1000 * 1000) && (now - cur[1].last.to_i) > (@min_distance_between_calls_in_seconds * 1000 * 1000))
52
- @redis_connection.multi
53
- @redis_connection.zrange(key, 0, -1)
54
- call_size.times do
55
- @redis_connection.zadd(key, now.to_s, now.to_s)
56
+ if (cur[1].count <= @max_calls_per_interval) && ((cur[1].count+call_size) <= @max_calls_per_interval) && ((@min_distance_between_calls_in_seconds * 1000 * 1000) && (now - cur[1].last.to_i) > (@min_distance_between_calls_in_seconds * 1000 * 1000))
57
+ @redis_connection.multi
58
+ @redis_connection.zrange(key, 0, -1)
59
+ call_size.times do
60
+ @redis_connection.zadd(key, now.to_s, now.to_s)
61
+ end
62
+ @redis_connection.expire(key, @interval_in_seconds)
63
+ results = @redis_connection.exec
64
+ else
65
+ results = [cur[1]]
66
+ end
67
+ else
68
+ raise Errors::LockWaiting, "Could not aquire lock"
69
+ end
56
70
  end
57
- @redis_connection.expire(key, @interval_in_seconds)
58
- results = @redis_connection.exec
59
71
  else
60
- results = [cur[1]]
72
+ raise Errors::MaxRetryReachedOnLockAcquire, "Unable to acquire lock for rate limit after 100 attempts"
61
73
  end
74
+ rescue Errors::LockWaiting
75
+ sleep 0.2
76
+ max_retry_counter +=1
77
+ retry
62
78
  end
79
+
63
80
  if results
64
81
  call_set = results[0]
65
82
  too_many_in_interval = call_set.count >= @max_calls_per_interval
@@ -2,5 +2,7 @@ class RubyRollingRateLimiter
2
2
  module Errors
3
3
  class RedisNotFound < StandardError; end
4
4
  class ArgumentInvalid < StandardError; end
5
+ class LockWaiting < StandardError; end
6
+ class MaxRetryReachedOnLockAcquire < StandardError; end
5
7
  end
6
8
  end
@@ -1,3 +1,3 @@
1
1
  class RubyRollingRateLimiter
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "bump"
29
29
 
30
30
  spec.add_runtime_dependency "redis", "~> 3.2"
31
- spec.add_runtime_dependency "mlanett-redis-lock"
31
+ spec.add_runtime_dependency "redlock", "~> 0.1.5"
32
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_rolling_rate_limiter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Kloppenborg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-07 00:00:00.000000000 Z
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,19 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.2'
83
83
  - !ruby/object:Gem::Dependency
84
- name: mlanett-redis-lock
84
+ name: redlock
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: 0.1.5
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: 0.1.5
97
97
  description: Often Redis is used for rate limiting purposes. Usually the rate limit
98
98
  packages available count how many times something happens on a certain second or
99
99
  a certain minute. When the clock ticks to the next minute, rate limit counter is