iron_bank 2.2.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/.env.example +0 -2
- data/.gitignore +0 -1
- data/.reek.yml +5 -15
- data/.rspec +1 -0
- data/.rubocop.yml +9 -4
- data/.ruby-version +1 -0
- data/.travis.yml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +134 -0
- data/README.md +34 -14
- data/Rakefile +11 -16
- data/bin/console +8 -8
- data/iron_bank.gemspec +32 -34
- data/lib/generators/iron_bank/install/install_generator.rb +4 -4
- data/lib/generators/iron_bank/install/templates/iron_bank.rb +6 -6
- data/lib/iron_bank/action.rb +1 -1
- data/lib/iron_bank/actions/query_more.rb +1 -1
- data/lib/iron_bank/associations.rb +2 -2
- data/lib/iron_bank/authentication.rb +1 -1
- data/lib/iron_bank/authentications/cookie.rb +7 -7
- data/lib/iron_bank/authentications/token.rb +9 -9
- data/lib/iron_bank/cacheable.rb +1 -0
- data/lib/iron_bank/client.rb +6 -10
- data/lib/iron_bank/collection.rb +1 -0
- data/lib/iron_bank/configuration.rb +8 -19
- data/lib/iron_bank/csv.rb +2 -2
- data/lib/iron_bank/describe/field.rb +2 -2
- data/lib/iron_bank/describe/object.rb +5 -5
- data/lib/iron_bank/describe/related.rb +3 -3
- data/lib/iron_bank/describe/tenant.rb +2 -2
- data/lib/iron_bank/endpoint.rb +3 -3
- data/lib/iron_bank/error.rb +17 -17
- data/lib/iron_bank/local.rb +15 -7
- data/lib/iron_bank/local_records.rb +58 -20
- data/lib/iron_bank/logger.rb +3 -3
- data/lib/iron_bank/operation.rb +1 -1
- data/lib/iron_bank/query_builder.rb +4 -4
- data/lib/iron_bank/resource.rb +2 -7
- data/lib/iron_bank/resources/account.rb +6 -6
- data/lib/iron_bank/resources/export.rb +23 -0
- data/lib/iron_bank/resources/product_rate_plan.rb +2 -1
- data/lib/iron_bank/resources/product_rate_plan_charge_tier.rb +0 -44
- data/lib/iron_bank/resources/rate_plan_charge.rb +1 -1
- data/lib/iron_bank/resources/subscription.rb +4 -4
- data/lib/iron_bank/resources/usage.rb +1 -1
- data/lib/iron_bank/utils.rb +5 -5
- data/lib/iron_bank/version.rb +2 -2
- data/lib/iron_bank.rb +67 -75
- metadata +21 -52
- data/lib/iron_bank/instrumentation.rb +0 -14
- data/lib/iron_bank/open_tracing.rb +0 -18
- data/lib/iron_bank/resources/catalog_tiers/discount_amount.rb +0 -26
- data/lib/iron_bank/resources/catalog_tiers/discount_percentage.rb +0 -26
- data/lib/iron_bank/resources/catalog_tiers/price.rb +0 -26
@@ -5,8 +5,6 @@ module IronBank
|
|
5
5
|
# Get a cookie to enable authenticated calls to Zuora through Session.
|
6
6
|
#
|
7
7
|
class Cookie
|
8
|
-
include IronBank::OpenTracing
|
9
|
-
|
10
8
|
TEN_MINUTES = 600
|
11
9
|
ONE_HOUR = 3600
|
12
10
|
|
@@ -23,7 +21,7 @@ module IronBank
|
|
23
21
|
end
|
24
22
|
|
25
23
|
def header
|
26
|
-
{
|
24
|
+
{ "Cookie" => use }
|
27
25
|
end
|
28
26
|
|
29
27
|
private
|
@@ -38,7 +36,7 @@ module IronBank
|
|
38
36
|
|
39
37
|
def fetch_cookie
|
40
38
|
response = authenticate
|
41
|
-
@cookie = response.headers[
|
39
|
+
@cookie = response.headers["set-cookie"]
|
42
40
|
@zsession = fetch_zsession
|
43
41
|
@expires_at = Time.now + ONE_HOUR
|
44
42
|
end
|
@@ -49,14 +47,16 @@ module IronBank
|
|
49
47
|
end
|
50
48
|
|
51
49
|
def authenticate
|
52
|
-
connection.post(
|
50
|
+
connection.post("v1/connections", {})
|
53
51
|
end
|
54
52
|
|
55
53
|
def connection
|
56
54
|
@connection ||= Faraday.new(faraday_config) do |conn|
|
57
|
-
|
55
|
+
IronBank.configuration.middlewares.each do |klass, options|
|
56
|
+
conn.use klass, options
|
57
|
+
end
|
58
|
+
|
58
59
|
conn.request :url_encoded
|
59
|
-
conn.response :logger, IronBank.logger
|
60
60
|
conn.response :json
|
61
61
|
conn.adapter Faraday.default_adapter
|
62
62
|
end
|
@@ -5,8 +5,6 @@ module IronBank
|
|
5
5
|
# Get a bearer token to enable authenticated calls to Zuora through OAuth.
|
6
6
|
#
|
7
7
|
class Token
|
8
|
-
include IronBank::OpenTracing
|
9
|
-
|
10
8
|
# Generic token error.
|
11
9
|
#
|
12
10
|
class Error < StandardError; end
|
@@ -31,7 +29,7 @@ module IronBank
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def header
|
34
|
-
{
|
32
|
+
{ "Authorization" => "Bearer #{use}" }
|
35
33
|
end
|
36
34
|
|
37
35
|
private
|
@@ -46,21 +44,23 @@ module IronBank
|
|
46
44
|
|
47
45
|
def fetch_token
|
48
46
|
response = authenticate || {}
|
49
|
-
@access_token = response.fetch(
|
50
|
-
@expires_at = Time.now + response.fetch(
|
47
|
+
@access_token = response.fetch("access_token", nil)
|
48
|
+
@expires_at = Time.now + response.fetch("expires_in", ONE_HOUR).to_i
|
51
49
|
validate_access_token
|
52
50
|
end
|
53
51
|
alias refetch_token fetch_token
|
54
52
|
|
55
53
|
def authenticate
|
56
|
-
connection.post(
|
54
|
+
connection.post("/oauth/token", authentication_params).body
|
57
55
|
end
|
58
56
|
|
59
57
|
def connection
|
60
58
|
@connection ||= Faraday.new(url: base_url) do |conn|
|
61
|
-
|
59
|
+
IronBank.configuration.middlewares.each do |klass, options|
|
60
|
+
conn.use klass, options
|
61
|
+
end
|
62
|
+
|
62
63
|
conn.request :url_encoded
|
63
|
-
conn.response :logger, IronBank.logger
|
64
64
|
conn.response :json
|
65
65
|
conn.adapter Faraday.default_adapter
|
66
66
|
end
|
@@ -70,7 +70,7 @@ module IronBank
|
|
70
70
|
{
|
71
71
|
client_id: client_id,
|
72
72
|
client_secret: client_secret,
|
73
|
-
grant_type:
|
73
|
+
grant_type: "client_credentials"
|
74
74
|
}
|
75
75
|
end
|
76
76
|
|
data/lib/iron_bank/cacheable.rb
CHANGED
data/lib/iron_bank/client.rb
CHANGED
@@ -5,9 +5,6 @@ module IronBank
|
|
5
5
|
# authenticated request, reusing the same session cookie for future requests.
|
6
6
|
#
|
7
7
|
class Client
|
8
|
-
include IronBank::Instrumentation
|
9
|
-
include IronBank::OpenTracing
|
10
|
-
|
11
8
|
# Generic client error.
|
12
9
|
#
|
13
10
|
class Error < StandardError; end
|
@@ -26,7 +23,7 @@ module IronBank
|
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
def initialize(domain:, client_id:, client_secret:, auth_type:
|
26
|
+
def initialize(domain:, client_id:, client_secret:, auth_type: "token")
|
30
27
|
@domain = domain
|
31
28
|
@client_id = client_id
|
32
29
|
@client_secret = client_secret
|
@@ -40,19 +37,18 @@ module IronBank
|
|
40
37
|
def connection
|
41
38
|
validate_domain
|
42
39
|
reset_connection if auth.expired?
|
40
|
+
config = IronBank.configuration
|
43
41
|
|
44
42
|
@connection ||= Faraday.new(faraday_config) do |conn|
|
43
|
+
config.middlewares.each { |klass, options| conn.use(klass, options) }
|
44
|
+
|
45
45
|
conn.request :json
|
46
|
-
conn.request :retry,
|
46
|
+
conn.request :retry, config.retry_options
|
47
47
|
|
48
48
|
conn.response :raise_error
|
49
49
|
conn.response :renew_auth, auth
|
50
|
-
conn.response :logger, IronBank.logger
|
51
50
|
conn.response :json, content_type: /\bjson$/
|
52
51
|
|
53
|
-
conn.use :ddtrace, open_tracing_options if open_tracing_enabled?
|
54
|
-
conn.use instrumenter, instrumenter_options if instrumenter
|
55
|
-
|
56
52
|
conn.adapter Faraday.default_adapter
|
57
53
|
end
|
58
54
|
end
|
@@ -103,7 +99,7 @@ module IronBank
|
|
103
99
|
end
|
104
100
|
|
105
101
|
def headers
|
106
|
-
{
|
102
|
+
{ "Content-Type" => "application/json" }.merge(auth.header)
|
107
103
|
end
|
108
104
|
|
109
105
|
def reset_connection
|
data/lib/iron_bank/collection.rb
CHANGED
@@ -4,9 +4,8 @@ module IronBank
|
|
4
4
|
# The Zuora configuration class.
|
5
5
|
#
|
6
6
|
class Configuration
|
7
|
-
#
|
8
|
-
attr_accessor :
|
9
|
-
attr_accessor :instrumenter_options
|
7
|
+
# middlewares
|
8
|
+
attr_accessor :middlewares
|
10
9
|
|
11
10
|
# Logger
|
12
11
|
attr_accessor :logger
|
@@ -26,15 +25,6 @@ module IronBank
|
|
26
25
|
# Cache store instance, optionally used by certain resources.
|
27
26
|
attr_accessor :cache
|
28
27
|
|
29
|
-
# Open Tracing
|
30
|
-
attr_accessor :open_tracing_enabled
|
31
|
-
|
32
|
-
# Open Tracing service name
|
33
|
-
attr_accessor :open_tracing_service_name
|
34
|
-
|
35
|
-
# Faraday retry options
|
36
|
-
attr_writer :retry_options
|
37
|
-
|
38
28
|
# Directory where the XML describe files are located.
|
39
29
|
attr_reader :schema_directory
|
40
30
|
|
@@ -42,12 +32,11 @@ module IronBank
|
|
42
32
|
attr_reader :export_directory
|
43
33
|
|
44
34
|
def initialize
|
45
|
-
@schema_directory
|
46
|
-
@export_directory
|
47
|
-
@logger
|
48
|
-
@auth_type
|
49
|
-
@
|
50
|
-
@open_tracing_service_name = 'ironbank'
|
35
|
+
@schema_directory = "./config/schema"
|
36
|
+
@export_directory = "./config/export"
|
37
|
+
@logger = IronBank::Logger.new
|
38
|
+
@auth_type = "token"
|
39
|
+
@middlewares = []
|
51
40
|
end
|
52
41
|
|
53
42
|
def schema_directory=(value)
|
@@ -68,7 +57,7 @@ module IronBank
|
|
68
57
|
@export_directory = value
|
69
58
|
return unless defined? IronBank::Product
|
70
59
|
|
71
|
-
IronBank::LocalRecords::
|
60
|
+
IronBank::LocalRecords::RESOURCE_QUERY_FIELDS.keys.each do |resource|
|
72
61
|
IronBank::Resources.const_get(resource).reset_store
|
73
62
|
end
|
74
63
|
end
|
data/lib/iron_bank/csv.rb
CHANGED
@@ -9,7 +9,7 @@ module IronBank
|
|
9
9
|
encoding = field.encode(CSV::ConverterEncoding)
|
10
10
|
|
11
11
|
# Match: [1, 10, 100], No match: [0.1, .1, 1., 0b10]
|
12
|
-
|
12
|
+
/^[+-]?\d+$/.match?(encoding) ? encoding.to_i : field
|
13
13
|
rescue # encoding or integer conversion
|
14
14
|
field
|
15
15
|
end
|
@@ -20,7 +20,7 @@ module IronBank
|
|
20
20
|
encoding = field.encode(CSV::ConverterEncoding)
|
21
21
|
|
22
22
|
# Match: [1.0, 1., 0.1, .1], No match: [1, 0b10]
|
23
|
-
|
23
|
+
/^[+-]?(?:\d*\.|\.\d*)\d*$/.match?(encoding) ? encoding.to_f : field
|
24
24
|
rescue # encoding or float conversion
|
25
25
|
field
|
26
26
|
end
|
@@ -33,7 +33,7 @@ module IronBank
|
|
33
33
|
|
34
34
|
# Defined separately because the node name is not ruby-friendly
|
35
35
|
def max_length
|
36
|
-
doc.at_xpath(
|
36
|
+
doc.at_xpath(".//maxlength").text.to_i
|
37
37
|
end
|
38
38
|
|
39
39
|
TEXT_VALUES.each do |val|
|
@@ -46,7 +46,7 @@ module IronBank
|
|
46
46
|
end
|
47
47
|
|
48
48
|
BOOLEAN_VALUES.each do |val|
|
49
|
-
define_method(:"#{val}?") { doc.at_xpath(".//#{val}").text ==
|
49
|
+
define_method(:"#{val}?") { doc.at_xpath(".//#{val}").text == "true" }
|
50
50
|
end
|
51
51
|
|
52
52
|
def inspect
|
@@ -31,22 +31,22 @@ module IronBank
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def export
|
34
|
-
File.open(file_path,
|
34
|
+
File.open(file_path, "w") { |file| file << doc.to_xml }
|
35
35
|
end
|
36
36
|
|
37
37
|
def name
|
38
|
-
node = doc.at_xpath(
|
38
|
+
node = doc.at_xpath(".//object/name")
|
39
39
|
raise InvalidXML unless node
|
40
40
|
|
41
41
|
node.text
|
42
42
|
end
|
43
43
|
|
44
44
|
def label
|
45
|
-
doc.at_xpath(
|
45
|
+
doc.at_xpath(".//object/label").text
|
46
46
|
end
|
47
47
|
|
48
48
|
def fields
|
49
|
-
@fields ||= doc.xpath(
|
49
|
+
@fields ||= doc.xpath(".//fields/field").map do |node|
|
50
50
|
IronBank::Describe::Field.from_xml(node)
|
51
51
|
end
|
52
52
|
end
|
@@ -56,7 +56,7 @@ module IronBank
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def related
|
59
|
-
@related ||= doc.xpath(
|
59
|
+
@related ||= doc.xpath(".//related-objects/object").map do |node|
|
60
60
|
IronBank::Describe::Related.from_xml(node)
|
61
61
|
end
|
62
62
|
end
|
@@ -13,15 +13,15 @@ module IronBank
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def type
|
16
|
-
@type ||= doc.attributes[
|
16
|
+
@type ||= doc.attributes["href"].value.split("/").last
|
17
17
|
end
|
18
18
|
|
19
19
|
def name
|
20
|
-
doc.at_xpath(
|
20
|
+
doc.at_xpath(".//name").text
|
21
21
|
end
|
22
22
|
|
23
23
|
def label
|
24
|
-
doc.at_xpath(
|
24
|
+
doc.at_xpath(".//label").text
|
25
25
|
end
|
26
26
|
|
27
27
|
def inspect
|
@@ -12,7 +12,7 @@ module IronBank
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.from_connection(connection)
|
15
|
-
xml = connection.get(
|
15
|
+
xml = connection.get("v1/describe").body
|
16
16
|
new(Nokogiri::XML(xml), connection)
|
17
17
|
rescue TypeError
|
18
18
|
# NOTE: Zuora returns HTTP 401 (unauthorized) roughly 1 out of 3 times
|
@@ -43,7 +43,7 @@ module IronBank
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def object_names
|
46
|
-
@object_names ||= doc.xpath(
|
46
|
+
@object_names ||= doc.xpath(".//object/name").map(&:text)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
data/lib/iron_bank/endpoint.rb
CHANGED
@@ -10,18 +10,18 @@ module IronBank
|
|
10
10
|
SERVICES = /\Aservices(\d+)\.zuora\.com(:\d+)?\z/i.freeze
|
11
11
|
APISANDBOX = /\Arest.apisandbox.zuora\.com\z/i.freeze
|
12
12
|
|
13
|
-
def self.base_url(domain =
|
13
|
+
def self.base_url(domain = "")
|
14
14
|
new(domain).base_url
|
15
15
|
end
|
16
16
|
|
17
17
|
def base_url
|
18
18
|
case domain
|
19
19
|
when PRODUCTION
|
20
|
-
|
20
|
+
"https://rest.zuora.com/"
|
21
21
|
when SERVICES
|
22
22
|
"https://#{domain}/".downcase
|
23
23
|
when APISANDBOX
|
24
|
-
|
24
|
+
"https://rest.apisandbox.zuora.com/"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
data/lib/iron_bank/error.rb
CHANGED
@@ -82,23 +82,23 @@ module IronBank
|
|
82
82
|
class LockCompetitionError < TemporaryError; end
|
83
83
|
|
84
84
|
CODE_CLASSES = {
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
85
|
+
"API_DISABLED" => ServerError,
|
86
|
+
"CANNOT_DELETE" => UnprocessableEntityError,
|
87
|
+
"DUPLICATE_VALUE" => ConflictError,
|
88
|
+
"INVALID_FIELD" => BadRequestError,
|
89
|
+
"INVALID_ID" => BadRequestError,
|
90
|
+
"INVALID_TYPE" => BadRequestError,
|
91
|
+
"INVALID_VALUE" => BadRequestError,
|
92
|
+
"LOCK_COMPETITION" => LockCompetitionError,
|
93
|
+
"MALFORMED_QUERY" => ClientError,
|
94
|
+
"MISSING_REQUIRED_VALUE" => ClientError,
|
95
|
+
"REQUEST_EXCEEDED_LIMIT" => TooManyRequestsError,
|
96
|
+
"REQUEST_EXCEEDED_RATE" => TooManyRequestsError,
|
97
|
+
"TEMPORARY_ERROR" => TemporaryError,
|
98
|
+
"TRANSACTION_FAILED" => InternalServerError,
|
99
|
+
"TRANSACTION_TERMINATED" => InternalServerError,
|
100
|
+
"TRANSACTION_TIMEOUT" => BadGatewayError,
|
101
|
+
"UNKNOWN_ERROR" => InternalServerError
|
102
102
|
}.freeze
|
103
103
|
|
104
104
|
CODE_MATCHER = /(#{CODE_CLASSES.keys.join('|')})/.freeze
|
data/lib/iron_bank/local.rb
CHANGED
@@ -33,25 +33,33 @@ module IronBank
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
+
# NOTE: Handle associations within the CSV export. E.g., when reading the
|
37
|
+
# `ProductRatePlan.csv` file, we have `ProductRatePlan.Id` and
|
38
|
+
# `Product.Id` fields. We want to end up with `id` and `product_id`
|
39
|
+
# respectively.
|
40
|
+
def underscore_header
|
41
|
+
lambda do |header|
|
42
|
+
parts = header.split(".")
|
43
|
+
header = parts.first.casecmp?(object_name) ? parts.last : parts.join
|
44
|
+
|
45
|
+
IronBank::Utils.underscore(header).to_sym
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
36
49
|
def store
|
37
50
|
@store ||= File.exist?(file_path) ? load_records : {}
|
38
51
|
end
|
39
52
|
|
40
53
|
def load_records
|
41
54
|
CSV.foreach(file_path, csv_options).with_object({}) do |row, store|
|
42
|
-
|
43
|
-
# this line, delete the other one, since `Hash#compact` is available in
|
44
|
-
# 2.4.x and we can remove two smells from `.reek` while we are at it
|
45
|
-
#
|
46
|
-
# store[row[:id]] = new(row.to_h.compact)
|
47
|
-
store[row[:id]] = new(row.to_h.reject { |_, value| value.nil? })
|
55
|
+
store[row[:id]] = new(row.to_h.compact)
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
51
59
|
def csv_options
|
52
60
|
{
|
53
61
|
headers: true,
|
54
|
-
header_converters: [
|
62
|
+
header_converters: [underscore_header],
|
55
63
|
converters: csv_converters
|
56
64
|
}
|
57
65
|
end
|
@@ -6,12 +6,12 @@ module IronBank
|
|
6
6
|
class LocalRecords
|
7
7
|
private_class_method :new
|
8
8
|
|
9
|
-
|
10
|
-
Product
|
11
|
-
ProductRatePlan
|
12
|
-
ProductRatePlanCharge
|
13
|
-
ProductRatePlanChargeTier
|
14
|
-
|
9
|
+
RESOURCE_QUERY_FIELDS = {
|
10
|
+
"Product" => ["*"],
|
11
|
+
"ProductRatePlan" => ["*", "Product.Id"],
|
12
|
+
"ProductRatePlanCharge" => ["*", "ProductRatePlan.Id"],
|
13
|
+
"ProductRatePlanChargeTier" => ["*", "ProductRatePlanCharge.Id"]
|
14
|
+
}.freeze
|
15
15
|
|
16
16
|
def self.directory
|
17
17
|
IronBank.configuration.export_directory
|
@@ -19,39 +19,77 @@ module IronBank
|
|
19
19
|
|
20
20
|
def self.export
|
21
21
|
FileUtils.mkdir_p(directory) unless Dir.exist?(directory)
|
22
|
-
|
22
|
+
RESOURCE_QUERY_FIELDS.keys.each { |resource| new(resource).save_file }
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
write_records(csv)
|
25
|
+
def save_file
|
26
|
+
until completed? || max_query?
|
27
|
+
IronBank.logger.info(export_query_info)
|
28
|
+
sleep backoff_time
|
30
29
|
end
|
30
|
+
|
31
|
+
File.open(file_path, "w") { |file| file.write(export.content) }
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
34
35
|
|
35
|
-
|
36
|
+
BACKOFF = {
|
37
|
+
max: 3,
|
38
|
+
interval: 0.5,
|
39
|
+
randomness: 0.5,
|
40
|
+
factor: 4
|
41
|
+
}.freeze
|
42
|
+
private_constant :BACKOFF
|
43
|
+
|
44
|
+
attr_reader :resource, :query_attempts
|
36
45
|
|
37
46
|
def initialize(resource)
|
38
|
-
@resource
|
47
|
+
@resource = resource
|
48
|
+
@query_attempts = 0
|
39
49
|
end
|
40
50
|
|
41
|
-
def
|
42
|
-
IronBank::
|
51
|
+
def export
|
52
|
+
@export ||= IronBank::Export.create(
|
53
|
+
"select #{RESOURCE_QUERY_FIELDS[resource].join(', ')} from #{resource}"
|
54
|
+
)
|
43
55
|
end
|
44
56
|
|
45
57
|
def file_path
|
46
58
|
File.expand_path("#{resource}.csv", self.class.directory)
|
47
59
|
end
|
48
60
|
|
49
|
-
def
|
50
|
-
|
61
|
+
def export_query_info
|
62
|
+
"Waiting for export #{export.id} to complete " \
|
63
|
+
"(attempt #{query_attempts} of #{BACKOFF[:max]})"
|
64
|
+
end
|
65
|
+
|
66
|
+
def completed?
|
67
|
+
return false unless (status = export.reload.status)
|
68
|
+
|
69
|
+
case status
|
70
|
+
when "Pending", "Processing" then false
|
71
|
+
when "Completed" then true
|
72
|
+
else raise_export_error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def raise_export_error
|
77
|
+
raise IronBank::Error, "Export #{export.id} has status #{export.status}"
|
51
78
|
end
|
52
79
|
|
53
|
-
def
|
54
|
-
|
80
|
+
def max_query?
|
81
|
+
@query_attempts += 1
|
82
|
+
return false unless @query_attempts > BACKOFF[:max]
|
83
|
+
|
84
|
+
raise IronBank::Error, "Export query attempts exceeded"
|
85
|
+
end
|
86
|
+
|
87
|
+
def backoff_time
|
88
|
+
interval = BACKOFF[:interval]
|
89
|
+
current_interval = interval * (BACKOFF[:factor]**query_attempts)
|
90
|
+
random_interval = rand * BACKOFF[:randomness].to_f * interval
|
91
|
+
|
92
|
+
current_interval + random_interval
|
55
93
|
end
|
56
94
|
end
|
57
95
|
end
|
data/lib/iron_bank/logger.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "singleton"
|
4
|
+
require "logger"
|
5
5
|
|
6
6
|
module IronBank
|
7
7
|
# Default logger for IronBank events
|
@@ -9,7 +9,7 @@ module IronBank
|
|
9
9
|
class Logger
|
10
10
|
extend Forwardable
|
11
11
|
|
12
|
-
PROGNAME =
|
12
|
+
PROGNAME = "iron_bank"
|
13
13
|
LEVEL = ::Logger::DEBUG
|
14
14
|
|
15
15
|
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
data/lib/iron_bank/operation.rb
CHANGED
@@ -26,7 +26,7 @@ module IronBank
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def query_fields
|
29
|
-
fields.join(
|
29
|
+
fields.join(",")
|
30
30
|
end
|
31
31
|
|
32
32
|
def query_conditions
|
@@ -41,7 +41,7 @@ module IronBank
|
|
41
41
|
def range_query_builder(field, value)
|
42
42
|
value.each.with_object([]) do |option, range_query|
|
43
43
|
range_query << "#{field}='#{option}'"
|
44
|
-
end.join(
|
44
|
+
end.join(" OR ")
|
45
45
|
end
|
46
46
|
|
47
47
|
def hash_query_conditions
|
@@ -49,7 +49,7 @@ module IronBank
|
|
49
49
|
# TODO: sanitize the value
|
50
50
|
field = IronBank::Utils.camelize(field)
|
51
51
|
filters << current_filter(field, value)
|
52
|
-
end.join(
|
52
|
+
end.join(" AND ")
|
53
53
|
end
|
54
54
|
|
55
55
|
def current_filter(field, value)
|
@@ -66,7 +66,7 @@ module IronBank
|
|
66
66
|
return if conditions.count <= 1
|
67
67
|
return unless conditions.values.any? { |value| value.is_a?(Array) }
|
68
68
|
|
69
|
-
raise
|
69
|
+
raise "Filter ranges must be used in isolation."
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
data/lib/iron_bank/resource.rb
CHANGED
@@ -10,7 +10,7 @@ module IronBank
|
|
10
10
|
extend IronBank::Queryable
|
11
11
|
|
12
12
|
def self.object_name
|
13
|
-
name.split(
|
13
|
+
name.split("::").last
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.with_local_records
|
@@ -52,12 +52,7 @@ module IronBank
|
|
52
52
|
def reload
|
53
53
|
remove_instance_vars
|
54
54
|
@remote = self.class.find(id).remote
|
55
|
-
|
56
|
-
|
57
|
-
def to_csv_row
|
58
|
-
self.class.fields.each.with_object([]) do |field, row|
|
59
|
-
row << remote[IronBank::Utils.underscore(field).to_sym]
|
60
|
-
end
|
55
|
+
self
|
61
56
|
end
|
62
57
|
|
63
58
|
def remove_instance_vars
|