nonnative 3.6.0 → 3.10.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: 0fb25075ea94da70b097c6b60e7a47fea1a73b7e80d4903f32b2a2d00675b50e
4
- data.tar.gz: 33c1c4310fa48a1a8dacf792d9ce6af73f9a406f67185f61fb292f07d06d2345
3
+ metadata.gz: 6a276b7ac5edae149fc6eb065909773b73c5c7e1684e4502244d88a0cdd6c521
4
+ data.tar.gz: 82545f52a383ba1f67af5c1d01c72653adee7339a3e1968fb987eabc9236421e
5
5
  SHA512:
6
- metadata.gz: c1c7e788eacbf1ed02100d4fc954f3ab7781c17a4e8c46c8ca8764becea615d54c6dee3be60404901228b37397533a809873c3ae27a157ac53463ff048ce8d50
7
- data.tar.gz: fc73665d0141f943beca8dd9d43adbee088a214d1d31dad757fed1502df707f8ae599f10f4d5b3eb0b0c7e8c7db4b43b860cdd655e90d49c194320148df65439
6
+ metadata.gz: 0eea335efd1554822d7153077244d2f8ff5d19c46af6b19e153bd0298e99e4902f090b933899d4614e46a88252d9b95e9f7ec92b3d6e9e824c96f00694d579f9
7
+ data.tar.gz: ce2d8e41f9313b289c3531fe8c605e869dd856a1eb8ae47bb1671ebc12aa1f97a3a8e795cad16681c11857b2a70ce4f2250b0310dd57286162cc9aed7efa764e
data/.circleci/config.yml CHANGED
@@ -32,13 +32,13 @@ jobs:
32
32
  - restore_cache:
33
33
  name: restore deps
34
34
  keys:
35
- - nonnative-ruby-cache-{{ checksum "Gemfile.lock" }}-{{ checksum "~/.ruby-version" }}-{{ checksum ".source-key" }}
35
+ - nonnative-ruby-cache-{{ checksum "Gemfile.lock" }}-{{ checksum "~/.ruby-version" }}
36
36
  - nonnative-ruby-cache-
37
37
  - run: make dep
38
38
  - run: make clean-dep
39
39
  - save_cache:
40
40
  name: save deps
41
- key: nonnative-ruby-cache-{{ checksum "Gemfile.lock" }}-{{ checksum "~/.ruby-version" }}-{{ checksum ".source-key" }}
41
+ key: nonnative-ruby-cache-{{ checksum "Gemfile.lock" }}-{{ checksum "~/.ruby-version" }}
42
42
  paths:
43
43
  - vendor
44
44
  - run: make lint
data/AGENTS.md CHANGED
@@ -74,6 +74,11 @@ of dependencies.
74
74
  use `nonnative` against real dependencies. Do not flag the in-repository
75
75
  service proxy success scenario's connection-only assertion as a test gap
76
76
  unless the task is explicitly about changing service proxy forwarding.
77
+ - `Nonnative::FaultInjectionProxy` owns its listener thread and stops it by
78
+ closing the owned `TCPServer`, which wakes the accept loop before joining the
79
+ thread. Do not flag the listener `join` as an unbounded reliability gap unless
80
+ the task is explicitly about proxy shutdown behavior or there is a normal-use
81
+ reproducer, failing CI evidence, or platform-specific hang evidence.
77
82
 
78
83
  ## Runtime Model
79
84
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (3.6.0)
4
+ nonnative (3.10.0)
5
5
  concurrent-ruby (>= 1, < 2)
6
6
  config (>= 5, < 6)
7
7
  cucumber (>= 7, < 12)
data/README.md CHANGED
@@ -66,13 +66,16 @@ Process/server fields:
66
66
  - `wait`: small sleep (seconds) between lifecycle steps.
67
67
  - `log`: per-runner log file used by process output redirection or server implementations.
68
68
 
69
+ Process-only fields:
70
+ - `readiness`: optional HTTP startup readiness check with explicit `port` and `path`.
71
+
69
72
  Service fields:
70
73
  - `port`: client-facing service port. Services do not get TCP readiness/shutdown checks from Nonnative.
71
74
 
72
- Nonnative readiness and shutdown checks are TCP-only. Configure process/server ports that are dedicated to the test run; if another process is already listening on the same endpoint, results are undefined.
75
+ Nonnative readiness and shutdown checks are TCP port checks by default. Configure process/server ports that are dedicated to the test run; if another process is already listening on the same endpoint, results are undefined. Processes can also opt into an HTTP readiness check that runs after TCP readiness succeeds.
73
76
 
74
77
  > [!WARNING]
75
- > Readiness and shutdown checks only prove that a TCP port opened or closed. They do not verify HTTP status, gRPC health, schema readiness, migrations, or application-specific health.
78
+ > TCP readiness and shutdown checks only prove that a TCP port opened or closed. HTTP readiness is process-only, checks for a 2xx response, and does not verify gRPC health, schema readiness, migrations, or other application-specific health.
76
79
 
77
80
  Start and stop Nonnative around the test scope that should own the configured runners:
78
81
 
@@ -91,7 +94,9 @@ Nonnative.stop
91
94
  `Nonnative.start` starts services first, then servers and processes. `Nonnative.stop` stops processes and servers first, then services. If startup fails, Nonnative rolls back runners that already started and raises `Nonnative::StartError`; shutdown failures raise `Nonnative::StopError`.
92
95
 
93
96
  > [!NOTE]
94
- > `Nonnative.clear` clears memoized configuration, logger, observability client, and pool. Use it before reconfiguring Nonnative in the same Ruby process.
97
+ > `Nonnative.start` / `Nonnative.stop` manage one lifecycle for the current pool.
98
+ > Call `Nonnative.clear` before reconfiguring Nonnative or starting a new lifecycle in the same Ruby process.
99
+ > `Nonnative.clear` clears memoized configuration, logger, observability client, and pool.
95
100
 
96
101
  ### 📈 Observability
97
102
 
@@ -170,6 +175,7 @@ Nonnative.configure do |config|
170
175
  p.ports = [12_321]
171
176
  p.log = '12_321.log'
172
177
  p.signal = 'INT' # Possible values are described in Signal.list.keys.
178
+ p.readiness = { port: 12_321, path: '/test/readyz' }
173
179
  p.environment = { # Pass environment variables to process.
174
180
  'TEST' => 'true'
175
181
  }
@@ -205,6 +211,9 @@ processes:
205
211
  - 12321
206
212
  log: 12_321.log
207
213
  signal: INT # Possible values are described in Signal.list.keys.
214
+ readiness:
215
+ port: 12321
216
+ path: /test/readyz
208
217
  environment: # Pass environment variables to process.
209
218
  TEST: true
210
219
  -
@@ -612,7 +621,7 @@ These proxies can simulate different situations. Available proxy kinds are:
612
621
  - `fault_injection`
613
622
 
614
623
  > [!WARNING]
615
- > Unknown proxy kinds fall back to `none`. If fault injection is not taking effect, check the `kind` spelling or register the custom kind before loading the configuration.
624
+ > Unknown proxy kinds raise an error. If fault injection is not taking effect, check the `kind` spelling or register the custom kind before starting the system.
616
625
 
617
626
  Custom proxy kinds can be registered through `Nonnative.proxies`:
618
627
 
@@ -22,6 +22,7 @@ module Nonnative
22
22
  # p.ports = [8080, 9090]
23
23
  # p.timeout = 10
24
24
  # p.log = 'api.log'
25
+ # p.readiness = { port: 8080, path: '/example/readyz' }
25
26
  # end
26
27
  # end
27
28
  #
@@ -142,6 +143,7 @@ module Nonnative
142
143
  process_config.command = command(loaded_process)
143
144
  process_config.signal = loaded_process.signal
144
145
  process_config.environment = loaded_process.environment
146
+ process_config.readiness = loaded_process.readiness if loaded_process.readiness
145
147
  runner_attributes(process_config, loaded_process)
146
148
  end
147
149
  end
@@ -163,6 +165,7 @@ module Nonnative
163
165
  servers = cfg.servers || []
164
166
  servers.each do |loaded_server|
165
167
  reject_proxy(loaded_server, 'servers')
168
+ reject_readiness(loaded_server, 'servers')
166
169
 
167
170
  server do |server_config|
168
171
  server_config.klass = Object.const_get(server_class_name(loaded_server))
@@ -174,6 +177,8 @@ module Nonnative
174
177
  def add_services(cfg)
175
178
  services = cfg.services || []
176
179
  services.each do |loaded_service|
180
+ reject_readiness(loaded_service, 'services')
181
+
177
182
  service do |service_config|
178
183
  service_config.name = loaded_service.name
179
184
  service_config.host = loaded_service.host if loaded_service.host
@@ -220,6 +225,13 @@ module Nonnative
220
225
  raise ArgumentError, "Use 'services' for proxy configuration; #{kind} do not support 'proxy'"
221
226
  end
222
227
 
228
+ def reject_readiness(loaded, kind)
229
+ values = loaded.to_h
230
+ return unless values.key?(:readiness) || values.key?('readiness')
231
+
232
+ raise ArgumentError, "Use 'processes' for readiness configuration; #{kind} do not support 'readiness'"
233
+ end
234
+
223
235
  def assign_proxy(service, loaded_proxy)
224
236
  return unless loaded_proxy
225
237
 
@@ -28,6 +28,9 @@ module Nonnative
28
28
  # @return [Hash, nil] environment variables to pass to the spawned process
29
29
  attr_accessor :environment
30
30
 
31
+ # @return [Nonnative::ConfigurationReadiness, nil] optional HTTP readiness check
32
+ attr_reader :readiness
33
+
31
34
  # Creates a process configuration with bounded lifecycle defaults.
32
35
  #
33
36
  # Defaults:
@@ -39,5 +42,13 @@ module Nonnative
39
42
 
40
43
  self.timeout = DEFAULT_TIMEOUT
41
44
  end
45
+
46
+ # Sets optional HTTP readiness configuration.
47
+ #
48
+ # @param value [Hash, #to_h, nil] readiness attributes with required `port` and `path`
49
+ # @return [void]
50
+ def readiness=(value)
51
+ @readiness = value.nil? ? nil : Nonnative::ConfigurationReadiness.new(value)
52
+ end
42
53
  end
43
54
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ # HTTP readiness configuration for a managed process.
5
+ #
6
+ # Readiness is optional. When present, both `port` and `path` are required so the startup
7
+ # check has an explicit application endpoint to poll after TCP readiness succeeds.
8
+ class ConfigurationReadiness
9
+ # @return [Integer] process HTTP readiness port
10
+ attr_accessor :port
11
+
12
+ # @return [String] HTTP readiness path
13
+ attr_accessor :path
14
+
15
+ # @param value [Hash, #to_h] readiness attributes
16
+ def initialize(value)
17
+ attributes = value.respond_to?(:to_h) ? value.to_h : value
18
+ self.port = attribute(attributes, :port)
19
+ self.path = attribute(attributes, :path)
20
+
21
+ validate!
22
+ end
23
+
24
+ private
25
+
26
+ def attribute(attributes, name)
27
+ attributes[name] || attributes[name.to_s]
28
+ end
29
+
30
+ def validate!
31
+ raise ArgumentError, "Process readiness requires 'port'" if port.nil?
32
+ raise ArgumentError, "Process readiness requires 'path'" if path.nil?
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ # Probes a managed process HTTP readiness endpoint.
5
+ class HTTPProbe < Nonnative::HTTPClient
6
+ NETWORK_ERRORS = [
7
+ Errno::ECONNREFUSED,
8
+ Errno::EHOSTUNREACH,
9
+ Errno::ECONNRESET,
10
+ SocketError,
11
+ RestClient::Exceptions::Timeout,
12
+ RestClient::ServerBrokeConnection
13
+ ].freeze
14
+
15
+ # @param process [Nonnative::ConfigurationProcess] process configuration with readiness attributes
16
+ def initialize(process)
17
+ @readiness = process.readiness
18
+ @base_url = "http://#{process.host}:#{readiness.port}"
19
+ @timeout = Nonnative::Timeout.new(process.timeout)
20
+
21
+ super(base_url)
22
+ end
23
+
24
+ # Returns whether the configured HTTP endpoint returns a 2xx response before timeout.
25
+ #
26
+ # @return [Boolean]
27
+ def ready?
28
+ Nonnative.logger.info "checking if readiness '#{endpoint}' is ready"
29
+
30
+ timeout.perform do
31
+ response = get(readiness.path)
32
+ raise Nonnative::Error unless ready_response?(response)
33
+
34
+ true
35
+ rescue Nonnative::Error, *NETWORK_ERRORS
36
+ sleep_interval
37
+ retry
38
+ end
39
+ end
40
+
41
+ # Returns the HTTP readiness endpoint for lifecycle diagnostics.
42
+ #
43
+ # @return [String]
44
+ def endpoint
45
+ "#{base_url}#{path}"
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :base_url, :readiness, :timeout
51
+
52
+ def path
53
+ readiness.path.start_with?('/') ? readiness.path : "/#{readiness.path}"
54
+ end
55
+
56
+ def ready_response?(response)
57
+ response.respond_to?(:code) && response.code.to_i.between?(200, 299)
58
+ end
59
+
60
+ def sleep_interval
61
+ sleep 0.01
62
+ end
63
+ end
64
+ end
@@ -3,7 +3,7 @@
3
3
  module Nonnative
4
4
  # No-op proxy implementation.
5
5
  #
6
- # This is the default proxy when `service.proxy.kind` is `"none"` (or an unknown kind is provided).
6
+ # This is the default proxy when `service.proxy.kind` is `"none"`.
7
7
  # It does not bind/listen or alter traffic; it simply exposes the underlying runner's configured
8
8
  # `host` and primary `port`.
9
9
  #
@@ -30,6 +30,7 @@ module Nonnative
30
30
  # @yieldparam name [String, nil] runner name
31
31
  # @yieldparam values [Object] runner-specific return value from `start` (e.g. `[pid, running]` for processes)
32
32
  # @yieldparam result [Boolean] result of the port readiness check (`true` if ready in time)
33
+ # @yieldparam port [Nonnative::Ports] checked port group
33
34
  # @return [Array<String>] lifecycle and readiness-check errors collected while starting
34
35
  def start(&)
35
36
  errors = []
@@ -47,6 +48,7 @@ module Nonnative
47
48
  # @yieldparam name [String, nil] runner name
48
49
  # @yieldparam id [Object] runner-specific identifier returned by `stop` (e.g. pid or object_id)
49
50
  # @yieldparam result [Boolean] result of the port shutdown check (`true` if closed in time)
51
+ # @yieldparam port [Nonnative::Ports] checked port group
50
52
  # @return [Array<String>] lifecycle and shutdown-check errors collected while stopping
51
53
  def stop(&)
52
54
  errors = []
@@ -65,6 +67,7 @@ module Nonnative
65
67
  # @yieldparam name [String, nil] runner name
66
68
  # @yieldparam id [Object] runner-specific identifier returned by `stop`
67
69
  # @yieldparam result [Boolean] result of the port shutdown check (`true` if closed in time)
70
+ # @yieldparam port [Nonnative::Ports] checked port group
68
71
  # @return [Array<String>] lifecycle and shutdown-check errors collected while rolling back
69
72
  def rollback(&)
70
73
  errors = []
@@ -183,7 +186,7 @@ module Nonnative
183
186
 
184
187
  runners.each do |runner, port|
185
188
  values = runner.send(lifecycle_method)
186
- checks << [runner, values, Thread.new { check_port(port, port_method) }]
189
+ checks << [runner, values, port, Thread.new { check_port(port, port_method) }]
187
190
  rescue StandardError => e
188
191
  errors << lifecycle_error(action, runner, e)
189
192
  end
@@ -198,12 +201,12 @@ module Nonnative
198
201
  end
199
202
 
200
203
  def yield_results(checks, action, &)
201
- checks.each_with_object([]) do |(type, values, thread), errors|
204
+ checks.each_with_object([]) do |(type, values, port, thread), errors|
202
205
  result = thread.value
203
206
  if result[:error]
204
207
  errors << port_error(action, type, result[:error])
205
208
  elsif block_given?
206
- yield type.name, values, result[:result]
209
+ yield type.name, values, result[:result], port
207
210
  end
208
211
  end
209
212
  end
@@ -61,6 +61,13 @@ module Nonnative
61
61
  end
62
62
  end
63
63
 
64
+ # Returns a human-readable endpoint for lifecycle diagnostics.
65
+ #
66
+ # @return [String]
67
+ def endpoint
68
+ "#{process.host}:#{port}"
69
+ end
70
+
64
71
  private
65
72
 
66
73
  attr_reader :process, :port, :timeout
@@ -10,14 +10,16 @@ module Nonnative
10
10
  class Ports
11
11
  # @param runner [#host, #ports, #timeout] runner configuration providing connection details
12
12
  def initialize(runner)
13
+ @runner = runner
13
14
  @ports = runner.ports.map { |port| Nonnative::Port.new(runner, port) }
15
+ @readiness = Nonnative::HTTPProbe.new(runner) if runner.respond_to?(:readiness) && runner.readiness
14
16
  end
15
17
 
16
18
  # Returns whether all configured ports become connectable before their timeouts elapse.
17
19
  #
18
20
  # @return [Boolean]
19
21
  def open?
20
- ports.all?(&:open?)
22
+ ports.all?(&:open?) && (readiness.nil? || readiness.ready?)
21
23
  end
22
24
 
23
25
  # Returns whether all configured ports become non-connectable before their timeouts elapse.
@@ -27,8 +29,27 @@ module Nonnative
27
29
  ports.all?(&:closed?)
28
30
  end
29
31
 
32
+ # Returns the checked endpoints for lifecycle diagnostics.
33
+ #
34
+ # @return [String]
35
+ def endpoints
36
+ ports.map(&:endpoint).join(', ')
37
+ end
38
+
39
+ # Returns endpoint and log context for lifecycle errors.
40
+ #
41
+ # @return [String]
42
+ def description
43
+ details = []
44
+ details << "readiness: #{readiness.endpoint}" if readiness
45
+ log = runner.log if runner.respond_to?(:log)
46
+ details << "log: #{log}" if log
47
+
48
+ details.empty? ? endpoints : "#{endpoints} (#{details.join('; ')})"
49
+ end
50
+
30
51
  private
31
52
 
32
- attr_reader :ports
53
+ attr_reader :ports, :readiness, :runner
33
54
  end
34
55
  end
@@ -20,6 +20,9 @@ module Nonnative
20
20
  @timeout = Nonnative::Timeout.new(service.timeout)
21
21
  end
22
22
 
23
+ # @return [GetProcessMem, nil] memory reader for the current process lifecycle
24
+ attr_reader :memory
25
+
23
26
  # Spawns the configured process if it is not already running.
24
27
  #
25
28
  # @return [Array<(Integer, Boolean)>]
@@ -29,6 +32,8 @@ module Nonnative
29
32
  def start
30
33
  unless process_exists?
31
34
  @pid = process_spawn
35
+ # Keep memory reads bound to the child spawned for this lifecycle.
36
+ @memory = GetProcessMem.new(pid)
32
37
  wait_start
33
38
  end
34
39
 
@@ -53,17 +58,8 @@ module Nonnative
53
58
  end
54
59
 
55
60
  [pid, stopped]
56
- end
57
-
58
- # Returns a memoized memory reader for the spawned process.
59
- #
60
- # This is primarily used by acceptance tests to assert memory usage.
61
- #
62
- # @return [GetProcessMem, nil] a memory reader for the pid, or `nil` if not started
63
- def memory
64
- return if pid.nil?
65
-
66
- @memory ||= GetProcessMem.new(pid)
61
+ ensure
62
+ @memory = nil
67
63
  end
68
64
 
69
65
  protected
@@ -6,7 +6,9 @@ module Nonnative
6
6
  # A runtime service constructs a proxy via this factory. The proxy implementation is selected by
7
7
  # `service.proxy.kind` and resolved using {Nonnative.proxy}.
8
8
  #
9
- # If the kind is unknown (or `"none"`), {Nonnative.proxy} returns {Nonnative::NoProxy}.
9
+ # If the kind is `"none"`, {Nonnative.proxy} returns {Nonnative::NoProxy}.
10
+ # Unknown non-`"none"` kinds raise an error so proxy configuration typos do not silently disable
11
+ # fault injection.
10
12
  #
11
13
  # @see Nonnative.proxy
12
14
  # @see Nonnative.proxies
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '3.6.0'
7
+ VERSION = '3.10.0'
8
8
  end
data/lib/nonnative.rb CHANGED
@@ -6,7 +6,7 @@
6
6
  # It can:
7
7
  #
8
8
  # - start external processes and in-process servers
9
- # - wait for readiness via port checks
9
+ # - wait for readiness via port checks and optional process HTTP readiness
10
10
  # - optionally run fault-injection proxies in front of services
11
11
  #
12
12
  # The public entry points are exposed as module-level methods on {Nonnative}.
@@ -27,6 +27,7 @@
27
27
  # p.ports = [8080, 9090]
28
28
  # p.timeout = 10
29
29
  # p.log = 'api.log'
30
+ # p.readiness = { port: 8080, path: '/example/readyz' }
30
31
  # end
31
32
  # end
32
33
  #
@@ -72,6 +73,7 @@ require 'nonnative/ports'
72
73
  require 'nonnative/configuration_file'
73
74
  require 'nonnative/configuration'
74
75
  require 'nonnative/configuration_runner'
76
+ require 'nonnative/configuration_readiness'
75
77
  require 'nonnative/configuration_process'
76
78
  require 'nonnative/configuration_server'
77
79
  require 'nonnative/configuration_service'
@@ -82,6 +84,7 @@ require 'nonnative/server'
82
84
  require 'nonnative/service'
83
85
  require 'nonnative/pool'
84
86
  require 'nonnative/http_client'
87
+ require 'nonnative/http_probe'
85
88
  require 'nonnative/http_server'
86
89
  require 'nonnative/http_proxy_server'
87
90
  require 'nonnative/grpc_server'
@@ -204,7 +207,7 @@ module Nonnative
204
207
  # @param kind [String] proxy kind name (for example `"fault_injection"`)
205
208
  # @return [Class] a subclass of {Nonnative::Proxy}
206
209
  def proxy(kind)
207
- Nonnative.proxies[kind] || Nonnative::NoProxy
210
+ kind.nil? || kind == 'none' ? NoProxy : proxies.fetch(kind) { raise ArgumentError, "Unsupported proxy kind '#{kind}'" }
208
211
  end
209
212
 
210
213
  # Starts all configured services, servers, and processes, and waits for readiness.
@@ -216,9 +219,9 @@ module Nonnative
216
219
  def start
217
220
  @pool ||= Nonnative::Pool.new(configuration)
218
221
  errors = []
219
- errors.concat(@pool.start do |name, values, result|
222
+ errors.concat(@pool.start do |name, values, result, ports|
220
223
  id, started = values
221
- errors << "Started #{name} with id #{id}, though did not respond in time" if !started || !result
224
+ errors << "Started #{name} with id #{id}, though did not respond in time for #{ports.description}" if !started || !result
222
225
  end)
223
226
  nil
224
227
  rescue StandardError => e
@@ -239,9 +242,9 @@ module Nonnative
239
242
  errors = []
240
243
  return if @pool.nil?
241
244
 
242
- errors.concat(@pool.stop do |name, values, result|
245
+ errors.concat(@pool.stop do |name, values, result, ports|
243
246
  id, stopped = Array(values).then { |v| [v.first, v.fetch(1, true)] }
244
- errors << "Stopped #{name} with id #{id}, though did not respond in time" unless result
247
+ errors << "Stopped #{name} with id #{id}, though did not respond in time for #{ports.description}" unless result
245
248
  errors << "Stopped #{name} with id #{id}, though the process did not exit in time" unless stopped
246
249
  end)
247
250
  nil
@@ -283,6 +286,9 @@ module Nonnative
283
286
 
284
287
  # Clears memoized configuration, logger, observability client, and pool.
285
288
  #
289
+ # Call this before reconfiguring Nonnative or starting a new lifecycle in the same Ruby process.
290
+ # `start`/`stop` are intended to manage one lifecycle for the current pool.
291
+ #
286
292
  # @return [void]
287
293
  def clear
288
294
  clear_logger
@@ -305,9 +311,9 @@ module Nonnative
305
311
  errors = []
306
312
  return errors if @pool.nil?
307
313
 
308
- errors.concat(@pool.rollback do |name, values, result|
314
+ errors.concat(@pool.rollback do |name, values, result, ports|
309
315
  id, stopped = Array(values).then { |v| [v.first, v.fetch(1, true)] }
310
- errors << "Rollback failed for #{name} with id #{id}, because it did not stop in time" unless result
316
+ errors << "Rollback failed for #{name} with id #{id}, because it did not stop in time for #{ports.description}" unless result
311
317
  errors << "Rollback failed for #{name} with id #{id}, because the process did not exit in time" unless stopped
312
318
  end)
313
319
  rescue StandardError => e
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski
@@ -291,6 +291,7 @@ files:
291
291
  - lib/nonnative/configuration_file.rb
292
292
  - lib/nonnative/configuration_process.rb
293
293
  - lib/nonnative/configuration_proxy.rb
294
+ - lib/nonnative/configuration_readiness.rb
294
295
  - lib/nonnative/configuration_runner.rb
295
296
  - lib/nonnative/configuration_server.rb
296
297
  - lib/nonnative/configuration_service.rb
@@ -302,6 +303,7 @@ files:
302
303
  - lib/nonnative/grpc_server.rb
303
304
  - lib/nonnative/header.rb
304
305
  - lib/nonnative/http_client.rb
306
+ - lib/nonnative/http_probe.rb
305
307
  - lib/nonnative/http_proxy_server.rb
306
308
  - lib/nonnative/http_server.rb
307
309
  - lib/nonnative/invalid_data_socket_pair.rb