EasyThrottle 0.0.1

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/config.yml +3 -0
  3. data/lib/throttler.rb +73 -0
  4. metadata +58 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f50c56588d5ab29db2d607f2907c5d936cff56b9a6d4b4b2ec46befecc908427
4
+ data.tar.gz: 3917275880a09753c25c8487d2fb9094b690a01ab52f28e300fbe141d6cc6524
5
+ SHA512:
6
+ metadata.gz: 85e43902ecef6ead3303c67a7fe05d7fa804fcad9eb8509eb89e85a2ff334a8ceb2e06dbf5426065bf9021ccb8edcba15addfa7253875e9af76e2c02142062a6
7
+ data.tar.gz: 85ea1906fcb738199be91c8bc1115e709647d63d7f543802a5786dbba1638affa15af9c9a76db574f3e972a0f74e5804719d22c26fca5e320e6f5115c7419256
data/lib/config.yml ADDED
@@ -0,0 +1,3 @@
1
+ errors:
2
+ - 'AmzSpApi::ApiError'
3
+
data/lib/throttler.rb ADDED
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'redis'
5
+
6
+ class Throttler
7
+ DEFAULT_OPTIONS = { interval: 60, limit: 1, burst: 20 }.freeze
8
+ LIMITS = {
9
+ # 'endpointName' => { interval: 10, limit: 1, burst: 1 },
10
+ }.freeze
11
+
12
+ def self.with_throttling(endpoint, prefix, options = DEFAULT_OPTIONS, &block)
13
+ new(endpoint, prefix, options).with_throttling { block.call }
14
+ end
15
+
16
+ def initialize(endpoint, prefix, options = DEFAULT_OPTIONS)
17
+ @config = YAML.load_file('lib/config.yml')
18
+ @endpoint = endpoint
19
+ @prefix = prefix
20
+ @redis = Redis.new
21
+ @options = LIMITS.fetch(endpoint, options)
22
+ end
23
+
24
+ def with_throttling(&block)
25
+ retry_count ||= 0
26
+ result = nil
27
+ loop do
28
+ if pool
29
+ result = block.call
30
+
31
+ break
32
+ else
33
+ sleep 0.1
34
+ end
35
+ end
36
+ result
37
+ rescue *config['errors'].map(&:constantize) => e
38
+ if e.code == 429
39
+ extend_key_duration
40
+ retry
41
+ end
42
+
43
+ if e.code == 500
44
+ raise if (retry_count += 1) > 5
45
+ extend_key_duration
46
+ retry
47
+ end
48
+
49
+ raise
50
+ end
51
+
52
+ def pool
53
+ max_ttl = (options[:burst] - 1) * options[:interval] * 1000
54
+ burst_ttl = redis.pttl(burst_key)
55
+ burst_ttl = 0 if burst_ttl.negative?
56
+
57
+ if burst_ttl <= max_ttl
58
+ redis.psetex(burst_key, burst_ttl + options[:interval] * 1000, true)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :redis, :endpoint, :prefix, :options
65
+
66
+ def burst_key
67
+ "#{prefix}:#{endpoint}:burst"
68
+ end
69
+
70
+ def extend_key_duration
71
+ redis.psetex(burst_key, (options[:interval] + 1) * options[:burst] * 1000, true)
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: EasyThrottle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Damian Szalbierz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-03-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ description:
28
+ email: szalbierz.d.k@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/config.yml
34
+ - lib/throttler.rb
35
+ homepage:
36
+ licenses:
37
+ - MIT
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.5.5
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Allows you to throttle requests to an API.
58
+ test_files: []