typeform_data 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|