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 +4 -4
- data/README.md +9 -0
- data/lib/typeform_data/client.rb +6 -3
- data/lib/typeform_data/config.rb +8 -1
- data/lib/typeform_data/requestor.rb +10 -3
- data/lib/typeform_data/utils.rb +6 -2
- data/lib/typeform_data/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3da62092341167802dd4565276637320bc9b4239
|
4
|
+
data.tar.gz: c60c7c72ddc21e7732f2ea866639f3c404879706
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/lib/typeform_data/client.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
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
|
data/lib/typeform_data/config.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 *
|
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
|
data/lib/typeform_data/utils.rb
CHANGED
@@ -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(
|
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 *
|
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
|
|
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:
|
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-
|
11
|
+
date: 2017-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|