jetstream_bridge 4.2.0 → 4.4.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: 40f09bd9d0341dd242cbd29f7eaa4c848d180886f4e11c76ca97fca5f312e8d9
4
- data.tar.gz: e2d8d22a90787f7824953c4d869ecc57e8eaebcd6948ed18a45033684dc45ce5
3
+ metadata.gz: 7f8e7cce25c596230a2d068e4f3aca0bfdc7d5156c9fb724e34f094e97d8909f
4
+ data.tar.gz: 21c66a2c19cf8e6d49017efd53dd53f7d1ae2654bac2b0df3e9f6b8d137e11e9
5
5
  SHA512:
6
- metadata.gz: 0bdc25b39ba3fdd08c70795f2db348c2155951af8a88d5acbca55eac6a36850ffaa4b9cc103e8a9774080aa798ba871792a7d9604f79ef94734164b7b9bbc9f3
7
- data.tar.gz: 54f528ac27f9031adbc794e4d31d7ba0d88f241dec379e063592b80a51a67cc0f3a9bb9af640a28d7d810de4686b17093ca79b3576ed48aa0198639f42fb1782
6
+ metadata.gz: 312c184a87c6d2b70e711c666b74f2a79a4c9d9afc29faf53776f46a906eab83e6ed2103d68e9f12e09cdb8b082c078f405769eeb13630adf998f9a498f82793
7
+ data.tar.gz: caeca3948e682aefb27f3de0617fba8d2558edb2c4a798ad732f16463a23a1bf586295918cb8a91cfddfef25b3b6b3df049a9ab84986b377f4da4f91080c9d67
data/CHANGELOG.md CHANGED
@@ -5,6 +5,66 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.4.0] - 2025-11-24
9
+
10
+ ### Changed
11
+
12
+ - **RTT Measurement** - Enhanced NATS round-trip time measurement with fallback support
13
+ - Added automatic unit normalization (seconds to milliseconds) for RTT values
14
+ - Implemented fallback RTT measurement using `flush` for NATS clients without native `rtt` method
15
+ - Supports both nats-pure and other NATS client implementations
16
+ - Better compatibility across different NATS client versions
17
+
18
+ - **Rails Integration** - Improved Rake task detection reliability
19
+ - Changed from `defined?(::Rake)` check to `$PROGRAM_NAME` inspection
20
+ - More reliable detection of Rake execution context
21
+ - Prevents false positives when Rake is loaded but not executing
22
+
23
+ ### Fixed
24
+
25
+ - **Test Coverage** - Comprehensive test suite improvements
26
+ - Added complete test coverage for Rails integration lifecycle methods
27
+ - Added tests for test helper matchers (`have_published`, `be_publish_success`, `be_publish_failure`)
28
+ - Added tests for fixture builders (`sample_event`, `sample_events`, `event`)
29
+ - Added test for RTT fallback behavior when client lacks `rtt` method
30
+ - Added spec file for `bridge_helpers` module
31
+
32
+ ## [4.3.0] - 2025-11-24
33
+
34
+ ### Added
35
+
36
+ - **Connection Diagnostics** - Exposed reconnection error tracking for health checks
37
+ - `last_reconnect_error` and `last_reconnect_error_at` now publicly accessible
38
+ - Enables better monitoring and diagnostics of connection issues
39
+ - Added test coverage for diagnostic accessor visibility
40
+
41
+ ### Changed
42
+
43
+ - **Connection Lifecycle** - Improved topology management during startup
44
+ - `startup!` now explicitly ensures topology is created during initialization
45
+ - `connect_and_ensure_stream!` properly ensures topology after connecting
46
+ - `fetch_stream_info` now ensures connection is established before querying
47
+ - More reliable initialization sequence for non-Rails applications
48
+
49
+ - **Rails Integration** - Changed console autostart behavior
50
+ - Rails console now autostarts JetStream Bridge by default (previously skipped)
51
+ - Simplified autostart logic by removing console detection as skip condition
52
+ - Autostart remains disabled only for rake tasks (unless forced with `JETSTREAM_BRIDGE_FORCE_AUTOSTART`)
53
+ - Better developer experience in Rails console for immediate testing
54
+
55
+ - **Documentation** - Clarified connection initialization behavior
56
+ - Added notes explaining that `configure` only sets options and does not connect
57
+ - Documented when connection actually occurs (Rails: after initialization; non-Rails: call `startup!`)
58
+ - Improved explanation of `lazy_connect` behavior in Rails environments
59
+ - Added guidance for non-Rails applications to call `startup!` explicitly
60
+
61
+ ### Fixed
62
+
63
+ - **Test Coverage** - Added missing test scenarios
64
+ - Added tests for topology ensuring in `startup!` and `connect_and_ensure_stream!`
65
+ - Added tests for connection initialization in `stream_info`
66
+ - Updated Rails integration specs to reflect new console behavior
67
+
8
68
  ## [4.2.0] - 2025-11-24
9
69
 
10
70
  ### Added
data/README.md CHANGED
@@ -54,6 +54,10 @@ JetstreamBridge.configure do |config|
54
54
  config.use_inbox = true
55
55
  config.use_dlq = true
56
56
  end
57
+
58
+ # Note: configure only sets options; it does not connect. In Rails the Railtie
59
+ # starts the bridge after initialization. In non-Rails apps call
60
+ # `JetstreamBridge.startup!` (or rely on auto-connect on first publish/subscribe).
57
61
  ```
58
62
 
59
63
  Publish:
@@ -52,9 +52,14 @@ JetstreamBridge.configure do |config|
52
52
  config.ack_wait = "30s"
53
53
  config.backoff = %w[1s 5s 15s 30s 60s]
54
54
  end
55
+
56
+ # Note: `configure` only sets options; it does not connect. Rails will start
57
+ # JetstreamBridge after initialization via the Railtie. For non-Rails or custom
58
+ # boot flows, call `JetstreamBridge.startup!` (or rely on auto-connect on first
59
+ # publish/subscribe).
55
60
  ```
56
61
 
57
- Rails autostart can be disabled for rake/console by `config.lazy_connect = true` or `JETSTREAM_BRIDGE_DISABLE_AUTOSTART=1`; it will connect on first publish/subscribe.
62
+ Rails autostart runs after initialization (including in console). You can opt out for rake tasks or other tooling with `config.lazy_connect = true` or `JETSTREAM_BRIDGE_DISABLE_AUTOSTART=1`; it will then connect on first publish/subscribe.
58
63
 
59
64
  ## Publish
60
65
 
@@ -37,7 +37,12 @@ module JetstreamBridge
37
37
  end
38
38
 
39
39
  def fetch_stream_info
40
+ # Ensure we have an active connection before querying stream info
41
+ connect_if_needed!
42
+
40
43
  jts = Connection.jetstream
44
+ raise ConnectionNotEstablishedError, 'NATS connection not established' unless jts
45
+
41
46
  info = jts.stream_info(config.stream_name)
42
47
 
43
48
  # Handle both object-style and hash-style access for compatibility
@@ -61,11 +66,20 @@ module JetstreamBridge
61
66
  end
62
67
 
63
68
  def measure_nats_rtt
64
- # Measure round-trip time using NATS RTT method
65
69
  nc = Connection.nc
66
- start = Time.now
67
- nc.rtt
68
- ((Time.now - start) * 1000).round(2)
70
+ return nil unless nc
71
+
72
+ # Prefer native RTT API when available (e.g., new NATS clients)
73
+ if nc.respond_to?(:rtt)
74
+ rtt_value = normalize_ms(nc.rtt)
75
+ return rtt_value if rtt_value
76
+ end
77
+
78
+ # Fallback for clients without #rtt (nats-pure): measure ping/pong via flush
79
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
80
+ nc.flush(1)
81
+ duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
82
+ normalize_ms(duration)
69
83
  rescue StandardError => e
70
84
  Logging.warn(
71
85
  "Failed to measure NATS RTT: #{e.class} #{e.message}",
@@ -74,6 +88,16 @@ module JetstreamBridge
74
88
  nil
75
89
  end
76
90
 
91
+ def normalize_ms(value)
92
+ return nil if value.nil?
93
+ return nil unless value.respond_to?(:to_f)
94
+
95
+ numeric = value.to_f
96
+ # Heuristic: sub-1 values are likely seconds; convert them to ms for reporting
97
+ ms = numeric < 1 ? numeric * 1000 : numeric
98
+ ms.round(2)
99
+ end
100
+
77
101
  def assign_config_option!(cfg, key, val)
78
102
  setter = :"#{key}="
79
103
  raise ArgumentError, "Unknown configuration option: #{key}" unless cfg.respond_to?(setter)
@@ -135,6 +135,9 @@ module JetstreamBridge
135
135
  # @return [Time, nil] timestamp when connection was established
136
136
  attr_reader :connected_at
137
137
 
138
+ # Last reconnection error metadata (exposed for health checks/diagnostics)
139
+ attr_reader :last_reconnect_error, :last_reconnect_error_at
140
+
138
141
  # Get current connection state
139
142
  #
140
143
  # @return [Symbol] Current connection state (see State module)
@@ -429,10 +432,6 @@ module JetstreamBridge
429
432
  @last_health_check = Time.now.to_i
430
433
  end
431
434
 
432
- # Get last reconnection error for diagnostics
433
- # @return [StandardError, nil] Last error during reconnection
434
- attr_reader :last_reconnect_error, :last_reconnect_error_at
435
-
436
435
  # Expose for class-level helpers (not part of public API)
437
436
  attr_reader :nc
438
437
 
@@ -71,13 +71,12 @@ module JetstreamBridge
71
71
 
72
72
  JetstreamBridge.config.lazy_connect ||
73
73
  env_disables_autostart? ||
74
- skip_autostart_for_rails_tooling?
74
+ rake_task?
75
75
  end
76
76
 
77
77
  def autostart_skip_reason
78
78
  return 'lazy_connect enabled' if JetstreamBridge.config.lazy_connect
79
79
  return 'JETSTREAM_BRIDGE_DISABLE_AUTOSTART set' if env_disables_autostart?
80
- return 'Rails console' if rails_console?
81
80
  return 'rake task' if rake_task?
82
81
 
83
82
  'unknown'
@@ -134,11 +133,7 @@ module JetstreamBridge
134
133
  end
135
134
 
136
135
  def rake_task?
137
- !!defined?(::Rake) || File.basename($PROGRAM_NAME) == 'rake'
138
- end
139
-
140
- def skip_autostart_for_rails_tooling?
141
- rails_console? || rake_task?
136
+ File.basename($PROGRAM_NAME) == 'rake'
142
137
  end
143
138
 
144
139
  def active_logger
@@ -4,5 +4,5 @@
4
4
  #
5
5
  # Version constant for the gem.
6
6
  module JetstreamBridge
7
- VERSION = '4.2.0'
7
+ VERSION = '4.4.0'
8
8
  end
@@ -133,14 +133,13 @@ module JetstreamBridge
133
133
 
134
134
  # Initialize the JetStream Bridge connection and topology
135
135
  #
136
- # This method is called automatically by `configure`, but can be called
137
- # explicitly if needed. It's idempotent and safe to call multiple times.
136
+ # This method can be called explicitly if needed. It's idempotent and safe to call multiple times.
138
137
  #
139
138
  # @return [void]
140
139
  def startup!
141
140
  return if @connection_initialized
142
141
 
143
- Connection.connect!
142
+ connect_and_ensure_stream!
144
143
  @connection_initialized = true
145
144
  Logging.info('JetStream Bridge started successfully', tag: 'JetstreamBridge')
146
145
  end
@@ -202,7 +201,9 @@ module JetstreamBridge
202
201
  # @return [Object] JetStream context
203
202
  def connect_and_ensure_stream!
204
203
  Connection.connect!
205
- Connection.jetstream
204
+ jts = Connection.jetstream
205
+ Topology.ensure!(jts)
206
+ jts
206
207
  end
207
208
 
208
209
  # Backwards-compatible alias for the previous method name
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jetstream_bridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Attara