noiseless 0.4.0 → 0.6.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: 1a2c76e38f11ce0e3d82ecea5c3644022e1b793613e413f81987063e333da393
4
- data.tar.gz: 7b862a6892326ed2fff34d3aa087d2cdfeafbc1b007b5f5c6285286d12d26a4f
3
+ metadata.gz: 191caa0c33ef498748dcff326328dbd5e02b7f3a225ef1999b91127edb23490b
4
+ data.tar.gz: 3260bb7ca298d9b3ccdfb9e89a5a6e89759dbe56e2637b811439653cef4f9673
5
5
  SHA512:
6
- metadata.gz: d25d6a3a8fd986c7f99454f358da6abe29a7c64ee4beddab5925a83c580469625dfc20bf6b19e6ca6af0448ea87093d05275b24ef23d7b4b9b17edc93ceec9a4
7
- data.tar.gz: 61371d2765af21a3d689931abe71afe4b13942fe4b6c7621115b0d75b1ce0a4d249b28f7ffb40a66e1ab28d5da57f65d3d8814e62372bd13c05c74885cd26507
6
+ metadata.gz: eff7ee517dd4bea214b4602231baf34e518fc01546f3fe47f8b759aa75efb889aa6113bca2de56031b5ebf01ac893099217be4f5afc7af7c0802bf8686759601
7
+ data.tar.gz: f0cd3e05dafd3b3a86a7d6a278eac89a5230dbd859674fe209264e8b033a8ec75640a44d969ec1cf945e3ad414fa4137b9816871f1c05e9e30d1e6eb9957d6c9
@@ -14,17 +14,35 @@ module Noiseless
14
14
  # DNS failure, transport timeout). These are wrapped into
15
15
  # Noiseless::ConnectionError so callers never have to know which HTTP
16
16
  # stack is underneath.
17
- TRANSPORT_ERRORS = [SystemCallError, SocketError, IOError, Timeout::Error].freeze
18
- def initialize(hosts: [], **connection_params)
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)
19
34
  # Ensure we always have at least one host
20
35
  hosts_array = Array(hosts)
21
36
  @hosts = hosts_array.empty? ? ["http://localhost:#{default_port}"] : hosts_array
37
+ @timeout = timeout
22
38
  @connection_params = connection_params
23
39
 
24
- # 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.
25
43
  @clients = {}
26
44
  @hosts.each do |host|
27
- endpoint = Async::HTTP::Endpoint.parse(host)
45
+ endpoint = Async::HTTP::Endpoint.parse(host, timeout: @timeout)
28
46
  @clients[host] = Async::HTTP::Client.new(endpoint)
29
47
  end
30
48
 
@@ -77,10 +95,19 @@ module Noiseless
77
95
  host = @hosts.sample
78
96
  client = @clients[host]
79
97
 
80
- 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
81
107
  rescue *TRANSPORT_ERRORS => e
108
+ location = host ? " at #{host}" : ""
82
109
  raise Noiseless::ConnectionError,
83
- "search backend unreachable at #{host} (#{e.class}: #{e.message})"
110
+ "search backend unreachable#{location} (#{e.class}: #{e.message})"
84
111
  end
85
112
 
86
113
  def default_headers
@@ -39,6 +39,7 @@ module Noiseless
39
39
  private
40
40
 
41
41
  def should_update_search_index?
42
+ return false unless Noiseless.config.auto_index
42
43
  return false if Thread.current[:noiseless_skip_auto_index]
43
44
  return false unless self.class.auto_index_enabled?
44
45
 
@@ -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
- Adapters.lookup(config[:adapter], hosts: config[:hosts])
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Noiseless
4
- VERSION = "0.4.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/noiseless.rb CHANGED
@@ -42,11 +42,16 @@ module Noiseless
42
42
 
43
43
  class Configuration
44
44
  attr_accessor :connections_config, :default_connection, :default_adapter, :config_path
45
+ # Global kill switch for model auto-indexing callbacks. Lets environments
46
+ # without a search backend (e.g. CI) run without connection-error noise on
47
+ # every save. Defaults to NOISELESS_AUTO_INDEX env var, on unless "false".
48
+ attr_accessor :auto_index
45
49
 
46
50
  def initialize
47
51
  @connections_config = {}
48
52
  @default_connection = :primary
49
53
  @default_adapter = :opensearch
54
+ @auto_index = ENV.fetch("NOISELESS_AUTO_INDEX", "true") != "false"
50
55
  @config_path = lambda do
51
56
  if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
52
57
  Rails.root.join("config/noiseless.yml")
@@ -93,7 +98,7 @@ module Noiseless
93
98
  config.connections_config.each do |name, params|
94
99
  adapter_name = params[:adapter]
95
100
  hosts = params[:hosts] || []
96
- connections.register(name, adapter: adapter_name, hosts: hosts)
101
+ connections.register(name, adapter: adapter_name, hosts: hosts, timeout: params[:timeout])
97
102
  end
98
103
  end
99
104
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noiseless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -294,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
294
294
  - !ruby/object:Gem::Version
295
295
  version: '0'
296
296
  requirements: []
297
- rubygems_version: 3.6.9
297
+ rubygems_version: 4.0.10
298
298
  specification_version: 4
299
299
  summary: Async-first Rails search abstraction with multi-backend support
300
300
  test_files: []