ratelimitcop 1.0.1 → 1.1.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: 4e0be667d421af5154e7b84f403f06b8035155e7ee93f38a22bbeff92d022212
4
- data.tar.gz: 350a30c2bee3c06f2b43f8926a34cd4f453a15787c31f74f595b7672aca1446b
3
+ metadata.gz: ac7981e5e89bda694b6285142af637d00500a08d5745e51b9306cbf4729d9049
4
+ data.tar.gz: d047720c407c6e7305f84ec9a3e812f39f964b2ab7038d04734eb8fea31b76e4
5
5
  SHA512:
6
- metadata.gz: 2f604b755935a82868411aac1d95c5f6419c74ec0e047a3f7eee4d6734cf871dba6fc71f0cc89be001f098ea9bdfea27673aaef1fd14cbf6027f83781adef7ba
7
- data.tar.gz: 3fd73c8d828bf2e1573d8611c33f1a532383c758ea5a2651ff6fa2d4b95741a948eea4aae28f739292e34653869d37fe5ad0a3c3a62c4a0b64f64f926366b639
6
+ metadata.gz: c485ff903fdb437b49bb809932298bc6bbd2a12cc5da6bd255096e742ba6429704ca70bb6463b3f3bc724db0e3d7c97852f80c4347b194b0fb754edeaae84346
7
+ data.tar.gz: 5f09f2e566e80108c54fbb3e77c915a7faae8f4c76897e0a7b40adf225165c28bb0e7adf7b616d298660212315e4f83058608f0f4c77388e98da8a736641fd29
@@ -0,0 +1,25 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ ruby-version: ['2.7', '3.0']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
24
+ - name: Run tests
25
+ run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ # v1.1.0
4
+ * [#5](https://github.com/koffeefinance/ratelimitcop/pull/5) Simplify `initialize` method to hide bucket configs in an `options` map - [@mathu97](https://github.com/mathu97).
5
+ * [#5](https://github.com/koffeefinance/ratelimitcop/pull/5) Add `execute` method that calls `add` and blocks if rate limit is exceeded before running user's code block - [@mathu97](https://github.com/mathu97).
6
+ * [#5](https://github.com/koffeefinance/ratelimitcop/pull/5) Add `DummyAPI` class for testing purposes, that can be used to simulate a rate limited API - [@mathu97](https://github.com/mathu97).
7
+
3
8
  # v1.0.1
4
9
  * Renaming of classes to match gem name - [@mathu97](https://github.com/mathu97).
5
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ratelimitcop (1.0.1)
4
+ ratelimitcop (1.1.0)
5
5
  redis (~> 4.4)
6
6
  redis-namespace (~> 1.8.1)
7
7
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Ratelimitcop
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/ratelimitcop.svg)](https://badge.fury.io/rb/ratelimitcop)
3
+ [![Gem Version](https://badge.fury.io/rb/ratelimitcop.svg)](https://badge.fury.io/rb/ratelimitcop) ![Build Status](https://github.com/koffeefinance/ratelimitcop/actions/workflows/ruby.yml/badge.svg)
4
4
 
5
- Ratelimitcop is a redis backed rate limiter. Appropriate for use cases where in-memory rate limiting would not work (i.e rate limiting across multiple processes, servers, apps, etc).
5
+ Ratelimitcop is a Redis backed rate limiter. Appropriate for use cases where in-memory rate limiting would not work (i.e rate limiting across multiple processes, servers, apps, etc).
6
6
 
7
7
  ## Installation
8
8
 
@@ -22,7 +22,42 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ### Basic Usage
26
+
27
+ To rate limit calling a block of code, simply initialize `Ratelimitcop` with a `threshold` and `interval`, then pass the block of code to the `execute` method. `threshold` is the maximum number of requests that can be made within a timed `interval`, where `interval` is in seconds. `execute` will automatically block if the execution of your code block will exceed the given rate limit.
28
+
29
+ Note: You need let Ratelimitcop know how it can connect to your Redis instance (or it will default to `localhost`, port 6379, as per the [Redis gem docs](https://www.rubydoc.info/gems/redis#getting-started)). To do this pass your Redis connection config as a parameter when intializing Ratelimitcop. View the [Redis gem docs](https://www.rubydoc.info/gems/redis#getting-started) to see the different ways you can connect Ratelimitcop to your Redis instance.
30
+
31
+ Here is an example of an API client that uses Ratelimitcop to ensure the API's rate limits are not exceeded.
32
+
33
+ ```ruby
34
+ require `iex-ruby-client`
35
+ require `ratelimitcop`
36
+
37
+ class IEXCloudAPIClient
38
+ def initialize
39
+ # rate limit 100 calls per second
40
+ @limiter = Ratelimitcop.new(
41
+ name: 'iex_cloud_api',
42
+ threshold: 100,
43
+ interval: 1,
44
+ redis: {
45
+ url: ENV['REDIS_URL']
46
+ }
47
+ )
48
+
49
+ @client = IEX::Api::Client.new
50
+ end
51
+
52
+ def quote(ticker:)
53
+ # regardless of how this method is called it will block if the rate limit is exceeded before trying to run the code block
54
+ @limiter.execute do
55
+ res = @client.quote(URI.encode(ticker))
56
+ res
57
+ end
58
+ end
59
+ end
60
+ ```
26
61
 
27
62
  ## Development
28
63
 
data/lib/errors.rb ADDED
@@ -0,0 +1 @@
1
+ class InvalidBucketConfigError < StandardError; end
@@ -1,3 +1,3 @@
1
1
  class Ratelimitcop
2
- VERSION = '1.0.1'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
data/lib/ratelimitcop.rb CHANGED
@@ -1,23 +1,25 @@
1
1
  require 'ratelimitcop/version'
2
2
  require 'redis'
3
3
  require 'redis-namespace'
4
+ require_relative 'errors'
4
5
 
5
6
  class Ratelimitcop
6
- attr_reader :name, :threshold, :interval, :time_span, :bucket_span
7
+ attr_reader :name, :threshold, :interval
7
8
 
8
- def initialize(name:, threshold:, interval:, redis_connection: {}, time_span: 600, bucket_span: 5)
9
+ def initialize(name:, threshold:, interval:, redis: {}, options: {})
9
10
  @name = name
10
11
  @threshold = threshold
11
12
  @interval = interval
12
- @time_span = time_span
13
- @bucket_span = bucket_span
13
+ @bucket_interval = options[:bucket_interval] ||= 5
14
+ @bucket_time_span = options[:bucket_time_span] ||= 600
15
+ @bucket_span = options[:bucket_span] ||= @bucket_interval
14
16
 
15
- raise ArgumentError if @interval > @time_span || @interval < @bucket_span
17
+ raise InvalidBucketConfigError if @bucket_interval > @bucket_time_span || @bucket_interval < @bucket_span
16
18
 
17
- @redis ||= Redis::Namespace.new(:limiter, redis: Redis.new(redis_connection))
19
+ @redis ||= Redis::Namespace.new(:limiter, redis: Redis.new(redis))
18
20
 
19
- @all_buckets_count = (@time_span / @bucket_span).floor
20
- @sliding_window_buckets_count = (@interval.to_f / @bucket_span).floor
21
+ @all_buckets_count = (@bucket_time_span / @bucket_span).floor
22
+ @sliding_window_buckets_count = (@bucket_interval.to_f / @bucket_span).floor
21
23
  end
22
24
 
23
25
  def add(count: 1)
@@ -46,6 +48,13 @@ class Ratelimitcop
46
48
  end.map(&:to_i).sum
47
49
  end
48
50
 
51
+ def execute(&block)
52
+ add
53
+ exec_within_threshold do
54
+ block.call
55
+ end
56
+ end
57
+
49
58
  def exec_within_threshold
50
59
  sleep @bucket_span while exceeded?
51
60
  yield
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ratelimitcop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mathusan Selvarajah
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-17 00:00:00.000000000 Z
11
+ date: 2021-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -117,6 +117,7 @@ executables: []
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".github/workflows/ruby.yml"
120
121
  - CHANGELOG.md
121
122
  - CODE_OF_CONDUCT.md
122
123
  - Gemfile
@@ -126,6 +127,7 @@ files:
126
127
  - Rakefile
127
128
  - bin/console
128
129
  - bin/setup
130
+ - lib/errors.rb
129
131
  - lib/ratelimitcop.rb
130
132
  - lib/ratelimitcop/version.rb
131
133
  - ratelimitcop.gemspec