noiseless 0.6.0 → 0.7.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: 191caa0c33ef498748dcff326328dbd5e02b7f3a225ef1999b91127edb23490b
4
- data.tar.gz: 3260bb7ca298d9b3ccdfb9e89a5a6e89759dbe56e2637b811439653cef4f9673
3
+ metadata.gz: 1d1df760c71373680498360fa0daef2cfc6a2dd42b08c7edd67f1027174958a5
4
+ data.tar.gz: bd720e1daa952b0c64c769a1f2927d5dd9083a5c3722c97c71fc644ab47f0670
5
5
  SHA512:
6
- metadata.gz: eff7ee517dd4bea214b4602231baf34e518fc01546f3fe47f8b759aa75efb889aa6113bca2de56031b5ebf01ac893099217be4f5afc7af7c0802bf8686759601
7
- data.tar.gz: f0cd3e05dafd3b3a86a7d6a278eac89a5230dbd859674fe209264e8b033a8ec75640a44d969ec1cf945e3ad414fa4137b9816871f1c05e9e30d1e6eb9957d6c9
6
+ metadata.gz: 1802b68562f768b1eee9c5533d26f9a5f387cc8d3052f27474809f889ea142bc8d6903ca4c60c56cfae2989c6e5e36def0abcac0f205d8fe6e86f1a4d87bd979
7
+ data.tar.gz: 8fad323b3284af9d96d9609dac487fa2980310d3470b074d0d135b2fbc09eef80d294f9369ae3836ec9fa6b0b7d515ed6cf1c7724e88ab55729a0e66ac1ae11d
@@ -359,8 +359,8 @@ module Noiseless
359
359
  end
360
360
 
361
361
  def build_aggregations_hash(aggregations)
362
- aggregations.each_with_object({}) do |agg, hash|
363
- hash[agg.name] = build_single_aggregation(agg)
362
+ aggregations.to_h do |agg|
363
+ [agg.name, build_single_aggregation(agg)]
364
364
  end
365
365
  end
366
366
 
@@ -30,11 +30,27 @@ module Noiseless
30
30
  # +timeout:+.
31
31
  DEFAULT_TIMEOUT = 5
32
32
 
33
- def initialize(hosts: [], timeout: DEFAULT_TIMEOUT, **connection_params)
33
+ # Default wall-clock deadline (seconds) for a complete round-trip:
34
+ # request write, response headers, and full body. The idle timeout
35
+ # above never trips against a backend that keeps trickling bytes —
36
+ # each read makes "progress" — which leaves callers blocked in
37
+ # Sync { ... .wait } indefinitely. This caps total duration instead.
38
+ # Override per-connection with +request_timeout:+; nil disables the
39
+ # deadline (long bulk imports may need a higher value or nil).
40
+ DEFAULT_REQUEST_TIMEOUT = 30
41
+
42
+ BufferedResponse = Struct.new(:status, :body) do
43
+ def read = body
44
+ def success? = (200..299).cover?(status)
45
+ def close = nil
46
+ end
47
+
48
+ def initialize(hosts: [], timeout: DEFAULT_TIMEOUT, request_timeout: DEFAULT_REQUEST_TIMEOUT, **connection_params)
34
49
  # Ensure we always have at least one host
35
50
  hosts_array = Array(hosts)
36
51
  @hosts = hosts_array.empty? ? ["http://localhost:#{default_port}"] : hosts_array
37
52
  @timeout = timeout
53
+ @request_timeout = request_timeout
38
54
  @connection_params = connection_params
39
55
 
40
56
  # Initialize HTTP clients for each host. The endpoint timeout makes a
@@ -95,7 +111,27 @@ module Noiseless
95
111
  host = @hosts.sample
96
112
  client = @clients[host]
97
113
 
98
- wrap_transport_errors(host: host) { yield(client) }
114
+ wrap_transport_errors(host: host) do
115
+ with_request_deadline(host: host) do
116
+ buffer_response(yield(client))
117
+ end
118
+ end
119
+ end
120
+
121
+ def with_request_deadline(host:, &)
122
+ task = @request_timeout && Async::Task.current?
123
+ return yield unless task
124
+
125
+ task.with_timeout(@request_timeout, &)
126
+ rescue Async::TimeoutError
127
+ raise Noiseless::ConnectionError,
128
+ "search backend at #{host} exceeded request_timeout (#{@request_timeout}s wall-clock)"
129
+ end
130
+
131
+ def buffer_response(response)
132
+ BufferedResponse.new(response.status, response.read)
133
+ ensure
134
+ response.close
99
135
  end
100
136
 
101
137
  def parse_json_response!(response, error_class: Noiseless::RequestError, context: nil)
@@ -402,7 +402,7 @@ module Noiseless
402
402
  headers
403
403
  end
404
404
 
405
- # rubocop:disable Lint/DuplicateBranch
405
+ # rubocop:disable-next Lint/DuplicateBranch
406
406
  def map_type_to_typesense(elasticsearch_type)
407
407
  # Map Elasticsearch types to Typesense types
408
408
  case elasticsearch_type
@@ -418,7 +418,6 @@ module Noiseless
418
418
  "string" # Default to string for unknown types
419
419
  end
420
420
  end
421
- # rubocop:enable Lint/DuplicateBranch
422
421
  end
423
422
  end
424
423
  end
@@ -7,9 +7,10 @@ module Noiseless
7
7
  @configs = {}
8
8
  end
9
9
 
10
- # Register a named client statically from YAML (boot-time only)
11
- def register(name, adapter:, hosts:, timeout: nil)
12
- @configs[name.to_sym] = { adapter: adapter, hosts: hosts, timeout: timeout }
10
+ # Register a named client statically from YAML (boot-time only).
11
+ # request_timeout: :default uses the adapter default, nil disables the deadline.
12
+ def register(name, adapter:, hosts:, timeout: nil, request_timeout: :default)
13
+ @configs[name.to_sym] = { adapter: adapter, hosts: hosts, timeout: timeout, request_timeout: request_timeout }
13
14
  end
14
15
 
15
16
  # Retrieve a client; defaults to :primary
@@ -21,6 +22,7 @@ module Noiseless
21
22
  config = @configs.fetch(name) { raise "Unknown connection: #{name}" }
22
23
  params = { hosts: config[:hosts] }
23
24
  params[:timeout] = config[:timeout] unless config[:timeout].nil?
25
+ params[:request_timeout] = config[:request_timeout] unless config[:request_timeout] == :default
24
26
  Adapters.lookup(config[:adapter], **params)
25
27
  end
26
28
  end
@@ -221,13 +221,13 @@ module Noiseless
221
221
  end
222
222
 
223
223
  def to_ast
224
- filter_nodes = @nodes.select { |n| n.is_a?(AST::Filter) }
225
- vector_nodes = @nodes.select { |n| n.is_a?(AST::Vector) }
224
+ filter_nodes = @nodes.grep(AST::Filter)
225
+ vector_nodes = @nodes.grep(AST::Vector)
226
226
  must_nodes = @nodes.reject do |n|
227
227
  n.is_a?(AST::Filter) || n.is_a?(AST::Sort) || n.is_a?(AST::Paginate) || n.is_a?(AST::Vector)
228
228
  end
229
229
  bool_node = AST::Bool.new(must: must_nodes, filter: filter_nodes)
230
- sort_nodes = @nodes.select { |n| n.is_a?(AST::Sort) }
230
+ sort_nodes = @nodes.grep(AST::Sort)
231
231
  paginate_node = @nodes.find { |n| n.is_a?(AST::Paginate) }
232
232
  AST::Root.new(
233
233
  indexes: @indexes,
@@ -13,7 +13,7 @@ module Noiseless
13
13
  end
14
14
 
15
15
  def each
16
- return enum_for(__method__) unless block_given?
16
+ enum_for(__method__) unless block_given?
17
17
  end
18
18
  end
19
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Noiseless
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/noiseless.rb CHANGED
@@ -98,7 +98,9 @@ module Noiseless
98
98
  config.connections_config.each do |name, params|
99
99
  adapter_name = params[:adapter]
100
100
  hosts = params[:hosts] || []
101
- connections.register(name, adapter: adapter_name, hosts: hosts, timeout: params[:timeout])
101
+ register_params = { adapter: adapter_name, hosts: hosts, timeout: params[:timeout] }
102
+ register_params[:request_timeout] = params[:request_timeout] if params.key?(:request_timeout)
103
+ connections.register(name, **register_params)
102
104
  end
103
105
  end
104
106
 
@@ -11,9 +11,7 @@ namespace :release do
11
11
  version_path = File.expand_path("../../lib/noiseless/version", __dir__)
12
12
  require version_path
13
13
 
14
- if spec.version.to_s != Noiseless::VERSION
15
- raise "Version mismatch: gemspec=#{spec.version} lib=#{Noiseless::VERSION}"
16
- end
14
+ raise "Version mismatch: gemspec=#{spec.version} lib=#{Noiseless::VERSION}" if spec.version.to_s != Noiseless::VERSION
17
15
 
18
16
  ruby = Shellwords.escape(RbConfig.ruby)
19
17
  sh "#{ruby} -Ilib -e 'require \"noiseless\"; abort(\"version mismatch\") unless Noiseless::VERSION == \"#{Noiseless::VERSION}\"'"
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.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -29,42 +29,42 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.20'
32
+ version: '2.45'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '2.20'
39
+ version: '2.45'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: async-http
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '0.80'
46
+ version: '0.103'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '0.80'
53
+ version: '0.103'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: async-pool
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '0.8'
60
+ version: '0.11'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '0.8'
67
+ version: '0.11'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: railties
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -85,14 +85,14 @@ dependencies:
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '2.7'
88
+ version: '2.8'
89
89
  type: :runtime
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '2.7'
95
+ version: '2.8'
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: async-safe
98
98
  requirement: !ruby/object:Gem::Requirement
@@ -109,6 +109,20 @@ dependencies:
109
109
  version: '0.5'
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: minitest
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '6.0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '6.0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: minitest-mock
112
126
  requirement: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - "~>"