inat-get 0.9.0.12 → 0.9.0.14
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/lib/inat-get/app/core/api.rb +19 -2
- data/lib/inat-get/app/core/api_cache.rb +37 -0
- data/lib/inat-get/app/core/console.rb +10 -0
- data/lib/inat-get/app/core/console_logger.rb +4 -0
- data/lib/inat-get/app/core/server.rb +4 -3
- data/lib/inat-get/app/setup.rb +4 -3
- data/lib/inat-get/data/models/base.rb +13 -0
- data/lib/inat-get/data/models/identification.rb +2 -0
- data/lib/inat-get/data/models/observation.rb +2 -0
- data/lib/inat-get/data/models/photo.rb +2 -0
- data/lib/inat-get/data/models/place.rb +2 -0
- data/lib/inat-get/data/models/project.rb +2 -0
- data/lib/inat-get/data/models/sound.rb +2 -0
- data/lib/inat-get/data/models/taxon.rb +2 -0
- data/lib/inat-get/data/models/user.rb +2 -0
- data/lib/inat-get/data/updaters/base.rb +15 -8
- data/lib/inat-get/info.rb +1 -1
- metadata +32 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05a4272992b33172ef754c61f1d1d1c89a11cc7efe51cb84420efda09bfff858
|
|
4
|
+
data.tar.gz: 702308f230e526f0a10125c2785b258a0417f513937f3111a816e0f727734262
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 673c18491a5152a65e5d6773f325125fa98824ee8ac6dc543e0d57cd50dafa9cac0751ab4ad522de7ecd9eaa9f87b77e2af56d8b64323c74ee83507aa43c76b4
|
|
7
|
+
data.tar.gz: a6c4facdb3f9ba680f693e58c9bf788ddf71ae0b0b675d457dc1b6b4ab82ee67dfa50a22a327fc81fad1e8b51710faea27f3b2a145eda9fda2eb8e1532fa5b22
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require 'faraday'
|
|
4
4
|
require 'faraday/retry'
|
|
5
|
+
require 'faraday/typhoeus'
|
|
6
|
+
# require 'faraday/gzip'
|
|
7
|
+
# require 'faraday-http-cache'
|
|
5
8
|
require 'is-duration'
|
|
6
9
|
|
|
7
10
|
require_relative 'server'
|
|
8
11
|
require_relative 'console_logger'
|
|
12
|
+
require_relative 'api_cache'
|
|
9
13
|
|
|
10
14
|
class INatGet::App::Server::API < INatGet::App::Server
|
|
11
15
|
|
|
@@ -21,6 +25,7 @@ class INatGet::App::Server::API < INatGet::App::Server
|
|
|
21
25
|
|
|
22
26
|
def get query, **opts
|
|
23
27
|
endpoint = @config.dig(:api, :root) + query[:endpoint].to_s
|
|
28
|
+
@logger.info query[:endpoint].to_s
|
|
24
29
|
timepoint = Time::now
|
|
25
30
|
if @last_request
|
|
26
31
|
delta = timepoint - @last_request
|
|
@@ -33,6 +38,7 @@ class INatGet::App::Server::API < INatGet::App::Server
|
|
|
33
38
|
rq.params.merge! query[:query]
|
|
34
39
|
rq.headers["User-Agent"] = "iNatGet v#{INatGet::Info::VERSION} (#{ INatGet::Info::VERSION_ALIAS })"
|
|
35
40
|
end
|
|
41
|
+
@logger.clear
|
|
36
42
|
if response.success?
|
|
37
43
|
begin
|
|
38
44
|
data = JSON.parse response.body, symbolize_names: true
|
|
@@ -45,6 +51,8 @@ class INatGet::App::Server::API < INatGet::App::Server
|
|
|
45
51
|
@logger.error "Error in response: #{response.status}"
|
|
46
52
|
return { status: :error, error: response.status }.freeze
|
|
47
53
|
end
|
|
54
|
+
# rescue => e
|
|
55
|
+
# return { status: :error, error: e.message }.freeze
|
|
48
56
|
end
|
|
49
57
|
|
|
50
58
|
def faraday
|
|
@@ -55,10 +63,19 @@ class INatGet::App::Server::API < INatGet::App::Server
|
|
|
55
63
|
interval: IS::Duration::parse(@config.dig(:api, :retry, :interval)),
|
|
56
64
|
interval_randomness: @config.dig(:api, :retry, :randomness),
|
|
57
65
|
backoff_factor: @config.dig(:api, :retry, :backoff),
|
|
66
|
+
retry_block: lambda { |env:, options:, retry_count:, exception:, will_retry_in:| @logger.warn "retry... : #{ retry_count } : #{ exception.class }" },
|
|
58
67
|
exceptions: [Faraday::TimeoutError, Faraday::ConnectionFailed, Faraday::SSLError, Faraday::ClientError]
|
|
59
68
|
f.request :url_encoded
|
|
60
|
-
# f.response :logger, tmp_logger,
|
|
61
|
-
|
|
69
|
+
# f.response :logger, tmp_logger, { headers: true, bodies: false }
|
|
70
|
+
|
|
71
|
+
# f.use :http_cache, store: INatGet::App::Server::API::Cache::new(@config.dig(:caching, :api) || 100)
|
|
72
|
+
|
|
73
|
+
f.adapter :typhoeus do |typhoeus|
|
|
74
|
+
typhoeus.options[:connecttimeout] = 10
|
|
75
|
+
typhoeus.options[:timeout] = 20
|
|
76
|
+
typhoeus.options[:low_speed_limit] = 10
|
|
77
|
+
typhoeus.options[:low_speed_time] = 10
|
|
78
|
+
end
|
|
62
79
|
end
|
|
63
80
|
end
|
|
64
81
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../info'
|
|
4
|
+
|
|
5
|
+
module INatGet::App
|
|
6
|
+
class Server
|
|
7
|
+
class API < INatGet::App::Server; end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
class INatGet::App::Server::API::Cache
|
|
13
|
+
|
|
14
|
+
def initialize limit = 100
|
|
15
|
+
@limit = limit
|
|
16
|
+
@data = {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def read key
|
|
20
|
+
return nil unless @data.has_key?(key)
|
|
21
|
+
value = @data.delete key
|
|
22
|
+
@data[key] = value
|
|
23
|
+
value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def write key, value
|
|
27
|
+
@data.delete key
|
|
28
|
+
@data[key] = value
|
|
29
|
+
@data.shift if @data.size > @limit
|
|
30
|
+
value
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delete key
|
|
34
|
+
@data.delete key
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -65,6 +65,16 @@ class INatGet::App::Server::Console < INatGet::App::Server
|
|
|
65
65
|
true
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
def clear progname, **opts
|
|
69
|
+
key = prog_key progname
|
|
70
|
+
pid = opts[:_sender_pid]
|
|
71
|
+
if key == :wrk
|
|
72
|
+
@table.update _sender_pid: pid, message: ''
|
|
73
|
+
else
|
|
74
|
+
@table.summary message: ''
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
68
78
|
private
|
|
69
79
|
|
|
70
80
|
def prog_key progname
|
|
@@ -66,6 +66,7 @@ class INatGet::App::Server
|
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def on_error exception
|
|
69
|
+
warn exception.class
|
|
69
70
|
warn exception
|
|
70
71
|
warn exception.backtrace
|
|
71
72
|
end
|
|
@@ -92,7 +93,7 @@ class INatGet::App::Server
|
|
|
92
93
|
end
|
|
93
94
|
|
|
94
95
|
def method_missing sym, *args, **kwargs
|
|
95
|
-
kwargs[:_sender_pid]
|
|
96
|
+
kwargs[:_sender_pid] ||= ::Process::pid
|
|
96
97
|
msg = {
|
|
97
98
|
method: sym,
|
|
98
99
|
args: args,
|
|
@@ -104,8 +105,8 @@ class INatGet::App::Server
|
|
|
104
105
|
socket.close
|
|
105
106
|
result
|
|
106
107
|
rescue => e
|
|
107
|
-
pp e
|
|
108
|
-
|
|
108
|
+
# pp e
|
|
109
|
+
{ status: :error, error: e.message }
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
end
|
data/lib/inat-get/app/setup.rb
CHANGED
|
@@ -16,8 +16,8 @@ module INatGet::App::Setup
|
|
|
16
16
|
DEFAULTS = {
|
|
17
17
|
logs: {
|
|
18
18
|
screen: {
|
|
19
|
-
api: '
|
|
20
|
-
sys: '
|
|
19
|
+
api: 'info',
|
|
20
|
+
sys: 'info',
|
|
21
21
|
wrk: 'info'
|
|
22
22
|
},
|
|
23
23
|
file: {
|
|
@@ -34,6 +34,7 @@ module INatGet::App::Setup
|
|
|
34
34
|
password: nil
|
|
35
35
|
},
|
|
36
36
|
caching: {
|
|
37
|
+
api: 100,
|
|
37
38
|
update: '4h',
|
|
38
39
|
refresh: {
|
|
39
40
|
interval: '4d',
|
|
@@ -62,7 +63,7 @@ module INatGet::App::Setup
|
|
|
62
63
|
preferred_place: 7161,
|
|
63
64
|
translate_projects: 'umbrella', # all | umbrella | none
|
|
64
65
|
retry: {
|
|
65
|
-
max:
|
|
66
|
+
max: 25,
|
|
66
67
|
interval: '1s',
|
|
67
68
|
randomness: 0.5,
|
|
68
69
|
backoff: 2
|
|
@@ -52,6 +52,19 @@ module INatGet::Data
|
|
|
52
52
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
module Identified
|
|
56
|
+
|
|
57
|
+
def eql? other
|
|
58
|
+
return false unless other.is_a?(self.class)
|
|
59
|
+
self.id == other.id
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def hash
|
|
63
|
+
[Identified, self.class, self.id].hash
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
|
|
55
68
|
end
|
|
56
69
|
|
|
57
70
|
end
|
|
@@ -9,6 +9,8 @@ module INatGet::Data; end
|
|
|
9
9
|
|
|
10
10
|
class INatGet::Data::Model::Photo < INatGet::Data::Model
|
|
11
11
|
|
|
12
|
+
include INatGet::Data::Model::Identified
|
|
13
|
+
|
|
12
14
|
set_dataset :photos
|
|
13
15
|
|
|
14
16
|
many_to_many :observations, class: :'INatGet::Data::Model::Observation', join_table: :observation_photos, left_key: :photo_id, right_key: :observation_id
|
|
@@ -9,6 +9,8 @@ module INatGet::Data; end
|
|
|
9
9
|
|
|
10
10
|
class INatGet::Data::Model::Place < INatGet::Data::Model
|
|
11
11
|
|
|
12
|
+
include INatGet::Data::Model::Identified
|
|
13
|
+
|
|
12
14
|
set_dataset :places
|
|
13
15
|
|
|
14
16
|
many_to_many :observations, class: :'INatGet::Data::Model::Observation', join_table: :observation_places, left_key: :place_id, right_key: :observation_id
|
|
@@ -6,6 +6,8 @@ require_relative "../../info"
|
|
|
6
6
|
|
|
7
7
|
class INatGet::Data::Model::Sound < INatGet::Data::Model
|
|
8
8
|
|
|
9
|
+
include INatGet::Data::Model::Identified
|
|
10
|
+
|
|
9
11
|
set_dataset :sounds
|
|
10
12
|
|
|
11
13
|
many_to_many :observations, class: :'INatGet::Data::Model::Observation', join_table: :observation_sounds, left_key: :sound_id, right_key: :observation_id
|
|
@@ -146,25 +146,30 @@ class INatGet::Data::Updater
|
|
|
146
146
|
rq_model = INatGet::Data::Model::Request
|
|
147
147
|
record = nil
|
|
148
148
|
found = false
|
|
149
|
-
rq_model.db.transaction(isolation: :committed, mode: :immediate) do
|
|
149
|
+
# rq_model.db.transaction(isolation: :committed, mode: :immediate) do
|
|
150
150
|
record = rq_model.with_pk(rq_hash)
|
|
151
151
|
if record
|
|
152
152
|
while record.busy
|
|
153
153
|
raise "Too old business" if start_point - record.busy > HARD_STOP
|
|
154
|
+
console.update status: 'waiting...'
|
|
154
155
|
sleep 0.1
|
|
155
156
|
record.reload
|
|
156
157
|
end
|
|
157
158
|
return :fresh if record.finished > actual_point
|
|
158
|
-
|
|
159
|
+
rq_model.db.transaction(isolation: :committed, mode: :immediate) do
|
|
160
|
+
record.update busy: start_point
|
|
161
|
+
end
|
|
159
162
|
found = true
|
|
160
163
|
else
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
rq_model.db.transaction(isolation: :committed, mode: :immediate) do
|
|
165
|
+
record = rq_model.create full: rq_hash, endless: el_hash, endpoint: endpoint.to_s, query: rq_json, started: start_point, freshed: start_point, busy: start_point
|
|
166
|
+
set_request_projects record, query[:project_id] if query[:project_id]
|
|
167
|
+
set_request_places record, query[:place_id] if query[:place_id]
|
|
168
|
+
set_request_taxa record, query[:taxon_id] if query[:taxon_id]
|
|
169
|
+
set_request_users record, query[:user_id] if query[:user_id]
|
|
170
|
+
end
|
|
166
171
|
end
|
|
167
|
-
end
|
|
172
|
+
# end
|
|
168
173
|
|
|
169
174
|
# Устанавливаем updated_since
|
|
170
175
|
if allow_updated_since?
|
|
@@ -307,6 +312,7 @@ class INatGet::Data::Updater
|
|
|
307
312
|
until result
|
|
308
313
|
query[:id_above] = id_above if id_above
|
|
309
314
|
check_shutdown!
|
|
315
|
+
console.update status: 'querying...'
|
|
310
316
|
response = api.get({ endpoint: endpoint, query: query })
|
|
311
317
|
if response[:status] == :error
|
|
312
318
|
result = :error
|
|
@@ -335,6 +341,7 @@ class INatGet::Data::Updater
|
|
|
335
341
|
until result
|
|
336
342
|
query[:page] = page if page
|
|
337
343
|
check_shutdown!
|
|
344
|
+
console.update status: 'querying...'
|
|
338
345
|
response = api.get({ endpoint: endpoint, query: query })
|
|
339
346
|
if response[:status] == :error
|
|
340
347
|
result = :error
|
data/lib/inat-get/info.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inat-get
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.0.
|
|
4
|
+
version: 0.9.0.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ivan Shikhalev
|
|
@@ -51,6 +51,34 @@ dependencies:
|
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '2.3'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: faraday-http-cache
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.6'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '2.6'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: faraday-typhoeus
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.1'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.1'
|
|
54
82
|
- !ruby/object:Gem::Dependency
|
|
55
83
|
name: is-dsl
|
|
56
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -71,14 +99,14 @@ dependencies:
|
|
|
71
99
|
requirements:
|
|
72
100
|
- - "~>"
|
|
73
101
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: 0.8.
|
|
102
|
+
version: 0.8.10
|
|
75
103
|
type: :runtime
|
|
76
104
|
prerelease: false
|
|
77
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
106
|
requirements:
|
|
79
107
|
- - "~>"
|
|
80
108
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: 0.8.
|
|
109
|
+
version: 0.8.10
|
|
82
110
|
- !ruby/object:Gem::Dependency
|
|
83
111
|
name: is-duration
|
|
84
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -250,6 +278,7 @@ files:
|
|
|
250
278
|
- lib/inat-get/app.rb
|
|
251
279
|
- lib/inat-get/app/application.rb
|
|
252
280
|
- lib/inat-get/app/core/api.rb
|
|
281
|
+
- lib/inat-get/app/core/api_cache.rb
|
|
253
282
|
- lib/inat-get/app/core/console.rb
|
|
254
283
|
- lib/inat-get/app/core/console_logger.rb
|
|
255
284
|
- lib/inat-get/app/core/server.rb
|