Skip to content

Commit 153a7c5

Browse files
authored
[ENG-125] Add support for retries with exponential backoff for rate limit errors (#7)
* chore: bump gem version to 1.3.0 * feat: add new configuration fields for retries with backoff * feat: add method to automatically retry failed requests The API call block will be called in a method that checks if the request failed or not. If the response status code falls in one of the configured status, it will make retries with exponential backoff.
1 parent 9ea7fb3 commit 153a7c5

7 files changed

Lines changed: 68 additions & 9 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ script:
88
- bundle install --path vendor/bundle
99
- bundle exec rspec
1010
- gem build stackone_hris_client.gemspec
11-
- gem install ./stackone_hris_client-1.2.2.gem
11+
- gem install ./stackone_hris_client-1.3.0.gem

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
stackone_hris_client (1.2.2)
4+
stackone_hris_client (1.3.0)
55
typhoeus (~> 1.0, >= 1.0.1)
66

77
GEM

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The documentation for the StackOne Unified API - HRIS
77
This SDK is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
88

99
- API version: 1.0.0
10-
- Package version: 1.2.2
10+
- Package version: 1.3.0
1111
- Build package: org.openapitools.codegen.languages.RubyClientCodegen
1212

1313
## Installation
@@ -23,16 +23,16 @@ gem build stackone_hris_client.gemspec
2323
Then either install the gem locally:
2424

2525
```shell
26-
gem install ./stackone_hris_client-1.2.2.gem
26+
gem install ./stackone_hris_client-1.3.0.gem
2727
```
2828

29-
(for development, run `gem install --dev ./stackone_hris_client-1.2.2.gem` to install the development dependencies)
29+
(for development, run `gem install --dev ./stackone_hris_client-1.3.0.gem` to install the development dependencies)
3030

3131
or publish the gem to a gem hosting service, e.g. [RubyGems](https://rubygems.org/).
3232

3333
Finally add this to the Gemfile:
3434

35-
gem 'stackone_hris_client', '~> 1.2.2'
35+
gem 'stackone_hris_client', '~> 1.3.0'
3636

3737
### Install from Git
3838

gem-config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ additionalProperties:
1010
gemName: "stackone_hris_client"
1111
gemRequiredRubyVersion: ">= 2.7"
1212
gemSummary: "StackOne HRIS client gem"
13-
gemVersion: "1.2.2"
13+
gemVersion: "1.3.0"
1414
library: "typhoeus"

lib/stackone_hris_client/api_client.rb

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def self.default
4646
#
4747
# @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
4848
# the data deserialized from response body (could be nil), response status code and response headers.
49-
def call_api(http_method, path, opts = {})
49+
def call_api_basic(http_method, path, opts = {})
5050
request = build_request(http_method, path, opts)
5151
response = request.run
5252

@@ -77,6 +77,12 @@ def call_api(http_method, path, opts = {})
7777
return data, response.code, response.headers
7878
end
7979

80+
def call_api(http_method, path, opts = {})
81+
retries_errors_with_exponential_backoff do
82+
return call_api_basic(http_method, path, opts)
83+
end
84+
end
85+
8086
# Builds the HTTP request
8187
#
8288
# @param [String] http_method HTTP method/verb (e.g. POST)
@@ -158,6 +164,41 @@ def build_request_body(header_params, form_params, body)
158164
data
159165
end
160166

167+
def retries_errors_with_exponential_backoff(
168+
max_retries: @config.max_retries,
169+
initial_backoff_seconds: @config.initial_backoff_seconds,
170+
max_backoff_seconds: @config.max_backoff_seconds,
171+
&block
172+
)
173+
retry_count = 0
174+
backoff_seconds = initial_backoff_seconds
175+
176+
loop do
177+
begin
178+
yield
179+
break
180+
rescue ApiError => e
181+
raise e unless @config.retry_status_codes.include? e.code
182+
183+
if @config.debugging
184+
@config.logger.debug "The error code (#{e.code}) matches retry_status_codes list. Retrying #(#{retry_count}) in #{backoff_seconds}s..."
185+
end
186+
187+
if retry_count >= max_retries
188+
if @config.debugging
189+
@config.logger.debug "Maximum number of retries (#{max_retries}) reached. Raising exception: #{e}"
190+
end
191+
192+
raise e
193+
else
194+
sleep backoff_seconds
195+
retry_count += 1
196+
backoff_seconds = [backoff_seconds * 2, max_backoff_seconds].min
197+
end
198+
end
199+
end
200+
end
201+
161202
# Save response body into a file in (the defined) temporary folder, using the filename
162203
# from the "Content-Disposition" header if provided, otherwise a random filename.
163204
# The response body is written to the file in chunks in order to handle files which

lib/stackone_hris_client/configuration.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ class Configuration
152152

153153
attr_accessor :force_ending_format
154154

155+
# Set this to customize the number of times to retry an API call when a server error occurs.
156+
attr_accessor :max_retries
157+
158+
# Set this to customize the initial number of seconds to wait before retrying an API call when a server error occurs.
159+
attr_accessor :initial_backoff_seconds
160+
161+
# Set this to customize the maximum number of seconds to keep retrying an API call when a server error occurs.
162+
attr_accessor :max_backoff_seconds
163+
164+
# Define the status codes that should be retried.
165+
attr_accessor :retry_status_codes
166+
155167
def initialize
156168
@scheme = 'https'
157169
@host = 'stackone.com'
@@ -173,6 +185,12 @@ def initialize
173185
@debugging = false
174186
@inject_format = false
175187
@force_ending_format = false
188+
189+
@max_retries = 5
190+
@initial_backoff_seconds = 1
191+
@max_backoff_seconds = 60
192+
@retry_status_codes = [429]
193+
176194
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
177195

178196
yield(self) if block_given?

lib/stackone_hris_client/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
=end
1212

1313
module StackOneHRIS
14-
VERSION = '1.2.2'
14+
VERSION = '1.3.0'
1515
end

0 commit comments

Comments
 (0)