typeform_data 2.0.0 → 3.0.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
  SHA1:
3
- metadata.gz: d70cdb5034873b422938f7cf426b0b1341a992ab
4
- data.tar.gz: a36e89135238d96c2ebe7ea0466c56fbf2f2b23f
3
+ metadata.gz: 3da62092341167802dd4565276637320bc9b4239
4
+ data.tar.gz: c60c7c72ddc21e7732f2ea866639f3c404879706
5
5
  SHA512:
6
- metadata.gz: 5ec3a03e56573d5b75fed0aff79d2f1a54dfeb176433c7afc1621e6532a76e7fb31a0ca9ca8477ca41c78ba04b9ef8b05ea4b0b5c9c88df2a7e870ea3ea47ed1
7
- data.tar.gz: 38532360add588301c0e3c3621088e72dba3ccc7758cecd1a84f43ae4eb27a4824010a32db4ae0d874088573f5a6b3fd1ebf14ec517ed3b869f989124394858a
6
+ metadata.gz: 0b423251f537bb0b5a2a041fa2a80f57ffceefd70c33c886c0fdfc4c7f8df52770148c021f03b8f7d5ee8fa3cf04b9b673ef1cdc713eeffafe154f082e6ecf72
7
+ data.tar.gz: 1ce2a17d3b448d5a0fa4a2c8aae6d2dcd22026f0590d9d1aaae0a10b652c8114d6a2be4de0bc1d3ecc5f9d9e64443123b11b56e1a2588aa44976b590b5cb4fad
data/README.md CHANGED
@@ -68,6 +68,15 @@ Unless you've encountered a bug, all exceptions raised by this gem should extend
68
68
 
69
69
  If a HTTP request to Typeform fails with an error that we expect to be transient (e.g. a 503) we retry the HTTP request up to 3 times, after waiting 1, 2 and 4 seconds. If you'd prefer a fail-fast approach, send us a PR!
70
70
 
71
+ Currently, all 404 errors are retried. This is because Typeform occasionally returns a 404 while it's waiting to achieve consistency. For more, see `lib/typeform_data/requestor.rb`.
72
+
73
+ ### Logging
74
+
75
+ This gem logs error and warning messages to $stdout by default. If you want to log to elsewhere, or in a different format, you can pass in your own logger object (anything that implements the same interface as the [default Ruby logger](https://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html)) like this:
76
+
77
+ ```
78
+ TypeformData::Client.new(api_key: 'YOUR API KEY', logger: logger)
79
+ ```
71
80
 
72
81
  ## Notes on the API
73
82
 
@@ -6,13 +6,16 @@ module TypeformData
6
6
 
7
7
  # For the sake of usability, we're breaking convention here and accepting an API key as the
8
8
  # first parameter instead of an instance of TypeformData::Config.
9
- def initialize(api_key:)
10
- @config = TypeformData::Config.new(api_key: api_key)
9
+ # @param api_key [String]
10
+ # @param logger [Object] Should implement the same API as
11
+ # https://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html)
12
+ def initialize(api_key:, logger: nil)
13
+ @config = TypeformData::Config.new(api_key: api_key, logger: logger)
11
14
  end
12
15
 
13
16
  def self.new_from_config(config)
14
17
  raise TypeformData::ArgumentError, 'Missing config' unless config
15
- new(api_key: config.api_key)
18
+ new(api_key: config.api_key, logger: config.logger)
16
19
  end
17
20
 
18
21
  # Your API key will automatically be added to the request URL as a query param, as required by
@@ -1,13 +1,20 @@
1
1
  # frozen_string_literal: true
2
+ require 'logger'
3
+
2
4
  module TypeformData
3
5
  class Config
4
6
  attr_reader :api_key
7
+ attr_reader :logger
5
8
 
6
- def initialize(api_key:)
9
+ # @param api_key [String]
10
+ # @param logger [Object] Should implement the same API as
11
+ # https://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html
12
+ def initialize(api_key:, logger: nil)
7
13
  unless api_key.is_a?(String) && api_key.length.positive?
8
14
  raise TypeformData::ArgumentError, 'An API key (as a nonempty String) is required'
9
15
  end
10
16
  @api_key = api_key
17
+ @logger = logger || Logger.new($stdout)
11
18
  end
12
19
 
13
20
  # These values were determined via URI.parse('https://api.typeform.com').
@@ -11,12 +11,19 @@ module TypeformData
11
11
 
12
12
  Errno::ECONNREFUSED,
13
13
  TypeformData::TransientResponseError,
14
+
15
+ # Sometimes it takes a while before Typeform's state becomes consistent. In particular, this
16
+ # can be an issue if you receive a webhook for a form response, then immediately request that
17
+ # response from Typeform's servers.
18
+ TypeformData::InvalidEndpointOrMissingResource,
14
19
  ].freeze
15
20
 
16
- RETRY_RESPONSE_CLASSES = [
21
+ TRANSIENT_RESPONSE_CLASSES = [
17
22
  Net::HTTPServiceUnavailable,
18
23
  Net::HTTPTooManyRequests,
19
24
  Net::HTTPBadGateway,
25
+ Net::HTTPGatewayTimeOut,
26
+ Net::HTTPInternalServerError,
20
27
  ].freeze
21
28
 
22
29
  def self.get(config, endpoint, params = nil)
@@ -34,7 +41,7 @@ module TypeformData
34
41
  params[:key] = config.api_key
35
42
 
36
43
  begin
37
- Utils.retry_with_exponential_backoff(RETRY_EXCEPTIONS, max_retries: 3) do
44
+ Utils.retry_with_exponential_backoff(config, RETRY_EXCEPTIONS, max_retries: 3) do
38
45
  request_and_validate_response(config, method_class, path, params)
39
46
  end
40
47
  rescue *RETRY_EXCEPTIONS => error
@@ -58,7 +65,7 @@ module TypeformData
58
65
  when Net::HTTPBadRequest
59
66
  raise TypeformData::BadRequest, 'Response was a Net::HTTPBadRequest with body: '\
60
67
  "#{response.body}. Your request with params: #{params} could not be processed."
61
- when *RETRY_RESPONSE_CLASSES
68
+ when *TRANSIENT_RESPONSE_CLASSES
62
69
  raise TypeformData::TransientResponseError, "Response was a #{response.class} "\
63
70
  "(code #{response.code}) with message #{response.message}"
64
71
  else
@@ -3,16 +3,20 @@ module Utils
3
3
 
4
4
  # Repeats the block until it succeeds or a limit is reached, waiting twice as long as it
5
5
  # previously did after each failure.
6
+ # @param config [TypeformData::Config]
6
7
  # @param rescued_exceptions [Class] Subclasses of Exception.
7
8
  # @param max_retries [Integer]
8
9
  # @param initial_wait [Integer] In seconds.
9
- def self.retry_with_exponential_backoff(rescued_exceptions, max_retries: 5, initial_wait: 1)
10
+ def self.retry_with_exponential_backoff(config, retry_exceptions, max_retries: 5, initial_wait: 1)
10
11
  seconds_to_wait = initial_wait
11
12
 
12
13
  max_retries.times do |iteration|
13
14
  begin
14
15
  break yield
15
- rescue *rescued_exceptions
16
+ rescue *retry_exceptions
17
+ config.logger.warn "Retry. Waiting #{seconds_to_wait}s, attempt #{iteration} of "\
18
+ "#{max_retries}."
19
+
16
20
  sleep seconds_to_wait
17
21
  seconds_to_wait *= 2
18
22
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module TypeformData
3
- VERSION = '2.0.0'
3
+ VERSION = '3.0.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typeform_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Wallace
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-10 00:00:00.000000000 Z
11
+ date: 2017-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler