frederick_api 0.4.2 → 0.6
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 +5 -5
- data/README.md +11 -0
- data/lib/frederick_api.rb +3 -0
- data/lib/frederick_api/v2/background_job.rb +36 -0
- data/lib/frederick_api/v2/errors/errors.rb +4 -0
- data/lib/frederick_api/v2/helpers/backgroundable_parser.rb +18 -0
- data/lib/frederick_api/v2/helpers/has_many.rb +1 -1
- data/lib/frederick_api/v2/helpers/query_builder.rb +24 -14
- data/lib/frederick_api/v2/helpers/requestor.rb +58 -5
- data/lib/frederick_api/v2/resource.rb +1 -0
- data/lib/frederick_api/v2/role.rb +10 -0
- data/lib/frederick_api/v2/user.rb +2 -0
- data/lib/frederick_api/version.rb +1 -1
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9848d60ef419d88f6758574988f60f90337c64645316a0c716c12aaf497f43a9
|
4
|
+
data.tar.gz: 2e6096aeca9837b93ee25a2468bc7d3e2cf2712f6c735fb7330cf13a489f3b1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06f920d1c60e09288bb9c75ef3b9be31168b93fe24ab681c33b1e2b77fb9127172e86608da5c8f862a43965867e1e33f571a91dfb80bd768cc9b227979b084dc
|
7
|
+
data.tar.gz: 738cf8ec474b270d81e79a95499325f62f70557baf09bc16220abd4d467564ead6607bf180bb22352bd309d78fdab6ce84435863341ea8c99c89985d430939b7
|
data/README.md
CHANGED
@@ -101,3 +101,14 @@ FrederickAPI::V2::Location.with_access_token(access_token) do
|
|
101
101
|
# => [...]
|
102
102
|
end
|
103
103
|
```
|
104
|
+
### Background Jobs
|
105
|
+
|
106
|
+
FrederickAPI Gem handles asynchronous responses as suggested in
|
107
|
+
[JSONApi Recommendations](https://jsonapi.org/recommendations/#asynchronous-processing)
|
108
|
+
[Asynchronous Processing](https://jsonapi.org/recommendations/#asynchronous-processing).
|
109
|
+
Polling until the job is complete, fetching and returning the completed resource.
|
110
|
+
|
111
|
+
* A FrederickAPI::V2::Errors::BackgroundJobFailure exception is raised if the API returns
|
112
|
+
an error on an asyncronous job.
|
113
|
+
* A BackgroundJob Resource will be returned from the client in the case that a successful
|
114
|
+
job does not return a resources.
|
data/lib/frederick_api.rb
CHANGED
@@ -12,11 +12,13 @@ require 'frederick_api/v2/helpers/has_many'
|
|
12
12
|
require 'frederick_api/v2/helpers/paginator'
|
13
13
|
require 'frederick_api/v2/helpers/query_builder'
|
14
14
|
require 'frederick_api/v2/helpers/requestor'
|
15
|
+
require 'frederick_api/v2/helpers/backgroundable_parser'
|
15
16
|
require 'frederick_api/v2/resource'
|
16
17
|
require 'frederick_api/v2/public_resource'
|
17
18
|
|
18
19
|
require 'frederick_api/v2/user'
|
19
20
|
require 'frederick_api/v2/location'
|
21
|
+
require 'frederick_api/v2/background_job'
|
20
22
|
|
21
23
|
# Public resources
|
22
24
|
require 'frederick_api/v2/business_category'
|
@@ -29,6 +31,7 @@ require 'frederick_api/v2/contact_property'
|
|
29
31
|
require 'frederick_api/v2/contact_list'
|
30
32
|
require 'frederick_api/v2/contact_type'
|
31
33
|
require 'frederick_api/v2/interaction'
|
34
|
+
require 'frederick_api/v2/role'
|
32
35
|
|
33
36
|
# Namespace for all Frederick API client methods/classes
|
34
37
|
module FrederickAPI
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FrederickAPI
|
4
|
+
module V2
|
5
|
+
# V2 Frederick API async background job class for parsing
|
6
|
+
# background job responses coming from API.
|
7
|
+
class BackgroundJob < Resource
|
8
|
+
attr_accessor :response
|
9
|
+
|
10
|
+
def has_errors?
|
11
|
+
@attributes['status'] == 'error'
|
12
|
+
end
|
13
|
+
|
14
|
+
def retry_after
|
15
|
+
try_time = @response[:headers]['retry-after'].to_i
|
16
|
+
@retry_after ||= try_time > 1 ? try_time : 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def response_code
|
20
|
+
@response_code ||= @response[:status]
|
21
|
+
end
|
22
|
+
|
23
|
+
def status
|
24
|
+
@attributes['status']
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
@attributes['messages']
|
29
|
+
end
|
30
|
+
|
31
|
+
def id
|
32
|
+
@attributes['id']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -23,6 +23,10 @@ module FrederickAPI
|
|
23
23
|
class BadRequest < Error; end
|
24
24
|
class UnprocessableEntity < Error; end
|
25
25
|
|
26
|
+
# an exception class for when the server reports that a
|
27
|
+
# long running job has failed.
|
28
|
+
class BackgroundJobFailure < Error; end
|
29
|
+
|
26
30
|
ERROR_CODES = {
|
27
31
|
'400' => BadRequest,
|
28
32
|
'422' => UnprocessableEntity
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FrederickAPI
|
4
|
+
module V2
|
5
|
+
module Helpers
|
6
|
+
# Custom Parser for parsing BackgroundJob resources for FrederickAPI V2
|
7
|
+
class BackgroundableParser < ::JsonApiClient::Parsers::Parser
|
8
|
+
def self.parse(klass, response)
|
9
|
+
result_set = super(klass, response)
|
10
|
+
return result_set unless result_set&.first&.type == 'background_jobs'
|
11
|
+
result_set = super(::FrederickAPI::V2::BackgroundJob, response)
|
12
|
+
result_set&.first&.response = { headers: response.headers, status: response.status }
|
13
|
+
result_set
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -20,7 +20,7 @@ module FrederickAPI
|
|
20
20
|
def query_builder(url)
|
21
21
|
association_class.query_builder.new(
|
22
22
|
association_class,
|
23
|
-
association_class.requestor_class.new(association_class, url)
|
23
|
+
requestor: association_class.requestor_class.new(association_class, url)
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
@@ -9,9 +9,9 @@ module FrederickAPI
|
|
9
9
|
class QueryBuilder < JsonApiClient::Query::Builder
|
10
10
|
attr_reader :requestor
|
11
11
|
|
12
|
-
def initialize(klass,
|
13
|
-
super(klass)
|
14
|
-
@requestor = requestor || klass.requestor
|
12
|
+
def initialize(klass, opts = {})
|
13
|
+
super(klass, opts)
|
14
|
+
@requestor = opts[:requestor] || klass.requestor
|
15
15
|
end
|
16
16
|
|
17
17
|
def params
|
@@ -23,17 +23,6 @@ module FrederickAPI
|
|
23
23
|
.merge(additional_params)
|
24
24
|
end
|
25
25
|
|
26
|
-
def find(args = {})
|
27
|
-
case args
|
28
|
-
when Hash
|
29
|
-
where(args)
|
30
|
-
else
|
31
|
-
@primary_key = args
|
32
|
-
end
|
33
|
-
|
34
|
-
requestor.get(params)
|
35
|
-
end
|
36
|
-
|
37
26
|
def filter_params
|
38
27
|
super_filter_params = super
|
39
28
|
|
@@ -65,6 +54,27 @@ module FrederickAPI
|
|
65
54
|
{ prefix => object }
|
66
55
|
end
|
67
56
|
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def _fetch
|
61
|
+
(requestor || klass.requestor).get(params)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def _new_scope(opts = {})
|
67
|
+
self.class.new(@klass,
|
68
|
+
requestor: requestor,
|
69
|
+
primary_key: opts.fetch(:primary_key, @primary_key),
|
70
|
+
pagination_params: @pagination_params.merge(opts.fetch(:pagination_params, {})),
|
71
|
+
path_params: @path_params.merge(opts.fetch(:path_params, {})),
|
72
|
+
additional_params: @additional_params.merge(opts.fetch(:additional_params, {})),
|
73
|
+
filters: @filters.merge(opts.fetch(:filters, {})),
|
74
|
+
includes: @includes + opts.fetch(:includes, []),
|
75
|
+
orders: @orders + opts.fetch(:orders, []),
|
76
|
+
fields: @fields + opts.fetch(:fields, []))
|
77
|
+
end
|
68
78
|
end
|
69
79
|
end
|
70
80
|
end
|
@@ -7,6 +7,13 @@ module FrederickAPI
|
|
7
7
|
class Requestor < JsonApiClient::Query::Requestor
|
8
8
|
attr_reader :path
|
9
9
|
|
10
|
+
# Paths that may have an unbounded query param length so we should always use a POST
|
11
|
+
# instead of a GET to get around AWS Cloudfront limitations
|
12
|
+
GET_VIA_POST_PATHS = [
|
13
|
+
%r{^.*locations\/[^\/]+\/contacts$},
|
14
|
+
%r{^.*locations\/[^\/]+\/interactions$}
|
15
|
+
].map(&:freeze).freeze
|
16
|
+
|
10
17
|
def initialize(klass, path = nil)
|
11
18
|
@klass = klass
|
12
19
|
@path = path
|
@@ -21,15 +28,49 @@ module FrederickAPI
|
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
31
|
+
def get(params = {})
|
32
|
+
path = resource_path(params)
|
33
|
+
|
34
|
+
params.delete(klass.primary_key)
|
35
|
+
if get_via_post_path?(path)
|
36
|
+
return request(:post, path, body: params.to_json, additional_headers: { 'X-Request-Method' => 'GET' })
|
37
|
+
end
|
38
|
+
|
39
|
+
request(:get, path, params: params)
|
40
|
+
end
|
41
|
+
|
42
|
+
def linked(path)
|
43
|
+
uri = URI.parse(path)
|
44
|
+
return super unless get_via_post_path?(uri.path)
|
45
|
+
|
46
|
+
path_without_params = "#{uri.scheme}://#{uri.host}#{uri.path}"
|
47
|
+
params = uri.query ? CGI.parse(uri.query).each_with_object({}) { |(k, v), h| h[k] = v[0] } : {}
|
48
|
+
request(:post, path_without_params, params: params, additional_headers: { 'X-Request-Method' => 'GET' })
|
49
|
+
end
|
50
|
+
|
24
51
|
# Retry once on unhandled server errors
|
25
|
-
def request(type, path, params)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
52
|
+
def request(type, path, params: nil, body: nil, additional_headers: {})
|
53
|
+
headers = klass.custom_headers.merge(additional_headers)
|
54
|
+
make_request = proc do
|
55
|
+
handle_background(handle_errors(make_request(type, path, params: params, body: body, headers: headers)))
|
56
|
+
end
|
57
|
+
|
58
|
+
begin
|
59
|
+
make_request.call
|
60
|
+
rescue JsonApiClient::Errors::ConnectionError, JsonApiClient::Errors::ServerError => ex
|
61
|
+
raise ex if ex.is_a?(JsonApiClient::Errors::NotFound) || ex.is_a?(JsonApiClient::Errors::Conflict)
|
62
|
+
make_request.call
|
63
|
+
end
|
30
64
|
end
|
31
65
|
|
32
66
|
private
|
67
|
+
def handle_background(response)
|
68
|
+
return response unless
|
69
|
+
(job = response&.first).is_a?(::FrederickAPI::V2::BackgroundJob) && job.status != 'complete'
|
70
|
+
raise FrederickAPI::V2::Errors::BackgroundJobFailure, job if job.has_errors?
|
71
|
+
sleep job.retry_after
|
72
|
+
linked(job.links.attributes['self'])
|
73
|
+
end
|
33
74
|
|
34
75
|
def handle_errors(result)
|
35
76
|
return result unless result.has_errors?
|
@@ -37,6 +78,18 @@ module FrederickAPI
|
|
37
78
|
FrederickAPI::V2::Errors::Error
|
38
79
|
raise error_klass, result
|
39
80
|
end
|
81
|
+
|
82
|
+
def make_request(type, path, params:, body:, headers:)
|
83
|
+
faraday_response = connection.run(type, path, params: params, body: body, headers: headers)
|
84
|
+
return klass.parser.parse(klass, faraday_response) unless faraday_response.status == 303
|
85
|
+
linked(faraday_response.headers['location'])
|
86
|
+
rescue JsonApiClient::Errors::ClientError => ex
|
87
|
+
klass.parser.parse(klass, ex.env.response)
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_via_post_path?(path)
|
91
|
+
GET_VIA_POST_PATHS.any? { |r| r.match(path) }
|
92
|
+
end
|
40
93
|
end
|
41
94
|
end
|
42
95
|
end
|
@@ -10,6 +10,7 @@ module FrederickAPI
|
|
10
10
|
self.query_builder = FrederickAPI::V2::Helpers::QueryBuilder
|
11
11
|
self.paginator = FrederickAPI::V2::Helpers::Paginator
|
12
12
|
self.requestor_class = FrederickAPI::V2::Helpers::Requestor
|
13
|
+
self.parser = ::FrederickAPI::V2::Helpers::BackgroundableParser
|
13
14
|
|
14
15
|
attr_accessor :custom_headers
|
15
16
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frederick_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.6'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frederick Engineering
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json_api_client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.17.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.17.1
|
27
27
|
description: Ruby client for the Frederick API
|
28
28
|
email:
|
29
29
|
- tech@hirefrederick.com
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- lib/frederick_api.rb
|
37
37
|
- lib/frederick_api/configuration.rb
|
38
38
|
- lib/frederick_api/v2/automation.rb
|
39
|
+
- lib/frederick_api/v2/background_job.rb
|
39
40
|
- lib/frederick_api/v2/business_category.rb
|
40
41
|
- lib/frederick_api/v2/communication_content.rb
|
41
42
|
- lib/frederick_api/v2/contact.rb
|
@@ -43,6 +44,7 @@ files:
|
|
43
44
|
- lib/frederick_api/v2/contact_property.rb
|
44
45
|
- lib/frederick_api/v2/contact_type.rb
|
45
46
|
- lib/frederick_api/v2/errors/errors.rb
|
47
|
+
- lib/frederick_api/v2/helpers/backgroundable_parser.rb
|
46
48
|
- lib/frederick_api/v2/helpers/has_many.rb
|
47
49
|
- lib/frederick_api/v2/helpers/paginator.rb
|
48
50
|
- lib/frederick_api/v2/helpers/query_builder.rb
|
@@ -51,13 +53,14 @@ files:
|
|
51
53
|
- lib/frederick_api/v2/location.rb
|
52
54
|
- lib/frederick_api/v2/public_resource.rb
|
53
55
|
- lib/frederick_api/v2/resource.rb
|
56
|
+
- lib/frederick_api/v2/role.rb
|
54
57
|
- lib/frederick_api/v2/user.rb
|
55
58
|
- lib/frederick_api/version.rb
|
56
59
|
homepage: https://github.com/HireFrederick/frederick_api_gem
|
57
60
|
licenses:
|
58
61
|
- MIT
|
59
62
|
metadata: {}
|
60
|
-
post_install_message:
|
63
|
+
post_install_message:
|
61
64
|
rdoc_options: []
|
62
65
|
require_paths:
|
63
66
|
- lib
|
@@ -72,9 +75,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
75
|
- !ruby/object:Gem::Version
|
73
76
|
version: '0'
|
74
77
|
requirements: []
|
75
|
-
|
76
|
-
|
77
|
-
signing_key:
|
78
|
+
rubygems_version: 3.0.8
|
79
|
+
signing_key:
|
78
80
|
specification_version: 4
|
79
81
|
summary: Frederick API Client
|
80
82
|
test_files: []
|