noiseless 0.3.0 → 0.5.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 466267a77224bbf9915eff8b198002c658e2e9c9d368c6c7f6e4e4ee32939892
|
|
4
|
+
data.tar.gz: 71281cfbbcdd40f83f55eedb0fca494f1e0a75172c4a9523c3000cae81fa752d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a0a6c9aa9134b043b4a87c8434735f837bca7cfc63520693e3bf49ff4001617351cf92259b73a781187fd22812d65f781130570f753d27dd68d4d6f3bb16fd0
|
|
7
|
+
data.tar.gz: 14387643b5a8c5b5fc506e00b28b8d5b2664d359bd48797c6180df38f03efa370dd86d46d0a871194328ff80f487458e439733b250dfdad9cf369a253e069c3e
|
|
@@ -1,21 +1,48 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "socket"
|
|
4
|
+
require "timeout"
|
|
5
|
+
|
|
3
6
|
module Noiseless
|
|
4
7
|
module Adapters
|
|
5
8
|
module ExecutionModules
|
|
6
9
|
# Shared Async::HTTP connection handling for HTTP-based adapters.
|
|
7
10
|
# Host classes must provide a private +default_port+ method.
|
|
8
11
|
module HttpTransport
|
|
9
|
-
|
|
12
|
+
# Low-level failures the Async::HTTP stack raises when it cannot
|
|
13
|
+
# complete a round-trip with the backend (refused/reset connection,
|
|
14
|
+
# DNS failure, transport timeout). These are wrapped into
|
|
15
|
+
# Noiseless::ConnectionError so callers never have to know which HTTP
|
|
16
|
+
# stack is underneath.
|
|
17
|
+
TRANSPORT_ERRORS = [
|
|
18
|
+
SystemCallError,
|
|
19
|
+
SocketError,
|
|
20
|
+
IOError,
|
|
21
|
+
IO::TimeoutError,
|
|
22
|
+
Timeout::Error
|
|
23
|
+
].freeze
|
|
24
|
+
|
|
25
|
+
# Default per-operation IO timeout (seconds) for the search backend.
|
|
26
|
+
# This is an *idle* timeout: every socket read/write must make progress
|
|
27
|
+
# within this window. It bounds a stalled/unresponsive backend without
|
|
28
|
+
# capping the total duration of streaming operations (e.g. bulk import),
|
|
29
|
+
# since data keeps flowing during those. Override per-connection with
|
|
30
|
+
# +timeout:+.
|
|
31
|
+
DEFAULT_TIMEOUT = 5
|
|
32
|
+
|
|
33
|
+
def initialize(hosts: [], timeout: DEFAULT_TIMEOUT, **connection_params)
|
|
10
34
|
# Ensure we always have at least one host
|
|
11
35
|
hosts_array = Array(hosts)
|
|
12
36
|
@hosts = hosts_array.empty? ? ["http://localhost:#{default_port}"] : hosts_array
|
|
37
|
+
@timeout = timeout
|
|
13
38
|
@connection_params = connection_params
|
|
14
39
|
|
|
15
|
-
# Initialize HTTP clients for each host
|
|
40
|
+
# Initialize HTTP clients for each host. The endpoint timeout makes a
|
|
41
|
+
# stalled backend raise IO::TimeoutError (wrapped below as
|
|
42
|
+
# ConnectionError) instead of blocking the fiber/reactor indefinitely.
|
|
16
43
|
@clients = {}
|
|
17
44
|
@hosts.each do |host|
|
|
18
|
-
endpoint = Async::HTTP::Endpoint.parse(host)
|
|
45
|
+
endpoint = Async::HTTP::Endpoint.parse(host, timeout: @timeout)
|
|
19
46
|
@clients[host] = Async::HTTP::Client.new(endpoint)
|
|
20
47
|
end
|
|
21
48
|
|
|
@@ -68,7 +95,19 @@ module Noiseless
|
|
|
68
95
|
host = @hosts.sample
|
|
69
96
|
client = @clients[host]
|
|
70
97
|
|
|
71
|
-
yield(client)
|
|
98
|
+
wrap_transport_errors(host: host) { yield(client) }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def parse_json_response!(response, error_class: Noiseless::RequestError, context: nil)
|
|
102
|
+
wrap_transport_errors { super }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def wrap_transport_errors(host: nil)
|
|
106
|
+
yield
|
|
107
|
+
rescue *TRANSPORT_ERRORS => e
|
|
108
|
+
location = host ? " at #{host}" : ""
|
|
109
|
+
raise Noiseless::ConnectionError,
|
|
110
|
+
"search backend unreachable#{location} (#{e.class}: #{e.message})"
|
|
72
111
|
end
|
|
73
112
|
|
|
74
113
|
def default_headers
|
data/lib/noiseless/callbacks.rb
CHANGED
|
@@ -54,7 +54,7 @@ module Noiseless
|
|
|
54
54
|
return unless should_update_search_index?
|
|
55
55
|
|
|
56
56
|
update_search_index_async if noiseless_new_record? || (respond_to?(:changed?) && changed?)
|
|
57
|
-
rescue
|
|
57
|
+
rescue Noiseless::Error => e
|
|
58
58
|
handle_search_index_error(e, :update)
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -62,7 +62,7 @@ module Noiseless
|
|
|
62
62
|
return unless should_update_search_index?
|
|
63
63
|
|
|
64
64
|
update_search_index_async
|
|
65
|
-
rescue
|
|
65
|
+
rescue Noiseless::Error => e
|
|
66
66
|
handle_search_index_error(e, :update)
|
|
67
67
|
end
|
|
68
68
|
|
|
@@ -70,7 +70,7 @@ module Noiseless
|
|
|
70
70
|
return unless should_update_search_index?
|
|
71
71
|
|
|
72
72
|
remove_from_search_index_async
|
|
73
|
-
rescue
|
|
73
|
+
rescue Noiseless::Error => e
|
|
74
74
|
handle_search_index_error(e, :delete)
|
|
75
75
|
end
|
|
76
76
|
|
|
@@ -78,7 +78,7 @@ module Noiseless
|
|
|
78
78
|
return unless should_update_search_index?
|
|
79
79
|
|
|
80
80
|
remove_from_search_index_async
|
|
81
|
-
rescue
|
|
81
|
+
rescue Noiseless::Error => e
|
|
82
82
|
handle_search_index_error(e, :delete)
|
|
83
83
|
end
|
|
84
84
|
|
|
@@ -8,8 +8,8 @@ module Noiseless
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
# Register a named client statically from YAML (boot-time only)
|
|
11
|
-
def register(name, adapter:, hosts:)
|
|
12
|
-
@configs[name.to_sym] = { adapter: adapter, hosts: hosts }
|
|
11
|
+
def register(name, adapter:, hosts:, timeout: nil)
|
|
12
|
+
@configs[name.to_sym] = { adapter: adapter, hosts: hosts, timeout: timeout }
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# Retrieve a client; defaults to :primary
|
|
@@ -19,7 +19,9 @@ module Noiseless
|
|
|
19
19
|
# Lazy-load the adapter only when actually used
|
|
20
20
|
@clients[name] ||= begin
|
|
21
21
|
config = @configs.fetch(name) { raise "Unknown connection: #{name}" }
|
|
22
|
-
|
|
22
|
+
params = { hosts: config[:hosts] }
|
|
23
|
+
params[:timeout] = config[:timeout] unless config[:timeout].nil?
|
|
24
|
+
Adapters.lookup(config[:adapter], **params)
|
|
23
25
|
end
|
|
24
26
|
end
|
|
25
27
|
end
|
data/lib/noiseless/version.rb
CHANGED
data/lib/noiseless.rb
CHANGED
|
@@ -32,6 +32,14 @@ module Noiseless
|
|
|
32
32
|
# (malformed query, missing index, shard failures).
|
|
33
33
|
class SearchError < RequestError; end
|
|
34
34
|
|
|
35
|
+
# Raised when the search backend cannot be reached at all: connection
|
|
36
|
+
# refused, DNS failure, reset socket, or transport timeout. Distinct from
|
|
37
|
+
# RequestError, which means the backend *was* reached and replied with an
|
|
38
|
+
# HTTP error. Wrapping happens at the transport boundary (HttpTransport),
|
|
39
|
+
# so callers rescue Noiseless::Error instead of enumerating socket/system
|
|
40
|
+
# exception classes from whatever HTTP stack the transport happens to use.
|
|
41
|
+
class ConnectionError < Error; end
|
|
42
|
+
|
|
35
43
|
class Configuration
|
|
36
44
|
attr_accessor :connections_config, :default_connection, :default_adapter, :config_path
|
|
37
45
|
|
|
@@ -85,7 +93,7 @@ module Noiseless
|
|
|
85
93
|
config.connections_config.each do |name, params|
|
|
86
94
|
adapter_name = params[:adapter]
|
|
87
95
|
hosts = params[:hosts] || []
|
|
88
|
-
connections.register(name, adapter: adapter_name, hosts: hosts)
|
|
96
|
+
connections.register(name, adapter: adapter_name, hosts: hosts, timeout: params[:timeout])
|
|
89
97
|
end
|
|
90
98
|
end
|
|
91
99
|
|