Class: JetstreamBridge::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/jetstream_bridge/core/config.rb

Overview

Configuration object for JetStream Bridge.

Holds all configuration settings including NATS connection details, application identifiers, reliability features, and consumer tuning.

IMPORTANT: app_name should not include environment identifiers (e.g., use “api” not “api-production”) as consumer names are shared across environments for the same application.

Examples:

Basic configuration

JetstreamBridge.configure do |config|
  config.nats_urls = "nats://localhost:4222"
  config.app_name = "api_service"
  config.destination_app = "worker_service"
  config.stream_name = "jetstream-bridge-stream"
  config.use_outbox = true
  config.use_inbox = true
end

Using a preset

JetstreamBridge.configure_for(:production) do |config|
  config.nats_urls = ENV["NATS_URLS"]
  config.app_name = "api"
  config.destination_app = "worker"
  config.stream_name = "jetstream-bridge-stream"
end

Defined Under Namespace

Modules: Status

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfig

Initialize a new Config with sensible defaults.

Reads initial values from environment variables when available (NATS_URLS, NATS_URL, JETSTREAM_STREAM_NAME, APP_NAME, DESTINATION_APP).



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/jetstream_bridge/core/config.rb', line 128

def initialize
  @nats_urls       = ENV['NATS_URLS'] || ENV['NATS_URL'] || 'nats://localhost:4222'
  @stream_name     = ENV['JETSTREAM_STREAM_NAME'] || 'jetstream-bridge-stream'
  @app_name        = ENV['APP_NAME'] || 'app'
  @destination_app = ENV.fetch('DESTINATION_APP', nil)

  @max_deliver = 5
  @ack_wait    = '30s'
  @backoff     = %w[1s 5s 15s 30s 60s]

  @use_outbox   = false
  @use_inbox    = false
  @use_dlq      = true
  @outbox_model = 'JetstreamBridge::OutboxEvent'
  @inbox_model  = 'JetstreamBridge::InboxEvent'
  @logger       = nil
  @preset_applied = nil

  # Connection management
  @connect_retry_attempts = 3
  @connect_retry_delay = 2
  @lazy_connect = false
  @auto_provision = true

  # Consumer mode
  @consumer_mode = :pull
  @delivery_subject = nil
  @push_consumer_group = nil
end

Instance Attribute Details

#ack_waitString, Integer

Time to wait for acknowledgment before redelivery

Returns:

  • (String, Integer)


70
71
72
# File 'lib/jetstream_bridge/core/config.rb', line 70

def ack_wait
  @ack_wait
end

#app_nameString

Application name for subject routing and consumer naming. Should not include environment identifiers (e.g., use “api” not “api-production”).

Returns:

  • (String)


64
65
66
# File 'lib/jetstream_bridge/core/config.rb', line 64

def app_name
  @app_name
end

#auto_provisionBoolean

Allow JetStream Bridge to create/update streams/consumers and call JetStream management APIs. Disable for locked-down environments and handle provisioning separately.

Returns:

  • (Boolean)


107
108
109
# File 'lib/jetstream_bridge/core/config.rb', line 107

def auto_provision
  @auto_provision
end

#backoffArray<String>

Backoff delays between retries

Returns:

  • (Array<String>)


73
74
75
# File 'lib/jetstream_bridge/core/config.rb', line 73

def backoff
  @backoff
end

#connect_retry_attemptsInteger

Number of retry attempts for initial connection

Returns:

  • (Integer)


97
98
99
# File 'lib/jetstream_bridge/core/config.rb', line 97

def connect_retry_attempts
  @connect_retry_attempts
end

#connect_retry_delayInteger

Delay between connection retry attempts (in seconds)

Returns:

  • (Integer)


100
101
102
# File 'lib/jetstream_bridge/core/config.rb', line 100

def connect_retry_delay
  @connect_retry_delay
end

#consumer_modeSymbol

Consumer mode: :pull (default) or :push Pull consumers require publishing to JetStream API subjects ($JS.API.CONSUMER.MSG.NEXT.*) Push consumers receive messages automatically on a delivery subject

Returns:

  • (Symbol)


112
113
114
# File 'lib/jetstream_bridge/core/config.rb', line 112

def consumer_mode
  @consumer_mode
end

#delivery_subjectString?

Delivery subject for push consumers (optional, defaults to #destination_subject.worker) Only used when consumer_mode is :push

Returns:

  • (String, nil)


116
117
118
# File 'lib/jetstream_bridge/core/config.rb', line 116

def delivery_subject
  @delivery_subject
end

#destination_appString

Destination application name for subject routing

Returns:

  • (String)


54
55
56
# File 'lib/jetstream_bridge/core/config.rb', line 54

def destination_app
  @destination_app
end

#inbox_modelString

ActiveRecord model class name for inbox events

Returns:

  • (String)


82
83
84
# File 'lib/jetstream_bridge/core/config.rb', line 82

def inbox_model
  @inbox_model
end

#lazy_connectBoolean

Enable lazy connection (connect on first use instead of during configure)

Returns:

  • (Boolean)


103
104
105
# File 'lib/jetstream_bridge/core/config.rb', line 103

def lazy_connect
  @lazy_connect
end

#loggerLogger?

Logger instance

Returns:

  • (Logger, nil)


91
92
93
# File 'lib/jetstream_bridge/core/config.rb', line 91

def logger
  @logger
end

#max_deliverInteger

Maximum delivery attempts before moving to DLQ

Returns:

  • (Integer)


67
68
69
# File 'lib/jetstream_bridge/core/config.rb', line 67

def max_deliver
  @max_deliver
end

#nats_urlsString

NATS server URL(s), comma-separated for multiple servers

Returns:

  • (String)


57
58
59
# File 'lib/jetstream_bridge/core/config.rb', line 57

def nats_urls
  @nats_urls
end

#outbox_modelString

ActiveRecord model class name for outbox events

Returns:

  • (String)


85
86
87
# File 'lib/jetstream_bridge/core/config.rb', line 85

def outbox_model
  @outbox_model
end

#preset_appliedSymbol? (readonly)

Applied preset name

Returns:

  • (Symbol, nil)


94
95
96
# File 'lib/jetstream_bridge/core/config.rb', line 94

def preset_applied
  @preset_applied
end

#push_consumer_groupString?

Queue group / deliver_group for push consumers (optional, defaults to durable_name or app_name) Only used when consumer_mode is :push. Determines how push consumers load-balance.

Returns:

  • (String, nil)


120
121
122
# File 'lib/jetstream_bridge/core/config.rb', line 120

def push_consumer_group
  @push_consumer_group
end

#stream_nameString

JetStream stream name (required)

Returns:

  • (String)


60
61
62
# File 'lib/jetstream_bridge/core/config.rb', line 60

def stream_name
  @stream_name
end

#use_dlqBoolean

Enable dead letter queue

Returns:

  • (Boolean)


88
89
90
# File 'lib/jetstream_bridge/core/config.rb', line 88

def use_dlq
  @use_dlq
end

#use_inboxBoolean

Enable idempotent inbox pattern

Returns:

  • (Boolean)


79
80
81
# File 'lib/jetstream_bridge/core/config.rb', line 79

def use_inbox
  @use_inbox
end

#use_outboxBoolean

Enable transactional outbox pattern

Returns:

  • (Boolean)


76
77
78
# File 'lib/jetstream_bridge/core/config.rb', line 76

def use_outbox
  @use_outbox
end

Instance Method Details

#apply_preset(preset_name) ⇒ self

Apply a configuration preset

Parameters:

  • preset_name (Symbol, String)

    Name of preset (e.g., :production, :development)

Returns:

  • (self)


162
163
164
165
166
167
# File 'lib/jetstream_bridge/core/config.rb', line 162

def apply_preset(preset_name)
  require_relative 'config_preset'
  ConfigPreset.apply(self, preset_name)
  @preset_applied = preset_name.to_sym
  self
end

#destination_subjectString

Get the NATS subject this application subscribes to.

Returns:

  • (String)

    Destination subject for consuming

Raises:



192
193
194
195
196
# File 'lib/jetstream_bridge/core/config.rb', line 192

def destination_subject
  validate_subject_component!(app_name, 'app_name')
  validate_subject_component!(destination_app, 'destination_app')
  "#{destination_app}.sync.#{app_name}"
end

#dlq_subjectString

Get the dead letter queue subject for this application.

Each app has its own DLQ for better isolation and monitoring.

Returns:

  • (String)

    DLQ subject in format “#app_name.sync.dlq”

Raises:



205
206
207
208
# File 'lib/jetstream_bridge/core/config.rb', line 205

def dlq_subject
  validate_subject_component!(app_name, 'app_name')
  "#{app_name}.sync.dlq"
end

#durable_nameString

Get the durable consumer name for this application.

Returns the app_name with “-workers” suffix. Consumer names are shared across environments, so app_name should not include environment identifiers (e.g., use “myapp” not “myapp-production”).

Examples:

config.app_name = "notifications"
config.durable_name  # => "notifications-workers"

Returns:

  • (String)

    Durable consumer name



221
222
223
# File 'lib/jetstream_bridge/core/config.rb', line 221

def durable_name
  "#{app_name}-workers"
end

#pull_consumer?Boolean

Check if using pull consumer mode.

Returns:

  • (Boolean)


253
254
255
256
257
# File 'lib/jetstream_bridge/core/config.rb', line 253

def pull_consumer?
  consumer_mode.to_sym == :pull
rescue NoMethodError
  false
end

#push_consumer?Boolean

Check if using push consumer mode.

Returns:

  • (Boolean)


262
263
264
265
266
# File 'lib/jetstream_bridge/core/config.rb', line 262

def push_consumer?
  consumer_mode.to_sym == :push
rescue NoMethodError
  false
end

#push_consumer_group_nameString

Queue group for push consumers. Controls deliver_group and queue subscription.

Returns:

  • (String)

    Queue group name

Raises:



241
242
243
244
245
246
247
248
# File 'lib/jetstream_bridge/core/config.rb', line 241

def push_consumer_group_name
  group = push_consumer_group
  group = durable_name if group.to_s.strip.empty?
  group = app_name if group.to_s.strip.empty?

  validate_subject_component!(group, 'push_consumer_group')
  group
end

#push_delivery_subjectString

Get the delivery subject for push consumers.

Returns:

  • (String)

    Delivery subject for push consumers

Raises:



230
231
232
233
234
235
# File 'lib/jetstream_bridge/core/config.rb', line 230

def push_delivery_subject
  return delivery_subject if delivery_subject && !delivery_subject.empty?

  # Default: {destination_subject}.worker
  "#{destination_subject}.worker"
end

#source_subjectString

Get the NATS subject this application publishes to.

Producer publishes to: app.sync.dest Consumer subscribes to: dest.sync.app

Examples:

config.app_name = "api"
config.destination_app = "worker"
config.source_subject  # => "api.sync.worker"

Returns:

  • (String)

    Source subject for publishing

Raises:



181
182
183
184
185
# File 'lib/jetstream_bridge/core/config.rb', line 181

def source_subject
  validate_subject_component!(app_name, 'app_name')
  validate_subject_component!(destination_app, 'destination_app')
  "#{app_name}.sync.#{destination_app}"
end

#validate!true

Validate all configuration settings.

Checks that required settings are present and valid. Raises errors for any invalid configuration.

Examples:

config.validate!  # Raises if destination_app is missing

Returns:

  • (true)

    If configuration is valid

Raises:



277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/jetstream_bridge/core/config.rb', line 277

def validate!
  errors = []
  validate_required_fields!(errors)
  validate_numeric_constraints!(errors)
  validate_backoff!(errors)
  validate_consumer_mode!(errors)
  validate_push_consumer!(errors)

  raise ConfigurationError, "Configuration errors: #{errors.join(', ')}" if errors.any?

  true
end