EasyThrottle 0.0.1 → 0.1.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: f50c56588d5ab29db2d607f2907c5d936cff56b9a6d4b4b2ec46befecc908427
4
- data.tar.gz: 3917275880a09753c25c8487d2fb9094b690a01ab52f28e300fbe141d6cc6524
3
+ metadata.gz: 9332a078cd5d2315222eb5c21cb7b962eab5675fc37dcb3b735a363965df105e
4
+ data.tar.gz: 68bb1a74c62fb3c6a7fbaf9e943c7b1bca0c825c39c6a15b85ddd2c8349f3692
5
5
  SHA512:
6
- metadata.gz: 85e43902ecef6ead3303c67a7fe05d7fa804fcad9eb8509eb89e85a2ff334a8ceb2e06dbf5426065bf9021ccb8edcba15addfa7253875e9af76e2c02142062a6
7
- data.tar.gz: 85ea1906fcb738199be91c8bc1115e709647d63d7f543802a5786dbba1638affa15af9c9a76db574f3e972a0f74e5804719d22c26fca5e320e6f5115c7419256
6
+ metadata.gz: 42612634bbab62c840994e2f5b4593211cce22d19c69efe1ded7e6ed2b82a21e6209b725b1db71852a3175298824899dee5af6d6825de64ec34cb3c109346239
7
+ data.tar.gz: 8395d6b5e34d5db37b530a5805fb8696c88fb9e13600aa9d6537570c24ea601687446f30af4986ee24b09df37396852fd71dc4c0a4dfdc8b7b93f6874d71aa18
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .tool-versions
3
+ EasyThrottle-*.gem
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem 'redis', '>= 4.0'
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'easy_throttle/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'EasyThrottle'
7
+ s.version = EasyThrottle::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Damian Szalbierz"]
10
+ s.email = ['szalbierz.d.k@gmail.com']
11
+ s.homepage = 'https://github.com/Szalbik/easy_throttle'
12
+ s.summary = "Allows you to throttle requests to an API."
13
+ s.licenses = ['MIT']
14
+
15
+ s.add_runtime_dependency 'redis', '~> 4.0'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ['lib']
20
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyThrottle
4
+ class Configuration
5
+ attr_accessor :interval, :limit, :burst, :errors, :limits
6
+
7
+ def initialize
8
+ @interval = 60
9
+ @limit = 1
10
+ @burst = 20
11
+ @errors = [AmzSpApi::ApiError]
12
+ @limits = {}
13
+ end
14
+
15
+ def add_error(error)
16
+ @errors << error
17
+ end
18
+
19
+ # Options example: { interval: 10, limit: 1, burst: 1 }
20
+ def add_limit(endpoint, options = {})
21
+ @limits[endpoint] = options
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyThrottle
4
+ class << self
5
+ # Instantiate the Configuration singleton
6
+ # or return it. Remember that the instance
7
+ # has attribute readers so that we can access
8
+ # the configured values
9
+ def configuration
10
+ @configuration ||= Configuration.new
11
+ end
12
+
13
+ # This is the configure block definition.
14
+ # The configuration method will return the
15
+ # Configuration singleton, which is then yielded
16
+ # to the configure block. Then it's just a matter
17
+ # of using the attribute accessors we previously defined
18
+ def configure
19
+ yield(configuration)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyThrottle
4
+ class Error < StandardError
5
+ def initialize(msg: 'Rate limit exceeded', error: nil)
6
+ super
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyThrottle
4
+ VERSION = '0.1.0'
5
+ end
@@ -1,24 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
3
  require 'redis'
5
4
 
6
- class Throttler
5
+ class EasyThrottle
7
6
  DEFAULT_OPTIONS = { interval: 60, limit: 1, burst: 20 }.freeze
8
- LIMITS = {
9
- # 'endpointName' => { interval: 10, limit: 1, burst: 1 },
10
- }.freeze
11
7
 
12
8
  def self.with_throttling(endpoint, prefix, options = DEFAULT_OPTIONS, &block)
13
9
  new(endpoint, prefix, options).with_throttling { block.call }
14
10
  end
15
11
 
16
12
  def initialize(endpoint, prefix, options = DEFAULT_OPTIONS)
17
- @config = YAML.load_file('lib/config.yml')
18
13
  @endpoint = endpoint
19
14
  @prefix = prefix
20
15
  @redis = Redis.new
21
- @options = LIMITS.fetch(endpoint, options)
16
+ @options = EasyThrottle.configuration.limits.fetch(endpoint, options)
22
17
  end
23
18
 
24
19
  def with_throttling(&block)
@@ -34,7 +29,7 @@ class Throttler
34
29
  end
35
30
  end
36
31
  result
37
- rescue *config['errors'].map(&:constantize) => e
32
+ rescue EasyThrottle.configuration.errors => e
38
33
  if e.code == 429
39
34
  extend_key_duration
40
35
  retry
@@ -46,7 +41,7 @@ class Throttler
46
41
  retry
47
42
  end
48
43
 
49
- raise
44
+ raise EasyThrottle::Error.new(msg: e.message, error: e)
50
45
  end
51
46
 
52
47
  def pool
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require_relative '../lib/throttler'
5
+
6
+ class ThrottlerTest < Minitest::Test
7
+ def setup
8
+ @endpoint = 'getItemOffers'
9
+ @prefix = 'US'
10
+ @redis = Minitest::Mock.new
11
+ @options = Throttler::DEFAULT_OPTIONS
12
+ @burst_key = "#{@prefix}:#{@endpoint}:burst"
13
+ @subject = Throttler.new(@endpoint, @prefix, @options)
14
+ end
15
+
16
+ def test_initialize
17
+ assert_equal @endpoint, @subject.instance_variable_get(:@endpoint)
18
+ assert_equal @prefix, @subject.instance_variable_get(:@prefix)
19
+ assert_equal @options, @subject.instance_variable_get(:@options)
20
+ end
21
+
22
+ def test_with_throttling
23
+ block = proc { 'result' }
24
+ @redis.expect(:pttl, 0)
25
+ @redis.expect(:psetex, true)
26
+ assert_equal 'result', @subject.with_throttling(&block)
27
+ end
28
+
29
+ def test_with_throttling_when_api_error_with_code_429_occurs
30
+ block = proc { raise StandardError.new(code: 429) }
31
+ assert_raises(StandardError) { @subject.with_throttling(&block) }
32
+ assert_mock @redis
33
+ end
34
+
35
+ def test_with_throttling_when_api_error_with_code_500_occurs
36
+ block = proc { raise StandardError.new(code: 500) }
37
+ assert_raises(StandardError) { @subject.with_throttling(&block) }
38
+ assert_mock @redis
39
+ end
40
+ end
metadata CHANGED
@@ -1,38 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: EasyThrottle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damian Szalbierz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-15 00:00:00.000000000 Z
11
+ date: 2024-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.0'
27
27
  description:
28
- email: szalbierz.d.k@gmail.com
28
+ email:
29
+ - szalbierz.d.k@gmail.com
29
30
  executables: []
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
33
- - lib/config.yml
34
- - lib/throttler.rb
35
- homepage:
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - easy_throttle.gemspec
37
+ - lib/easy_throttle.rb
38
+ - lib/easy_throttle/configuration.rb
39
+ - lib/easy_throttle/easy_throttle.rb
40
+ - lib/easy_throttle/error.rb
41
+ - lib/easy_throttle/version.rb
42
+ - test/test_easy_throttle.rb
43
+ homepage: https://github.com/Szalbik/easy_throttle
36
44
  licenses:
37
45
  - MIT
38
46
  metadata: {}
@@ -51,8 +59,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
59
  - !ruby/object:Gem::Version
52
60
  version: '0'
53
61
  requirements: []
54
- rubygems_version: 3.5.5
62
+ rubygems_version: 3.3.7
55
63
  signing_key:
56
64
  specification_version: 4
57
65
  summary: Allows you to throttle requests to an API.
58
- test_files: []
66
+ test_files:
67
+ - test/test_easy_throttle.rb
data/lib/config.yml DELETED
@@ -1,3 +0,0 @@
1
- errors:
2
- - 'AmzSpApi::ApiError'
3
-