forest_admin_datasource_rpc 1.25.0 → 1.25.1
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6473d3b105d21ba059701998a1179cb820551ffd9efc471a6850d23add3bbdad
|
|
4
|
+
data.tar.gz: bf4c243fe556572d5b634f9cef370ee3b09d6800ae3d8cf5a1d45806e3ed9481
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a443bb560f80a2f96d2b70c32ddb32abf53fd3fe9881dacb49caa021c0c8894a15c25d21f9c2eb83683c3d82557d503538461b75c112c368c404becb745eccd3
|
|
7
|
+
data.tar.gz: 55da1ddd18d8eea56472cba795e1622e88d3ede2ead212b0e4b3c3e4cf15ed3ea27635d89ae0058efdf20f8c0e245e22cb23013e902a27571bcdc67a4051b200
|
|
@@ -5,16 +5,6 @@ require 'time'
|
|
|
5
5
|
|
|
6
6
|
module ForestAdminDatasourceRpc
|
|
7
7
|
module Utils
|
|
8
|
-
# Response wrapper for schema requests that need ETag
|
|
9
|
-
class SchemaResponse
|
|
10
|
-
attr_reader :body, :etag
|
|
11
|
-
|
|
12
|
-
def initialize(body, etag = nil)
|
|
13
|
-
@body = body
|
|
14
|
-
@etag = etag
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
8
|
class RpcClient
|
|
19
9
|
ERROR_STATUS_MAP = {
|
|
20
10
|
400 => ForestAdminAgent::Http::Exceptions::ValidationError,
|
|
@@ -51,14 +41,14 @@ module ForestAdminDatasourceRpc
|
|
|
51
41
|
|
|
52
42
|
def fetch_schema(endpoint, if_none_match: nil)
|
|
53
43
|
response = make_request(endpoint, method: :get, symbolize_keys: true, if_none_match: if_none_match)
|
|
54
|
-
|
|
44
|
+
handle_response(response)
|
|
55
45
|
end
|
|
56
46
|
|
|
57
47
|
private
|
|
58
48
|
|
|
59
49
|
# rubocop:disable Metrics/ParameterLists
|
|
60
50
|
def make_request(endpoint, caller: nil, method: :get, payload: nil, symbolize_keys: false, if_none_match: nil)
|
|
61
|
-
log_request_start(method, endpoint
|
|
51
|
+
log_request_start(method, endpoint)
|
|
62
52
|
|
|
63
53
|
client = build_faraday_client(symbolize_keys)
|
|
64
54
|
headers = build_request_headers(caller, if_none_match)
|
|
@@ -128,25 +118,6 @@ module ForestAdminDatasourceRpc
|
|
|
128
118
|
raise_appropriate_error(response)
|
|
129
119
|
end
|
|
130
120
|
|
|
131
|
-
def handle_response_with_etag(response)
|
|
132
|
-
if response.success?
|
|
133
|
-
etag = extract_etag(response)
|
|
134
|
-
ForestAdminAgent::Facades::Container.logger&.log(
|
|
135
|
-
'Debug',
|
|
136
|
-
"[RPC Client] Schema response received (status: #{response.status}, ETag: #{etag || "none"})"
|
|
137
|
-
)
|
|
138
|
-
return SchemaResponse.new(response.body, etag)
|
|
139
|
-
end
|
|
140
|
-
return NotModified if response.status == HTTP_NOT_MODIFIED
|
|
141
|
-
|
|
142
|
-
raise_appropriate_error(response)
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def extract_etag(response)
|
|
146
|
-
etag = response.headers['ETag'] || response.headers['etag']
|
|
147
|
-
etag&.gsub(/\A"?|"?\z/, '')
|
|
148
|
-
end
|
|
149
|
-
|
|
150
121
|
def raise_appropriate_error(response)
|
|
151
122
|
error_body = parse_error_body(response)
|
|
152
123
|
status = response.status
|
|
@@ -194,11 +165,10 @@ module ForestAdminDatasourceRpc
|
|
|
194
165
|
}.compact
|
|
195
166
|
end
|
|
196
167
|
|
|
197
|
-
def log_request_start(method, endpoint
|
|
198
|
-
etag_info = if_none_match ? " (If-None-Match: #{if_none_match})" : ''
|
|
168
|
+
def log_request_start(method, endpoint)
|
|
199
169
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
200
170
|
'Debug',
|
|
201
|
-
"[RPC Client] Sending #{method.to_s.upcase} request to #{@api_url}#{endpoint}
|
|
171
|
+
"[RPC Client] Sending #{method.to_s.upcase} request to #{@api_url}#{endpoint}"
|
|
202
172
|
)
|
|
203
173
|
end
|
|
204
174
|
|
|
@@ -12,17 +12,15 @@ module ForestAdminDatasourceRpc
|
|
|
12
12
|
MIN_POLLING_INTERVAL = 1
|
|
13
13
|
MAX_POLLING_INTERVAL = 3600
|
|
14
14
|
|
|
15
|
-
def initialize(uri, auth_secret, polling_interval: DEFAULT_POLLING_INTERVAL,
|
|
16
|
-
|
|
15
|
+
def initialize(uri, auth_secret, polling_interval: DEFAULT_POLLING_INTERVAL, introspection: nil,
|
|
16
|
+
&on_schema_change)
|
|
17
17
|
@uri = uri
|
|
18
18
|
@auth_secret = auth_secret
|
|
19
19
|
@polling_interval = polling_interval
|
|
20
20
|
@on_schema_change = on_schema_change
|
|
21
21
|
@closed = false
|
|
22
|
-
@introspection_schema =
|
|
23
|
-
@introspection_etag = introspection_etag
|
|
22
|
+
@introspection_schema = introspection
|
|
24
23
|
@current_schema = nil
|
|
25
|
-
@cached_etag = nil
|
|
26
24
|
@connection_attempts = 0
|
|
27
25
|
@initial_sync_completed = false
|
|
28
26
|
@client_id = uri
|
|
@@ -63,7 +61,7 @@ module ForestAdminDatasourceRpc
|
|
|
63
61
|
@connection_attempts += 1
|
|
64
62
|
log_checking_schema
|
|
65
63
|
|
|
66
|
-
result = @rpc_client.fetch_schema('/forest/rpc-schema', if_none_match: @
|
|
64
|
+
result = @rpc_client.fetch_schema('/forest/rpc-schema', if_none_match: @current_schema&.dig(:etag))
|
|
67
65
|
handle_schema_result(result)
|
|
68
66
|
rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e
|
|
69
67
|
log_connection_error(e)
|
|
@@ -77,34 +75,25 @@ module ForestAdminDatasourceRpc
|
|
|
77
75
|
|
|
78
76
|
private
|
|
79
77
|
|
|
80
|
-
def compute_etag(schema)
|
|
81
|
-
return nil if schema.nil?
|
|
82
|
-
|
|
83
|
-
schema[:etag] || schema['etag'] || Digest::SHA1.hexdigest(JSON.generate(schema))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
78
|
def fetch_initial_schema_sync
|
|
87
79
|
# If we have an introspection schema, send its ETag to avoid re-downloading unchanged schema
|
|
88
|
-
|
|
89
|
-
result = @rpc_client.fetch_schema('/forest/rpc-schema', if_none_match: introspection_etag)
|
|
80
|
+
result = @rpc_client.fetch_schema('/forest/rpc-schema', if_none_match: @introspection_schema&.dig(:etag))
|
|
90
81
|
|
|
91
82
|
if result == RpcClient::NotModified
|
|
92
83
|
# Schema unchanged from introspection - use introspection
|
|
93
84
|
@current_schema = @introspection_schema
|
|
94
|
-
@cached_etag = introspection_etag
|
|
95
85
|
@initial_sync_completed = true
|
|
96
86
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
97
87
|
'Info',
|
|
98
|
-
"[Schema Polling] RPC schema unchanged (HTTP 304), using introspection (ETag: #{@
|
|
88
|
+
"[Schema Polling] RPC schema unchanged (HTTP 304), using introspection (ETag: #{@current_schema[:etag]})"
|
|
99
89
|
)
|
|
100
90
|
else
|
|
101
91
|
# New schema from RPC
|
|
102
|
-
@current_schema = result
|
|
103
|
-
@cached_etag = result.etag || compute_etag(@current_schema)
|
|
92
|
+
@current_schema = result
|
|
104
93
|
@initial_sync_completed = true
|
|
105
94
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
106
95
|
'Debug',
|
|
107
|
-
"[Schema Polling] Initial schema fetched successfully (ETag: #{@
|
|
96
|
+
"[Schema Polling] Initial schema fetched successfully (ETag: #{@current_schema[:etag]})"
|
|
108
97
|
)
|
|
109
98
|
end
|
|
110
99
|
|
|
@@ -119,14 +108,12 @@ module ForestAdminDatasourceRpc
|
|
|
119
108
|
if @introspection_schema
|
|
120
109
|
# Fallback to introspection schema - don't crash
|
|
121
110
|
@current_schema = @introspection_schema
|
|
122
|
-
@cached_etag = @introspection_etag || compute_etag(@current_schema)
|
|
123
111
|
@introspection_schema = nil
|
|
124
|
-
@introspection_etag = nil
|
|
125
112
|
@initial_sync_completed = true
|
|
126
113
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
127
114
|
'Warn',
|
|
128
115
|
"RPC agent at #{@uri} is unreachable (#{error.class}: #{error.message}), " \
|
|
129
|
-
"using provided introspection schema (ETag: #{@
|
|
116
|
+
"using provided introspection schema (ETag: #{@current_schema[:etag]})"
|
|
130
117
|
)
|
|
131
118
|
else
|
|
132
119
|
# No introspection - re-raise to crash
|
|
@@ -159,7 +146,8 @@ module ForestAdminDatasourceRpc
|
|
|
159
146
|
end
|
|
160
147
|
|
|
161
148
|
def log_checking_schema
|
|
162
|
-
|
|
149
|
+
etag = @current_schema&.dig(:etag)
|
|
150
|
+
etag_info = etag ? "with ETag: #{etag}" : 'without ETag (initial fetch)'
|
|
163
151
|
msg = "[Schema Polling] Checking schema from #{@uri}/forest/rpc-schema " \
|
|
164
152
|
"(attempt ##{@connection_attempts}, #{etag_info})"
|
|
165
153
|
ForestAdminAgent::Facades::Container.logger&.log('Debug', msg)
|
|
@@ -176,34 +164,31 @@ module ForestAdminDatasourceRpc
|
|
|
176
164
|
def handle_schema_unchanged
|
|
177
165
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
178
166
|
'Debug',
|
|
179
|
-
"[Schema Polling] Schema unchanged (HTTP 304 Not Modified), ETag still valid: #{@
|
|
167
|
+
"[Schema Polling] Schema unchanged (HTTP 304 Not Modified), ETag still valid: #{@current_schema[:etag]}"
|
|
180
168
|
)
|
|
181
169
|
@connection_attempts = 0
|
|
182
170
|
end
|
|
183
171
|
|
|
184
172
|
def handle_schema_changed(result)
|
|
185
|
-
new_schema = result
|
|
186
|
-
new_etag = result.etag || compute_etag(new_schema)
|
|
173
|
+
new_schema = result
|
|
187
174
|
|
|
188
175
|
if @initial_sync_completed
|
|
189
|
-
handle_schema_update(new_schema
|
|
176
|
+
handle_schema_update(new_schema)
|
|
190
177
|
else
|
|
191
|
-
@cached_etag = new_etag
|
|
192
178
|
@current_schema = new_schema
|
|
193
179
|
@initial_sync_completed = true
|
|
194
180
|
ForestAdminAgent::Facades::Container.logger&.log(
|
|
195
181
|
'Info',
|
|
196
|
-
"[Schema Polling] Initial sync completed successfully (ETag: #{
|
|
182
|
+
"[Schema Polling] Initial sync completed successfully (ETag: #{@current_schema[:etag]})"
|
|
197
183
|
)
|
|
198
184
|
end
|
|
199
185
|
@connection_attempts = 0
|
|
200
186
|
end
|
|
201
187
|
|
|
202
|
-
def handle_schema_update(schema
|
|
203
|
-
old_etag = @
|
|
204
|
-
@cached_etag = etag
|
|
188
|
+
def handle_schema_update(schema)
|
|
189
|
+
old_etag = @current_schema[:etag]
|
|
205
190
|
@current_schema = schema
|
|
206
|
-
msg = "[Schema Polling] Schema changed detected (old ETag: #{old_etag}, new ETag: #{etag}), " \
|
|
191
|
+
msg = "[Schema Polling] Schema changed detected (old ETag: #{old_etag}, new ETag: #{schema[:etag]}), " \
|
|
207
192
|
'triggering reload callback'
|
|
208
193
|
ForestAdminAgent::Facades::Container.logger&.log('Info', msg)
|
|
209
194
|
trigger_schema_change_callback(schema)
|
|
@@ -12,7 +12,7 @@ module ForestAdminDatasourceRpc
|
|
|
12
12
|
Utils::SchemaPollingPool.instance.configure(max_threads: max_threads)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
KNOWN_BUILD_OPTIONS = %i[uri auth_secret introspection
|
|
15
|
+
KNOWN_BUILD_OPTIONS = %i[uri auth_secret introspection schema_polling_interval_sec].freeze
|
|
16
16
|
|
|
17
17
|
def self.build(options)
|
|
18
18
|
unknown_keys = options.keys - KNOWN_BUILD_OPTIONS
|
|
@@ -27,7 +27,6 @@ module ForestAdminDatasourceRpc
|
|
|
27
27
|
uri = options[:uri]
|
|
28
28
|
auth_secret = options[:auth_secret] || ForestAdminAgent::Facades::Container.cache(:auth_secret)
|
|
29
29
|
provided_introspection = options[:introspection]
|
|
30
|
-
provided_introspection_etag = options[:introspection_etag]
|
|
31
30
|
|
|
32
31
|
polling_interval = options[:schema_polling_interval_sec] ||
|
|
33
32
|
ENV['SCHEMA_POLLING_INTERVAL_SEC']&.to_i ||
|
|
@@ -40,8 +39,7 @@ module ForestAdminDatasourceRpc
|
|
|
40
39
|
uri,
|
|
41
40
|
auth_secret,
|
|
42
41
|
polling_interval: polling_interval,
|
|
43
|
-
|
|
44
|
-
introspection_etag: provided_introspection_etag
|
|
42
|
+
introspection: provided_introspection
|
|
45
43
|
) do
|
|
46
44
|
Thread.new do
|
|
47
45
|
logger = ForestAdminAgent::Facades::Container.logger
|