nats_wave 1.1.4 → 1.1.5
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/generators/nats_wave/templates/initializer.rb +50 -58
- data/lib/nats_wave/adapters/datadog_metrics.rb +1 -1
- data/lib/nats_wave/client.rb +1 -1
- data/lib/nats_wave/configuration.rb +4 -3
- data/lib/nats_wave/publisher.rb +8 -16
- data/lib/nats_wave/railtie.rb +4 -3
- data/lib/nats_wave/subscriber.rb +31 -49
- data/lib/nats_wave/version.rb +1 -1
- data/lib/nats_wave.rb +2 -1
- metadata +2 -5
- data/examples/catalog_model.rb +0 -36
- data/examples/configuration_examples.rb +0 -68
- data/examples/user_model.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87bd7c130badc871675b1dee2a91bafc98c8d0f64c16fe114a6a4bb6b97387e3
|
4
|
+
data.tar.gz: 0e2ff399e1b408d64d832488f3a2c73316e58216ca4deda02282cde3de223134
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01400fba320e5d11427dc593f6f15730627137c84aa4b320ddcd1a6dda5bb33f0257c46d5fd64455f0c205c74321bcbc5190759722fb52e8f606c1bb28283800
|
7
|
+
data.tar.gz: 33795a3661cfd98b0c24e68f0c95164e4b79c838822c3f345e66c03b3702c867e40f39bba29d9515d65d0b3de4780d3e3561d0dd3fedc35d746a7b482b1c9e19
|
data/Gemfile.lock
CHANGED
@@ -1,64 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# Authentication (optional)
|
40
|
-
# config.middleware_authentication_enabled = true
|
41
|
-
# config.auth_secret_key = ENV['NATS_AUTH_SECRET']
|
2
|
+
|
3
|
+
begin
|
4
|
+
Rails.logger.info "Initializing NATS Wave with URL: #{ENV['NATS_URL']}"
|
5
|
+
|
6
|
+
NatsWave.configure do |config|
|
7
|
+
config.nats_url = ENV.fetch('NATS_URL', 'nats://localhost:4222')
|
8
|
+
config.service_name = ENV.fetch('NATS_SERVICE_NAME',
|
9
|
+
Rails.application.class.name.deconstantize.underscore)
|
10
|
+
config.connection_pool_size = 10
|
11
|
+
config.reconnect_attempts = 3
|
12
|
+
|
13
|
+
Rails.logger.info "NATS URL: #{config.nats_url}"
|
14
|
+
Rails.logger.info "Service Name: #{config.service_name}"
|
15
|
+
|
16
|
+
# Publishing
|
17
|
+
config.publishing_enabled = !Rails.env.test?
|
18
|
+
config.async_publishing = Rails.env.production?
|
19
|
+
config.default_subject_prefix = config.service_name
|
20
|
+
|
21
|
+
# Subscription
|
22
|
+
config.subscription_enabled = !Rails.env.test?
|
23
|
+
config.queue_group = "#{config.service_name}_consumers"
|
24
|
+
|
25
|
+
# Error Handling
|
26
|
+
config.max_retries = 3
|
27
|
+
config.retry_delay = 5
|
28
|
+
config.dead_letter_queue = "failed_messages"
|
29
|
+
|
30
|
+
# Authentication (optional)
|
31
|
+
# config.middleware_authentication_enabled = true
|
32
|
+
# config.auth_secret_key = ENV['NATS_AUTH_SECRET']
|
33
|
+
|
34
|
+
# Validation (optional)
|
35
|
+
# config.middleware_validation_enabled = true
|
36
|
+
# config.schema_registry_url = ENV['SCHEMA_REGISTRY_URL']
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
Rails.logger.info "NATS Wave configuration completed successfully"
|
40
|
+
rescue => e
|
41
|
+
Rails.logger.error "Failed to configure NATS Wave: #{e.message}"
|
42
|
+
Rails.logger.error e.backtrace.join("\n")
|
46
43
|
end
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
NatsWave.start_subscriber
|
58
|
-
Rails.logger.info 'NatsWave subscriber started automatically'
|
59
|
-
rescue StandardError => e
|
60
|
-
Rails.logger.error "Failed to start NatsWave subscriber: #{e.message}"
|
61
|
-
end
|
45
|
+
Rails.application.config.after_initialize do
|
46
|
+
Thread.new do
|
47
|
+
sleep 2 # Give Rails time to boot
|
48
|
+
begin
|
49
|
+
NatsWave.start_subscriber
|
50
|
+
Rails.logger.info "✅ NatsWave subscriber started successfully"
|
51
|
+
rescue StandardError => e
|
52
|
+
Rails.logger.error "Failed to start NatsWave subscriber: #{e.message}"
|
53
|
+
Rails.logger.error e.backtrace.join("\n")
|
62
54
|
end
|
63
55
|
end
|
64
|
-
end
|
56
|
+
end
|
data/lib/nats_wave/client.rb
CHANGED
@@ -16,9 +16,9 @@ module NatsWave
|
|
16
16
|
:subscriptions, :publications
|
17
17
|
|
18
18
|
def initialize(options = {})
|
19
|
-
@nats_url = ENV['NATS_URL']
|
20
|
-
@service_name = ENV['
|
21
|
-
@version = ENV['NATS_SERVICE_VERSION'] || "1.1.
|
19
|
+
@nats_url = ENV['NATS_URL'] || "nats://localhost:4222"
|
20
|
+
@service_name = ENV['NATS_SERVICE_NAME'] || "purplewave"
|
21
|
+
@version = ENV['NATS_SERVICE_VERSION'] || "1.1.5"
|
22
22
|
@instance_id = ENV['NATS_INSTANCE_ID'] || Socket.gethostname
|
23
23
|
@database_url = ENV['NATS_DATABASE_URL'] || nil
|
24
24
|
@connection_pool_size = (ENV['NATS_CONNECTION_POOL_SIZE'] || 10).to_i
|
@@ -80,6 +80,7 @@ module NatsWave
|
|
80
80
|
|
81
81
|
def nats_server_url
|
82
82
|
# This is the URL other teams can use to subscribe to your events
|
83
|
+
return nil if @nats_url.nil?
|
83
84
|
uri = URI.parse(@nats_url)
|
84
85
|
"#{uri.scheme}://#{uri.host}:#{uri.port}"
|
85
86
|
end
|
data/lib/nats_wave/publisher.rb
CHANGED
@@ -44,10 +44,9 @@ module NatsWave
|
|
44
44
|
class Publisher
|
45
45
|
attr_reader :config, :nats_client
|
46
46
|
|
47
|
-
def initialize(config, nats_client, middleware_stack)
|
47
|
+
def initialize(config, nats_client, middleware_stack = [])
|
48
48
|
@config = config
|
49
49
|
@nats_client = nats_client
|
50
|
-
@middleware_stack = middleware_stack
|
51
50
|
@message_transformer = MessageTransformer.new(config)
|
52
51
|
@dead_letter_queue = DeadLetterQueue.new(config) if config.dead_letter_queue
|
53
52
|
end
|
@@ -56,17 +55,15 @@ module NatsWave
|
|
56
55
|
return unless @config.publishing_enabled
|
57
56
|
|
58
57
|
message = build_message(subject, model, action, data, metadata)
|
59
|
-
processed_message = apply_middleware(message)
|
60
58
|
full_subject = build_full_subject(subject)
|
61
59
|
|
62
60
|
if @config.async_publishing && defined?(Concurrent)
|
63
|
-
publish_async(full_subject,
|
61
|
+
publish_async(full_subject, message)
|
64
62
|
else
|
65
|
-
publish_sync(full_subject,
|
63
|
+
publish_sync(full_subject, message)
|
66
64
|
end
|
67
65
|
|
68
|
-
Metrics.increment_published_messages(full_subject)
|
69
|
-
NatsWave.logger.debug("Published message to #{full_subject}")
|
66
|
+
# Metrics.increment_published_messages(full_subject)
|
70
67
|
rescue => e
|
71
68
|
NatsWave.logger.error("Failed to publish message: #{e.message}")
|
72
69
|
@dead_letter_queue&.store_failed_message(message, e, 0)
|
@@ -81,12 +78,11 @@ module NatsWave
|
|
81
78
|
source: build_source_info
|
82
79
|
}
|
83
80
|
|
84
|
-
processed_message = apply_middleware(batch_message)
|
85
81
|
subject = "#{@config.default_subject_prefix}.batch"
|
86
82
|
|
87
|
-
@nats_client.publish(subject,
|
83
|
+
@nats_client.publish(subject, batch_message.to_json)
|
88
84
|
|
89
|
-
Metrics.increment_published_messages(subject)
|
85
|
+
# Metrics.increment_published_messages(subject)
|
90
86
|
NatsWave.logger.info("Published batch with #{events.size} events")
|
91
87
|
end
|
92
88
|
|
@@ -128,20 +124,16 @@ module NatsWave
|
|
128
124
|
end
|
129
125
|
end
|
130
126
|
|
131
|
-
def apply_middleware(message)
|
132
|
-
@middleware_stack.reduce(message) do |msg, middleware|
|
133
|
-
middleware.call(msg)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
127
|
def publish_sync(subject, message)
|
138
128
|
@nats_client.publish(subject, message.to_json)
|
129
|
+
NatsWave.logger.debug("Published sync message to #{subject}")
|
139
130
|
end
|
140
131
|
|
141
132
|
def publish_async(subject, message)
|
142
133
|
if defined?(Concurrent)
|
143
134
|
Concurrent::Future.execute do
|
144
135
|
@nats_client.publish(subject, message.to_json)
|
136
|
+
NatsWave.logger.debug("Published async message to #{subject}")
|
145
137
|
end
|
146
138
|
else
|
147
139
|
publish_sync(subject, message)
|
data/lib/nats_wave/railtie.rb
CHANGED
@@ -20,7 +20,9 @@ module NatsWave
|
|
20
20
|
config_file = Rails.root.join('config', 'nats_wave.yml')
|
21
21
|
if File.exist?(config_file)
|
22
22
|
begin
|
23
|
-
|
23
|
+
erb_content = ERB.new(File.read(config_file)).result
|
24
|
+
yaml_data = YAML.safe_load(erb_content)
|
25
|
+
yaml_config = yaml_data&.dig(Rails.env.to_s) || yaml_data&.dig(Rails.env) || {}
|
24
26
|
|
25
27
|
NatsWave.configure do |config|
|
26
28
|
# NATS Configuration
|
@@ -95,11 +97,10 @@ module NatsWave
|
|
95
97
|
Rails.application.config.after_initialize do
|
96
98
|
if NatsWave.configuration&.publishing_enabled || NatsWave.configuration&.subscription_enabled
|
97
99
|
Thread.new do
|
98
|
-
sleep
|
100
|
+
sleep 2 # Give Rails time to fully boot
|
99
101
|
begin
|
100
102
|
NatsWave.client
|
101
103
|
NatsWave.logger.info "NatsWave client initialized"
|
102
|
-
NatsWave.logger.info "NATS URL #{@nats_url}"
|
103
104
|
rescue => e
|
104
105
|
NatsWave.logger.error "Failed to initialize NatsWave client: #{e.message}"
|
105
106
|
end
|
data/lib/nats_wave/subscriber.rb
CHANGED
@@ -4,15 +4,17 @@ module NatsWave
|
|
4
4
|
class Subscriber
|
5
5
|
attr_reader :config, :nats_client
|
6
6
|
|
7
|
-
def initialize(config, nats_client, middleware_stack)
|
7
|
+
def initialize(config, nats_client, middleware_stack = [])
|
8
8
|
@config = config
|
9
9
|
@nats_client = nats_client
|
10
|
-
@middleware_stack = middleware_stack
|
11
10
|
@database_connector = DatabaseConnector.new(config)
|
12
11
|
@model_mapper = ModelMapper.new(config)
|
13
12
|
@message_transformer = MessageTransformer.new(config)
|
14
13
|
@dead_letter_queue = DeadLetterQueue.new(config)
|
15
|
-
|
14
|
+
|
15
|
+
# Separate the two types of subscriptions
|
16
|
+
@registry_subscriptions = ModelRegistry.subscriptions # Hash objects
|
17
|
+
@nats_subscriptions = [] # NATS::Subscription objects
|
16
18
|
@running = false
|
17
19
|
end
|
18
20
|
|
@@ -23,26 +25,29 @@ module NatsWave
|
|
23
25
|
@running = true
|
24
26
|
NatsWave.logger.info "Starting NATS subscriber for #{@config.service_name}"
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
# Use ModelRegistry subscriptions
|
29
|
+
@registry_subscriptions.each do |subscription|
|
30
|
+
subscription[:subjects].each do |subject|
|
31
|
+
subscribe_to_subject(subject, subscription[:handler])
|
32
|
+
end
|
29
33
|
end
|
30
34
|
|
31
|
-
NatsWave.logger.info "
|
35
|
+
NatsWave.logger.info "Started #{@registry_subscriptions.size} subscriptions from ModelRegistry"
|
32
36
|
end
|
33
37
|
|
34
38
|
def subscribe(subjects:, model_mappings: {}, handler: nil)
|
35
39
|
subjects = Array(subjects)
|
36
40
|
|
37
41
|
subjects.each do |subject|
|
38
|
-
subscribe_to_subject(subject, handler,
|
39
|
-
|
42
|
+
subscribe_to_subject(subject, handler, model_mappings)
|
43
|
+
NatsWave.logger.info "Subscribed to #{subject}"
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
47
|
def unsubscribe_all
|
44
|
-
|
45
|
-
@
|
48
|
+
# Unsubscribe from NATS subscriptions (the actual NATS::Subscription objects)
|
49
|
+
@nats_subscriptions.each(&:unsubscribe)
|
50
|
+
@nats_subscriptions.clear
|
46
51
|
@running = false
|
47
52
|
end
|
48
53
|
|
@@ -57,33 +62,29 @@ module NatsWave
|
|
57
62
|
private
|
58
63
|
|
59
64
|
def subscribe_to_subject(subject_pattern, custom_handler = nil, model_mappings = {})
|
60
|
-
NatsWave.logger.info "
|
65
|
+
NatsWave.logger.info "🔍 Attempting to subscribe to: #{subject_pattern}"
|
61
66
|
|
62
|
-
|
67
|
+
# Create the NATS subscription
|
68
|
+
nats_subscription = @nats_client.subscribe(
|
63
69
|
subject_pattern,
|
64
70
|
queue: @config.queue_group
|
65
71
|
) do |msg|
|
66
|
-
|
67
|
-
|
72
|
+
NatsWave.logger.info "📨 Received message on #{msg.subject}: #{msg.data}"
|
73
|
+
process_message(msg.data, custom_handler, model_mappings)
|
68
74
|
end
|
69
75
|
|
70
|
-
|
76
|
+
# Add to NATS subscriptions array (not the registry subscriptions)
|
77
|
+
@nats_subscriptions << nats_subscription
|
78
|
+
NatsWave.logger.info "✅ Successfully subscribed to #{subject_pattern} (total: #{@nats_subscriptions.size})"
|
71
79
|
end
|
72
80
|
|
73
81
|
def process_message(raw_message, custom_handler, model_mappings)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
message
|
78
|
-
|
79
|
-
|
80
|
-
if custom_handler
|
81
|
-
custom_handler.call(processed_message)
|
82
|
-
else
|
83
|
-
handle_model_sync(
|
84
|
-
processed_message, model_mappings
|
85
|
-
)
|
86
|
-
end
|
82
|
+
message = parse_message(raw_message)
|
83
|
+
|
84
|
+
if custom_handler
|
85
|
+
custom_handler.call(message)
|
86
|
+
else
|
87
|
+
handle_model_sync(message, model_mappings)
|
87
88
|
end
|
88
89
|
|
89
90
|
NatsWave.logger.debug('Successfully processed message')
|
@@ -91,29 +92,10 @@ module NatsWave
|
|
91
92
|
handle_error(e, raw_message, message)
|
92
93
|
end
|
93
94
|
|
94
|
-
def should_process_message?(raw_message)
|
95
|
-
# Skip messages from same service instance
|
96
|
-
message = JSON.parse(raw_message)
|
97
|
-
source = message['source'] || {}
|
98
|
-
|
99
|
-
return false if source['service'] == @config.service_name &&
|
100
|
-
source['instance_id'] == @config.instance_id
|
101
|
-
|
102
|
-
true
|
103
|
-
rescue JSON::ParserError
|
104
|
-
false
|
105
|
-
end
|
106
|
-
|
107
95
|
def parse_message(raw_message)
|
108
96
|
@message_transformer.parse_message(raw_message)
|
109
97
|
end
|
110
98
|
|
111
|
-
def apply_middleware(message)
|
112
|
-
@middleware_stack.reduce(message) do |msg, middleware|
|
113
|
-
middleware.call(msg)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
99
|
def handle_model_sync(message, model_mappings)
|
118
100
|
source_model = message['model']
|
119
101
|
mapping = model_mappings[source_model] || @config.model_mappings[source_model]
|
@@ -158,4 +140,4 @@ module NatsWave
|
|
158
140
|
# Continue processing - don't raise to avoid breaking subscription
|
159
141
|
end
|
160
142
|
end
|
161
|
-
end
|
143
|
+
end
|
data/lib/nats_wave/version.rb
CHANGED
data/lib/nats_wave.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nats_wave
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeffrey Dabo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nats-pure
|
@@ -318,9 +318,6 @@ files:
|
|
318
318
|
- README.md
|
319
319
|
- Rakefile
|
320
320
|
- config/nats_wave.yml
|
321
|
-
- examples/catalog_model.rb
|
322
|
-
- examples/configuration_examples.rb
|
323
|
-
- examples/user_model.rb
|
324
321
|
- lib/generators/nats_wave/install_generator.rb
|
325
322
|
- lib/generators/nats_wave/templates/README
|
326
323
|
- lib/generators/nats_wave/templates/create_nats_wave_failed_messages.rb
|
data/examples/catalog_model.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Catalog < ApplicationRecord
|
4
|
-
include NatsWave::NatsPublishable
|
5
|
-
|
6
|
-
nats_publishable(
|
7
|
-
actions: %i[create update], # Don't publish deletes
|
8
|
-
skip_attributes: %i[view_count search_vector internal_notes],
|
9
|
-
include_associations: %i[category variants]
|
10
|
-
)
|
11
|
-
|
12
|
-
# Custom serializer support
|
13
|
-
def self.nats_wave_attribute_transformations
|
14
|
-
{
|
15
|
-
hammer_estimate: ->(value, _action) { value.to_f.round(2) },
|
16
|
-
name: :sanitize_name,
|
17
|
-
description: lambda { |value, _action|
|
18
|
-
ActionView::Base.full_sanitizer.sanitize(value)
|
19
|
-
}
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def sanitize_name(name, _action)
|
26
|
-
name&.strip&.titleize
|
27
|
-
end
|
28
|
-
|
29
|
-
def nats_wave_metadata
|
30
|
-
{
|
31
|
-
organization: organization&.name,
|
32
|
-
make:,
|
33
|
-
catalog_tracked: track_catalog?
|
34
|
-
}
|
35
|
-
end
|
36
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Basic configuration
|
4
|
-
NatsWave.configure do |config|
|
5
|
-
config.nats_url = 'nats://localhost:4222'
|
6
|
-
config.service_name = 'ecommerce_api'
|
7
|
-
config.default_subject_prefix = 'ecommerce.events'
|
8
|
-
end
|
9
|
-
|
10
|
-
# Advanced configuration with model mappings
|
11
|
-
NatsWave.configure do |config|
|
12
|
-
config.nats_url = ENV.fetch('NATS_URL', 'nats://localhost:4222')
|
13
|
-
config.service_name = 'catalog_service'
|
14
|
-
config.environment = Rails.env
|
15
|
-
|
16
|
-
# Subscribe to other team's events
|
17
|
-
config.add_subscription('warehouse.assets.*')
|
18
|
-
config.add_subscription('external.catalogs.*')
|
19
|
-
config.add_subscription('payments.transactions.*')
|
20
|
-
|
21
|
-
# Map external models to local models
|
22
|
-
config.add_model_mapping('WarehouseAsset', 'Catalog', {
|
23
|
-
'asset_name' => 'name',
|
24
|
-
'asset_description' => 'description',
|
25
|
-
'asset_value' => 'hammer_estimate',
|
26
|
-
'asset_id' => 'external_icn',
|
27
|
-
'model' => 'category'
|
28
|
-
})
|
29
|
-
|
30
|
-
config.add_model_mapping('ExternalCatalog', 'Catalog', {
|
31
|
-
'package_name' => 'name',
|
32
|
-
'package_cost' => 'hammer_estimate',
|
33
|
-
'external_vin' => 'vin'
|
34
|
-
})
|
35
|
-
|
36
|
-
# Custom transformation rules
|
37
|
-
config.transformation_rules = {
|
38
|
-
'hammer_estimate' => ->(value) { value.to_f.round(2) },
|
39
|
-
'name' => ->(value) { value&.titleize },
|
40
|
-
'email' => ->(value) { value&.downcase }
|
41
|
-
}
|
42
|
-
|
43
|
-
# Custom subscription with handler
|
44
|
-
config.add_subscription('payments.failed.*') do |message|
|
45
|
-
PaymentFailureHandler.process(message)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Middleware configuration
|
49
|
-
config.middleware_authentication_enabled = Rails.env.production?
|
50
|
-
config.auth_secret_key = ENV['NATS_AUTH_SECRET']
|
51
|
-
config.middleware_validation_enabled = true
|
52
|
-
config.middleware_logging_enabled = true
|
53
|
-
config.log_level = Rails.env.production? ? 'info' : 'debug'
|
54
|
-
end
|
55
|
-
|
56
|
-
# Catalogion configuration
|
57
|
-
if Rails.env.production?
|
58
|
-
NatsWave.configure do |config|
|
59
|
-
config.nats_url = ENV.fetch('NATS_CLUSTER_URL')
|
60
|
-
config.connection_pool_size = 20
|
61
|
-
config.async_publishing = true
|
62
|
-
config.middleware_authentication_enabled = true
|
63
|
-
config.auth_secret_key = ENV.fetch('NATS_AUTH_SECRET')
|
64
|
-
config.schema_registry_url = ENV['SCHEMA_REGISTRY_URL']
|
65
|
-
config.max_retries = 5
|
66
|
-
config.retry_delay = 10
|
67
|
-
end
|
68
|
-
end
|
data/examples/user_model.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class User < ApplicationRecord
|
4
|
-
include NatsWave::NatsPublishable
|
5
|
-
|
6
|
-
# Configure NATS publishing
|
7
|
-
nats_publishable(
|
8
|
-
actions: %i[create update destroy],
|
9
|
-
skip_attributes: %i[password_digest remember_token password_reset_token],
|
10
|
-
include_associations: %i[profile organization],
|
11
|
-
subject_prefix: 'users',
|
12
|
-
metadata: { tenant_id: 'main' },
|
13
|
-
if: -> { active? },
|
14
|
-
unless: -> { system_user? }
|
15
|
-
)
|
16
|
-
|
17
|
-
# Define unique attributes for syncing
|
18
|
-
def self.nats_wave_unique_attributes
|
19
|
-
%i[email external_icn username]
|
20
|
-
end
|
21
|
-
|
22
|
-
# Define attributes that shouldn't be synced from other instances
|
23
|
-
def self.nats_wave_skip_sync_attributes
|
24
|
-
%i[last_login_at login_count password_digest]
|
25
|
-
end
|
26
|
-
|
27
|
-
# Custom attribute transformations
|
28
|
-
def self.nats_wave_attribute_transformations
|
29
|
-
{
|
30
|
-
email: ->(value, _action) { value&.downcase&.strip },
|
31
|
-
phone: :format_phone_number
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# Custom metadata for NATS messages
|
38
|
-
def nats_wave_metadata
|
39
|
-
{
|
40
|
-
tenant_id: organization&.tenant_id,
|
41
|
-
user_type: account_type,
|
42
|
-
subscription_level: subscription&.level
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
def format_phone_number(phone, _action)
|
47
|
-
# Custom transformation logic
|
48
|
-
phone&.gsub(/\D/, '')
|
49
|
-
end
|
50
|
-
|
51
|
-
def active?
|
52
|
-
status == 'active'
|
53
|
-
end
|
54
|
-
|
55
|
-
def system_user?
|
56
|
-
email&.ends_with?('@system.internal')
|
57
|
-
end
|
58
|
-
end
|