4me-sdk 1.1.5 → 1.1.6

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
  SHA1:
3
- metadata.gz: 5709d9ce126fa6349fdff96ab4a2dd1c80b8653a
4
- data.tar.gz: 56ea4d39c7dce6e5c0578f0eb5ab1bbeb154622d
3
+ metadata.gz: 2fb299375b12d3219de2b62186c08d386ab35c15
4
+ data.tar.gz: fec7a3b7d9f0da1bc33845aeb80a909941911428
5
5
  SHA512:
6
- metadata.gz: 754794a8253b590ddfd4064d2d96e9bae96597ab89c0169c6ebdb7fc8db4dd9035e7a0770be6f6644cff362a9f0dc5e061cb3992e15e6502556921bbdd997c5a
7
- data.tar.gz: 80eaad3b45968a8ca3e1ce3afa4a6750c74105ba188122e1bcaf800ea87c64ab63c88893d70ee32793bf8bc19b22a38f5cec830935c153a03ccb978c83fb1607
6
+ metadata.gz: b32a2e7eec8c40b1889ab72555586370bce6080fbff9ea74bc3bd3e7d63709fe456b73b8250a35c7a7f59f30c4755e1a9c1fd79f513372bd611a27965e513330
7
+ data.tar.gz: a8bc3da3ef888716c14d9fe44c75b22c797e4732e52314b6c1efb76c5401661877e1613d311ad675cb400a6755fce0de0f53e9799566f15cab5c4699a3b7e48a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- 4me-sdk (1.1.5)
4
+ 4me-sdk (1.1.6)
5
5
  activesupport (>= 4.2)
6
6
  gem_config (>= 0.3)
7
7
  mime-types (>= 3.0)
data/README.md CHANGED
@@ -37,13 +37,14 @@ All options available:
37
37
  * _api_token_: (**required**) The [4me API token](http://developer.4me.com/v1/#api-tokens)
38
38
  * _account_: Specify a [different account](http://developer.4me.com/v1/#multiple-accounts) to work with
39
39
  * _source_: The [source](http://developer.4me.com/v1/general/source/) used when creating new records
40
- * _max_retry_time_: maximum nr of seconds to wait for server to respond (default = 5400 = 1.5 hours)<br/>
40
+ * _max_retry_time_: maximum nr of seconds to retry a request on a failed response (default = 300 = 5 minutes)<br/>
41
41
  The sleep time between retries starts at 2 seconds and doubles after each retry, i.e.
42
- 2, 6, 18, 54, 162, 486, 1458, 4374, 13122, ... seconds.<br/>
42
+ 2, 6, 18, 54, 162, 486, 1458, ... seconds.<br/>
43
43
  Set to 0 to prevent retries.
44
44
  * _read_timeout_: [HTTP read timeout](http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#method-i-read_timeout-3D) in seconds (default = 25)
45
- * _block_at_rate_limit_: Set to `true` to block the request until the [rate limit](http://developer.4me.com/v1/#rate-limiting) is lifted, default: `false`<br/>
46
- The `Retry-After` header is used to compute when the retry should be performed. If that moment is later than the _max_retry_time_ the request will not be blocked and the throttled response is returned.
45
+ * _block_at_rate_limit_: Set to `true` to block the request until the [rate limit](http://developer.4me.com/v1/#rate-limiting) is lifted, default: `true`<br/>
46
+ The `Retry-After` header is used to compute when the retry should be performed. If that moment is later than the _max_throttle_time_ the request will not be blocked and the throttled response is returned.
47
+ * _max_throttle_time_: maximum nr of seconds to retry a request on a rate limiter (default = 3660 = 1 hour and 1 minute)<br/>
47
48
  * _proxy_host_: Define in case HTTP traffic needs to go through a proxy
48
49
  * _proxy_port_: Port of the proxy, defaults to 8080
49
50
  * _proxy_user_: Proxy user
@@ -305,10 +306,17 @@ Note that blocking for the export to finish is recommended as you will get direc
305
306
 
306
307
  ### Blocking
307
308
 
308
- By default all actions on the 4me SDK Client will block until the 4me API is accessible, see the _max_retry_time_ option in the [configuration](#configuration). This is especially helpfull for flaky internet connections.
309
+ When the currently used API token hits the [4me rate limiter](http://developer.4me.com/v1/#rate-limiting) a HTTP 429 response is returned that specifies after how many seconds the rate limit will be lifted.
309
310
 
310
- By setting the _block_at_rate_limit_ to `true` in the [configuration](#configuration) all actions will also block in case the [rate limit](http://developer.4me.com/v1/#rate-limiting) is reached. The action is retried every 5 minutes until the [rate limit](http://developer.4me.com/v1/#rate-limiting) is lifted again, which might take up to 1 hour.
311
+ If that time lies within the _max_throttle_time_ the 4me SDK Client will wait and retry the action, if not, the throttled response will be returned. You can verify if a response was throttled using:
312
+ ```
313
+ response = client.get('me')
314
+ puts response.throttled?
315
+ ```
316
+
317
+ By setting the _block_at_rate_limit_ to `false` in the [configuration](#configuration) the 4me SDK Client will never wait when a rate limit is hit.
311
318
 
319
+ Note that 4me has different rate limiters. If the intention is to only wait when the short-burst (max 20 requests in 2 seconds) rate limiter is hit, you could set the _max_throttle_time_ to e.g. 5 seconds.
312
320
 
313
321
  ### Translations
314
322
 
data/lib/sdk4me.rb CHANGED
@@ -14,10 +14,10 @@ module Sdk4me
14
14
  has :account, classes: String
15
15
  has :source, classes: String
16
16
 
17
- has :max_retry_time, classes: Integer, default: 5400
17
+ has :max_retry_time, classes: Integer, default: 300
18
18
  has :read_timeout, classes: Integer, default: 25
19
- has :block_at_rate_limit, classes: [TrueClass, FalseClass], default: false
20
-
19
+ has :block_at_rate_limit, classes: [TrueClass, FalseClass], default: true
20
+ has :max_throttle_time, classes: Integer, default: 3660
21
21
  has :proxy_host, classes: String
22
22
  has :proxy_port, classes: Integer, default: 8080
23
23
  has :proxy_user, classes: String
data/lib/sdk4me/client.rb CHANGED
@@ -300,16 +300,16 @@ module Sdk4me
300
300
  module SendWithRateLimitBlock
301
301
  # Wraps the _send method with retries when the server does not respond, see +initialize+ option +:rate_limit_block+
302
302
  def _send(request, domain = @domain, port = @port, ssl = @ssl)
303
- return super(request, domain, port, ssl) unless option(:block_at_rate_limit)
304
- now = Time.now
303
+ return super(request, domain, port, ssl) unless option(:block_at_rate_limit) && option(:max_throttle_time) > 0
304
+ now = nil
305
305
  timed_out = false
306
- # respect the max_retry_time with fallback to max 1 hour and 1 minute wait time
307
- max_retry_time = option(:max_retry_time) > 0 ? option(:max_retry_time) : 3660
308
306
  begin
309
307
  _response = super(request, domain, port, ssl)
308
+ now ||= Time.now
310
309
  if _response.throttled?
310
+ # if no Retry-After is not provided, the 4me server is very busy, wait 5 minutes
311
311
  retry_after = _response.retry_after == 0 ? 300 : [_response.retry_after, 2].max
312
- if (Time.now - now + retry_after) < max_retry_time
312
+ if (Time.now - now + retry_after) < option(:max_throttle_time)
313
313
  @logger.warn { "Request throttled, trying again in #{retry_after} seconds: #{_response.message}" }
314
314
  sleep(retry_after)
315
315
  else
@@ -328,12 +328,12 @@ module Sdk4me
328
328
  return super(request, domain, port, ssl) unless option(:max_retry_time) > 0
329
329
  retries = 0
330
330
  sleep_time = 1
331
- now = Time.now
331
+ now = nil
332
332
  timed_out = false
333
333
  begin
334
334
  _response = super(request, domain, port, ssl)
335
- # throttling is handled separately
336
- if !_response.success? && !_response.throttled?
335
+ now ||= Time.now
336
+ if _response.failure?
337
337
  sleep_time *= 2
338
338
  if (Time.now - now + sleep_time) < option(:max_retry_time)
339
339
  @logger.warn { "Request failed, retry ##{retries += 1} in #{sleep_time} seconds: #{_response.message}" }
@@ -342,7 +342,7 @@ module Sdk4me
342
342
  timed_out = true
343
343
  end
344
344
  end
345
- end while !_response.success? && !_response.throttled? && !timed_out
345
+ end while _response.failure? && !timed_out
346
346
  _response
347
347
  end
348
348
  end
@@ -59,6 +59,11 @@ module Sdk4me
59
59
  end
60
60
  alias_method :success?, :valid?
61
61
 
62
+ # +true+ in case of a HTTP 5xx error
63
+ def failure?
64
+ !success? && (@response.code.to_s.blank? || @response.code.to_s =~ /5\d\d/)
65
+ end
66
+
62
67
  # retrieve a value from the resource
63
68
  # if the JSON value is an Array a array with the value for each resource will be given
64
69
  # @param keys: a single key or a key-path separated by comma
@@ -1,5 +1,5 @@
1
1
  module Sdk4me
2
2
  class Client
3
- VERSION = '1.1.5'
3
+ VERSION = '1.1.6'
4
4
  end
5
5
  end
@@ -528,7 +528,7 @@ describe Sdk4me::Client do
528
528
  expect_log('Sending GET request to api.4me.com:443/v1/me', :debug )
529
529
  expect_log(%(Response:\n{\n "name": "my name"\n}), :debug )
530
530
 
531
- client = Sdk4me::Client.new(api_token: 'secret', block_at_rate_limit: true)
531
+ client = Sdk4me::Client.new(api_token: 'secret', block_at_rate_limit: true, max_retry_time: 500)
532
532
  allow(client).to receive(:sleep)
533
533
  response = client.get('me')
534
534
  expect(stub).to have_been_requested.times(2)
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Sdk4me::Response do
4
4
  before(:each) do
5
- @client = Sdk4me::Client.new(api_token: 'secret', max_retry_time: -1)
5
+ @client = Sdk4me::Client.new(api_token: 'secret', max_retry_time: -1, block_at_rate_limit: false)
6
6
  @person_hash = {
7
7
  addresses:[],
8
8
  contacts:[ {id: 1365, label: 'work', telephone: '7139872946'} ],
@@ -22,7 +22,6 @@ describe Sdk4me::Response do
22
22
  stub_request(:get, 'https://api.4me.com/v1/me').with(basic_auth: ['secret', 'x']).to_return(body: @person_hash.to_json)
23
23
  @response_hash = @client.get('me')
24
24
 
25
- @client = Sdk4me::Client.new(api_token: 'secret', max_retry_time: -1)
26
25
  @people_array = [
27
26
  {id: 562, name: 'John', organization: { id: 20, name: 'SDK4ME Institute'}, site: {id: 14, name: 'IT Training Facility'} },
28
27
  {id: 560, name: 'Lucas', organization: { id: 20, name: 'SDK4ME Institute', office: { name: 'The Office'}}, site: {id: 14, name: 'IT Training Facility'} },
@@ -4,15 +4,15 @@ describe Sdk4me do
4
4
  it "should define a default configuration" do
5
5
  conf = Sdk4me.configuration.current
6
6
 
7
- expect(conf.keys.sort).to eq([:account, :api_token, :api_version, :block_at_rate_limit, :ca_file, :host, :logger, :max_retry_time, :proxy_host, :proxy_password, :proxy_port, :proxy_user, :read_timeout, :source])
7
+ expect(conf.keys.sort).to eq([:account, :api_token, :api_version, :block_at_rate_limit, :ca_file, :host, :logger, :max_retry_time, :max_throttle_time, :proxy_host, :proxy_password, :proxy_port, :proxy_user, :read_timeout, :source])
8
8
 
9
9
  expect(conf[:logger].class).to eq(::Logger)
10
10
  expect(conf[:host]).to eq('https://api.4me.com')
11
11
  expect(conf[:api_version]).to eq('v1')
12
12
 
13
- expect(conf[:max_retry_time]).to eq(5400)
13
+ expect(conf[:max_retry_time]).to eq(300)
14
14
  expect(conf[:read_timeout]).to eq(25)
15
- expect(conf[:block_at_rate_limit]).to be_falsey
15
+ expect(conf[:block_at_rate_limit]).to be_truthy
16
16
 
17
17
  expect(conf[:proxy_port]).to eq(8080)
18
18
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 4me-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.5
4
+ version: 1.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - 4me
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-10 00:00:00.000000000 Z
11
+ date: 2019-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config