ecoportal-api 0.10.10 → 0.10.12
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/.gitignore +2 -0
- data/CHANGELOG.md +15 -1
- data/lib/ecoportal/api/common/base_model.rb +4 -3
- data/lib/ecoportal/api/common/client/time_out.rb +3 -0
- data/lib/ecoportal/api/common/client.rb +22 -9
- data/lib/ecoportal/api/common/hash_diff.rb +1 -1
- data/lib/ecoportal/api/v1/job/awaiter/timer.rb +28 -9
- data/lib/ecoportal/api/v1/job/awaiter.rb +10 -3
- data/lib/ecoportal/api/v1/job.rb +2 -1
- data/lib/ecoportal/api/v1/person_details.rb +3 -2
- data/lib/ecoportal/api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c2232426e0251d1242aba6d7a0aa65c545b1bf07f273d23403b0daab0ae57d1
|
4
|
+
data.tar.gz: e155ec14f82fa569df5eeb4adcb89eb3848b21c902f01009ab4d5644b42b73c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41297931b543449d223f06cb64f46108d96d16141ab8b2a54f10a5bf782d241e8c37060a43807dd4e63d34288f1919c0a716db4a554e5ef4f3da54e42a574561
|
7
|
+
data.tar.gz: d0d7c16a92811f06df6611ae85fe0e93a62abd950ac478a8be0a6dca7c59fe4e064ca06849d974b913c370c65d79a68593c194324984f7cb3045fe0d5476be62
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,14 +2,28 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
-
## [0.10.
|
5
|
+
## [0.10.12] - 2025-05-xx
|
6
6
|
|
7
7
|
### Added
|
8
8
|
|
9
|
+
- `Client#post` **added** named argument `params` (for the **url** arguments)
|
10
|
+
|
9
11
|
### Changed
|
10
12
|
|
11
13
|
### Fixed
|
12
14
|
|
15
|
+
## [0.10.11] - 2025-05-15
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- `MAX_START_DELAY` to be `120` (it was `60`).
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
|
23
|
+
- `PersonDetails#changed?`: `ref` wasn't being used.
|
24
|
+
- `Ecoportal::API::V1::Job::Awaiter`
|
25
|
+
- First timer relay should use `ldelay` of 1 second if it's first loop.
|
26
|
+
|
13
27
|
## [0.10.10] - 2025-04-04
|
14
28
|
|
15
29
|
### Fixed
|
@@ -4,9 +4,10 @@ module Ecoportal
|
|
4
4
|
module Common
|
5
5
|
class BaseModel
|
6
6
|
class UnlinkedModel < StandardError
|
7
|
-
def initialize(msg =
|
8
|
-
msg
|
9
|
-
msg
|
7
|
+
def initialize(msg = nil, from: nil, key: nil)
|
8
|
+
msg ||= 'Something went wrong when linking the document.'
|
9
|
+
msg << " From: #{from}." if from
|
10
|
+
msg << " key: #{key}." if key
|
10
11
|
super(msg)
|
11
12
|
end
|
12
13
|
end
|
@@ -40,6 +40,9 @@ module Ecoportal
|
|
40
40
|
throughput.eta_for(to_count(count), **kargs)
|
41
41
|
end
|
42
42
|
|
43
|
+
# @todo introduce `min_wait`
|
44
|
+
# - The reason is because small batches have still an associated lag
|
45
|
+
# before the jobs start to run.
|
43
46
|
def timeout_for(count, waited: 0, max_wait: nil, approach: :conservative)
|
44
47
|
(waited + eta_for(count, approach: approach)).then do |time|
|
45
48
|
next time unless max_wait
|
@@ -27,7 +27,8 @@ module Ecoportal
|
|
27
27
|
include WithRetry
|
28
28
|
include RateThrottling
|
29
29
|
|
30
|
-
DEFAULT_HOST
|
30
|
+
DEFAULT_HOST = 'live.ecoportal.com'.freeze
|
31
|
+
MAIN_END_POINT = 'api'.freeze
|
31
32
|
|
32
33
|
attr_accessor :logger
|
33
34
|
attr_reader :host
|
@@ -47,9 +48,9 @@ module Ecoportal
|
|
47
48
|
@deep_logging = deep_logging
|
48
49
|
|
49
50
|
if host.match(/^localhost|^127\.0\.0\.1/)
|
50
|
-
@base_uri = "http://#{host}/
|
51
|
+
@base_uri = "http://#{host}/#{main_end_point}/"
|
51
52
|
else
|
52
|
-
@base_uri = "https://#{host}/
|
53
|
+
@base_uri = "https://#{host}/#{main_end_point}/"
|
53
54
|
end
|
54
55
|
|
55
56
|
if deep_logging?
|
@@ -58,7 +59,7 @@ module Ecoportal
|
|
58
59
|
}
|
59
60
|
end
|
60
61
|
|
61
|
-
return unless
|
62
|
+
return unless api_key.nil? || api_key.match(/\A\W*\z/)
|
62
63
|
return unless version
|
63
64
|
|
64
65
|
log(:error) { 'Api-key missing!' }
|
@@ -85,11 +86,17 @@ module Ecoportal
|
|
85
86
|
# @note it automatically adds the http header param `Content-Type` as `application/json`
|
86
87
|
# @param path [String] the tail that completes the url of the request.
|
87
88
|
# @param data [String] the body of the query in json format.
|
89
|
+
# @param params [Hash] the header paramters of the http request (not including the api key).
|
90
|
+
# @option params [String] URL params; will depend on he API being used.
|
88
91
|
# @return [Common::Reponse] the basic custom response object.
|
89
|
-
def post(path, data:)
|
90
|
-
instrument('POST', path,
|
92
|
+
def post(path, data:, params: {})
|
93
|
+
instrument('POST', path, params) do
|
91
94
|
request do |http|
|
92
|
-
http.post(
|
95
|
+
http.post(
|
96
|
+
url_for(path),
|
97
|
+
json: data,
|
98
|
+
params: params
|
99
|
+
)
|
93
100
|
end
|
94
101
|
end
|
95
102
|
end
|
@@ -144,9 +151,9 @@ module Ecoportal
|
|
144
151
|
@base_request ||=
|
145
152
|
case @version
|
146
153
|
when 'v2'
|
147
|
-
HTTP.headers('X-ECOPORTAL-API-KEY' =>
|
154
|
+
HTTP.headers('X-ECOPORTAL-API-KEY' => api_key).accept(:json)
|
148
155
|
else
|
149
|
-
HTTP.headers('X-ApiKey' =>
|
156
|
+
HTTP.headers('X-ApiKey' => api_key).accept(:json)
|
150
157
|
end
|
151
158
|
end
|
152
159
|
|
@@ -159,6 +166,8 @@ module Ecoportal
|
|
159
166
|
|
160
167
|
private
|
161
168
|
|
169
|
+
attr_reader :api_key
|
170
|
+
|
162
171
|
def instrument(method, path, data = nil, &block)
|
163
172
|
raise 'Expected block' unless block_given?
|
164
173
|
|
@@ -203,6 +212,10 @@ module Ecoportal
|
|
203
212
|
puts "(#{level}) #{yield}"
|
204
213
|
logger&.send(level, &block)
|
205
214
|
end
|
215
|
+
|
216
|
+
def main_end_point
|
217
|
+
self.class::MAIN_END_POINT
|
218
|
+
end
|
206
219
|
end
|
207
220
|
end
|
208
221
|
end
|
@@ -11,7 +11,7 @@ module Ecoportal
|
|
11
11
|
|
12
12
|
# The class
|
13
13
|
Timer = Struct.new(*TIMER_ARGS) do
|
14
|
-
self::MAX_START_DELAY =
|
14
|
+
self::MAX_START_DELAY = 120
|
15
15
|
|
16
16
|
attr_reader :timestamp
|
17
17
|
|
@@ -22,17 +22,24 @@ module Ecoportal
|
|
22
22
|
end
|
23
23
|
|
24
24
|
alias_method :original_start, :start
|
25
|
+
# Previous start or current timestamp.
|
26
|
+
# @note in practice this translates into the very first
|
27
|
+
# timestamp (so it's an absolute start)
|
25
28
|
def start
|
26
29
|
original_start || timestamp
|
27
30
|
end
|
28
31
|
|
29
32
|
alias_method :original_last, :last
|
33
|
+
# Previous timestamp.
|
30
34
|
def last
|
31
35
|
original_last || start
|
32
36
|
end
|
33
37
|
|
34
38
|
def new(**kargs, &block)
|
35
|
-
self.class.new(
|
39
|
+
self.class.new(
|
40
|
+
**new_kargs.merge(kargs),
|
41
|
+
&block
|
42
|
+
)
|
36
43
|
end
|
37
44
|
|
38
45
|
def job_id
|
@@ -40,10 +47,14 @@ module Ecoportal
|
|
40
47
|
end
|
41
48
|
|
42
49
|
def complete?
|
50
|
+
return false unless status
|
51
|
+
|
43
52
|
status.complete?(total)
|
44
53
|
end
|
45
54
|
|
46
55
|
def started?
|
56
|
+
return false unless status
|
57
|
+
|
47
58
|
status.started?
|
48
59
|
end
|
49
60
|
|
@@ -59,14 +70,17 @@ module Ecoportal
|
|
59
70
|
status.progress_increase(lstatus)
|
60
71
|
end
|
61
72
|
|
73
|
+
# Total time waited (absolute).
|
62
74
|
def waited
|
63
75
|
timestamp - start
|
64
76
|
end
|
65
77
|
|
78
|
+
# Time waited since last timestamp (relative).
|
66
79
|
def lwaited
|
67
80
|
timestamp - last
|
68
81
|
end
|
69
82
|
|
83
|
+
# Absolute wait minus half of the last sleep.
|
70
84
|
def net_waited
|
71
85
|
last_delay = ldelay || 0
|
72
86
|
waited - (last_delay / 2)
|
@@ -76,22 +90,26 @@ module Ecoportal
|
|
76
90
|
(timeout_in - waited).round(2)
|
77
91
|
end
|
78
92
|
|
93
|
+
# Time left before timing out job started
|
94
|
+
# or job finished.
|
95
|
+
def timeout_in
|
96
|
+
return time_left_total if started?
|
97
|
+
|
98
|
+
time_left_to_start
|
99
|
+
end
|
100
|
+
|
101
|
+
# Total time left before timing out.
|
79
102
|
def time_left_total
|
80
103
|
(timeout - waited).round(2)
|
81
104
|
end
|
82
105
|
|
106
|
+
# Time left before Job start times out.
|
83
107
|
def time_left_to_start
|
84
108
|
return max_start_delay if started?
|
85
109
|
|
86
110
|
(max_start_delay - waited).round(2)
|
87
111
|
end
|
88
112
|
|
89
|
-
def timeout_in
|
90
|
-
return time_left_total if started?
|
91
|
-
|
92
|
-
time_left_to_start
|
93
|
-
end
|
94
|
-
|
95
113
|
# timeout library is evil. So we make poor-man timeout.
|
96
114
|
# https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/
|
97
115
|
def timeout?
|
@@ -141,7 +159,7 @@ module Ecoportal
|
|
141
159
|
%i[total timeout start].each_with_object({}) do |key, kargs|
|
142
160
|
kargs[key] = send(key)
|
143
161
|
end.tap do |kargs|
|
144
|
-
kargs[:start] = start
|
162
|
+
kargs[:start] = start # @todo redundant
|
145
163
|
kargs[:last] = timestamp
|
146
164
|
kargs[:lstatus] = status
|
147
165
|
end
|
@@ -149,6 +167,7 @@ module Ecoportal
|
|
149
167
|
|
150
168
|
private
|
151
169
|
|
170
|
+
# We would not wait more than this time for a Job to start.
|
152
171
|
def max_start_delay
|
153
172
|
self.class::MAX_START_DELAY
|
154
173
|
end
|
@@ -9,8 +9,14 @@ module Ecoportal
|
|
9
9
|
include Common::Client::TimeOut
|
10
10
|
include StatusFrequency
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
# available approaches are:
|
13
|
+
# - `:min` assumes always the `MIN_THROUGHPUT`.
|
14
|
+
# - `:last` last seen throughput.
|
15
|
+
# - `:conservative` the bigger of: min throughput seen or `MIN_THROUGHPUT`.
|
16
|
+
# - `:optimistic` the smoller of: max throughput seen or `MAX_THROUGHPUT`.
|
17
|
+
# - `:average` the accumulated avarage of througoutputs.
|
18
|
+
TIMEOUT_APPROACH = :min
|
19
|
+
TIMEOUT_FALLBACK = :min # on timeout swap to this approach.
|
14
20
|
|
15
21
|
attr_reader :job_api, :job_id, :total
|
16
22
|
|
@@ -51,10 +57,11 @@ module Ecoportal
|
|
51
57
|
|
52
58
|
timer = timer.new(
|
53
59
|
status: job_api.status(job_id),
|
54
|
-
ldelay: delay_status_check
|
60
|
+
ldelay: delay_status_check || 1
|
55
61
|
)
|
56
62
|
|
57
63
|
# ratio = throughput!(timer.net_waited, count: timer.progress)
|
64
|
+
# last throughput (rather than average as above)
|
58
65
|
ratio = throughput!(timer.lwaited, count: timer.increased)
|
59
66
|
|
60
67
|
break timer.status if timer.complete?
|
data/lib/ecoportal/api/v1/job.rb
CHANGED
@@ -4,6 +4,7 @@ require 'ecoportal/api/v1/job/awaiter'
|
|
4
4
|
module Ecoportal
|
5
5
|
module API
|
6
6
|
class V1
|
7
|
+
# @todo add `#relaunch` where only pending results are requested.
|
7
8
|
class Job
|
8
9
|
attr_reader :client, :person_class
|
9
10
|
|
@@ -15,7 +16,7 @@ module Ecoportal
|
|
15
16
|
@created = false
|
16
17
|
end
|
17
18
|
|
18
|
-
# Allows to preserve the learned
|
19
|
+
# Allows to preserve the learned throughput
|
19
20
|
def new
|
20
21
|
self.class.new(client, person_class: person_class).tap do |out|
|
21
22
|
out.awaiter = @awaiter
|
@@ -25,6 +25,7 @@ module Ecoportal
|
|
25
25
|
# @return [Array<SchemaFieldValue>] the array of fields of the schema.
|
26
26
|
def fields
|
27
27
|
return @fields if defined?(@fields)
|
28
|
+
|
28
29
|
@fields = (doc['fields'] || []).each_with_index.map do |field, i|
|
29
30
|
schema_field_value_class.new(field, parent: self, key: ['fields', i])
|
30
31
|
end
|
@@ -66,10 +67,10 @@ module Ecoportal
|
|
66
67
|
end
|
67
68
|
|
68
69
|
# @return [Boolean] `true` if `id` exists and `value` has changed, `false` otherwise
|
69
|
-
def changed?(id,
|
70
|
+
def changed?(id, ref = :last)
|
70
71
|
return false unless (field = get_field(id))
|
71
72
|
|
72
|
-
field.as_update.key?('value')
|
73
|
+
field.as_update(ref).key?('value')
|
73
74
|
end
|
74
75
|
|
75
76
|
def original_value(id)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecoportal-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tapio Saarinen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|