nats_wave 1.1.13 → 1.1.15

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.
@@ -1,367 +1,3 @@
1
- # # # # frozen_string_literal: true
2
- # # #
3
- # # # module NatsWave
4
- # # # module Concerns
5
- # # # module Mappable
6
- # # # extend ActiveSupport::Concern
7
- # # #
8
- # # # included do
9
- # # # class_attribute :nats_wave_subscription_config, :nats_wave_publishing_config
10
- # # # self.nats_wave_subscription_config = {}
11
- # # # self.nats_wave_publishing_config = {}
12
- # # # end
13
- # # #
14
- # # # class_methods do
15
- # # # # Configure subscriptions with optional custom handler
16
- # # # def nats_wave_subscribes_to(*subjects, **options, &block)
17
- # # # Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
18
- # # #
19
- # # # handler = options[:handler] || block
20
- # # #
21
- # # # subscription_config = {
22
- # # # subjects: subjects.flatten,
23
- # # # field_mappings: options[:field_mappings] || {},
24
- # # # transformations: options[:transformations] || {},
25
- # # # skip_fields: options[:skip_fields] || [],
26
- # # # unique_fields: options[:unique_fields] || [:id],
27
- # # # sync_strategy: options[:sync_strategy] || :upsert,
28
- # # # handler: handler,
29
- # # # queue_group: options[:queue_group],
30
- # # # auto_sync: options[:auto_sync] != false # Default to true, can be disabled
31
- # # # }
32
- # # #
33
- # # # # Store the config
34
- # # # config_key = subjects.join(',')
35
- # # # self.nats_wave_subscription_config[config_key] = subscription_config
36
- # # #
37
- # # # # Create the subscription handler
38
- # # # processed_handler = create_subscription_handler(subscription_config)
39
- # # #
40
- # # # # Register the subscription
41
- # # # NatsWave::ModelRegistry.register_subscription(
42
- # # # subjects: subjects.flatten,
43
- # # # model: self.name,
44
- # # # handler: processed_handler,
45
- # # # queue_group: subscription_config[:queue_group]
46
- # # # )
47
- # # #
48
- # # # Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
49
- # # # end
50
- # # #
51
- # # # # Configure publishing with optional custom handler
52
- # # # def nats_wave_publishes_to(*subjects, **options, &block)
53
- # # # Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
54
- # # #
55
- # # # handler = options[:handler] || block
56
- # # #
57
- # # # publishing_config = {
58
- # # # subjects: subjects.flatten,
59
- # # # field_mappings: options[:field_mappings] || {},
60
- # # # transformations: options[:transformations] || {},
61
- # # # skip_fields: options[:skip_fields] || [],
62
- # # # conditions: options[:conditions] || {},
63
- # # # actions: options[:actions] || [:create, :update, :destroy],
64
- # # # handler: handler,
65
- # # # async: options[:async] != false, # Default to true
66
- # # # enabled: options[:enabled] != false # Default to true
67
- # # # }
68
- # # #
69
- # # # # Store the config
70
- # # # config_key = subjects.join(',')
71
- # # # self.nats_wave_publishing_config[config_key] = publishing_config
72
- # # #
73
- # # # Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
74
- # # # end
75
- # # #
76
- # # # # Get all subscription configurations
77
- # # # def nats_wave_subscription_configs
78
- # # # nats_wave_subscription_config
79
- # # # end
80
- # # #
81
- # # # # Get all publishing configurations
82
- # # # def nats_wave_publishing_configs
83
- # # # nats_wave_publishing_config
84
- # # # end
85
- # # #
86
- # # # # Get all subjects this model subscribes to
87
- # # # def nats_wave_subscribed_subjects
88
- # # # nats_wave_subscription_config.values.flat_map { |config| config[:subjects] }.uniq
89
- # # # end
90
- # # #
91
- # # # # Get all subjects this model publishes to
92
- # # # def nats_wave_published_subjects
93
- # # # nats_wave_publishing_config.values.flat_map { |config| config[:subjects] }.uniq
94
- # # # end
95
- # # #
96
- # # # private
97
- # # #
98
- # # # # Create a subscription handler that processes data and calls custom handler or auto-sync
99
- # # # def create_subscription_handler(config)
100
- # # # model_class = self
101
- # # #
102
- # # # lambda do |message|
103
- # # # begin
104
- # # # Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
105
- # # #
106
- # # # # Extract the raw data
107
- # # # raw_data = message['data'] || {}
108
- # # # model_name = message['model']
109
- # # # action = message['action']
110
- # # #
111
- # # # # Process the data through mappings and transformations
112
- # # # processed_data = model_class.process_data(raw_data, config)
113
- # # #
114
- # # # # If custom handler is provided, call it with model_name, action, processed_data
115
- # # # if config[:handler]
116
- # # # Rails.logger.debug "📨 Calling custom subscription handler" if defined?(Rails)
117
- # # # config[:handler].call(model_name, action, processed_data, message)
118
- # # # elsif config[:auto_sync]
119
- # # # Rails.logger.debug "📨 Performing auto-sync" if defined?(Rails)
120
- # # # # Default auto-sync behavior
121
- # # # model_class.perform_auto_sync(model_name, action, processed_data, config)
122
- # # # else
123
- # # # Rails.logger.debug "📨 No handler provided and auto_sync disabled" if defined?(Rails)
124
- # # # end
125
- # # #
126
- # # # rescue => e
127
- # # # Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
128
- # # # Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
129
- # # # raise
130
- # # # end
131
- # # # end
132
- # # # end
133
- # # #
134
- # # # # Process data through field mappings and transformations (used by both subscription and publishing)
135
- # # # def process_data(raw_data, config)
136
- # # # processed_data = {}
137
- # # # field_mappings = config[:field_mappings]
138
- # # # transformations = config[:transformations]
139
- # # # skip_fields = config[:skip_fields]
140
- # # #
141
- # # # raw_data.each do |field, value|
142
- # # # field_str = field.to_s
143
- # # # field_sym = field.to_sym
144
- # # #
145
- # # # # Skip if in skip_fields
146
- # # # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
147
- # # #
148
- # # # # Apply field mapping
149
- # # # mapped_field = field_mappings[field_str] ||
150
- # # # field_mappings[field_sym] ||
151
- # # # field
152
- # # #
153
- # # # # Apply transformation if any
154
- # # # transformed_value = apply_transformation(value, mapped_field, transformations, raw_data)
155
- # # #
156
- # # # processed_data[mapped_field.to_s] = transformed_value
157
- # # # end
158
- # # #
159
- # # # processed_data
160
- # # # end
161
- # # #
162
- # # # # Apply transformations to field values
163
- # # # def apply_transformation(value, field, transformations, full_record)
164
- # # # transformation = transformations[field] || transformations[field.to_sym]
165
- # # #
166
- # # # case transformation
167
- # # # when Proc
168
- # # # if transformation.arity == 2 || transformation.arity < 0
169
- # # # transformation.call(value, full_record)
170
- # # # else
171
- # # # transformation.call(value)
172
- # # # end
173
- # # # when Symbol
174
- # # # if self.respond_to?(transformation, true)
175
- # # # self.send(transformation, value)
176
- # # # elsif value.respond_to?(transformation)
177
- # # # value.send(transformation)
178
- # # # else
179
- # # # Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
180
- # # # value
181
- # # # end
182
- # # # else
183
- # # # value
184
- # # # end
185
- # # # end
186
- # # #
187
- # # # # Default auto-sync behavior
188
- # # # def perform_auto_sync(model_name, action, processed_data, config)
189
- # # # unique_fields = config[:unique_fields]
190
- # # # sync_strategy = config[:sync_strategy]
191
- # # #
192
- # # # case action.to_s.downcase
193
- # # # when 'create', 'created'
194
- # # # handle_auto_create(processed_data, unique_fields, sync_strategy)
195
- # # # when 'update', 'updated'
196
- # # # handle_auto_update(processed_data, unique_fields, sync_strategy)
197
- # # # when 'delete', 'deleted', 'destroy', 'destroyed'
198
- # # # handle_auto_delete(processed_data, unique_fields)
199
- # # # else
200
- # # # Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
201
- # # # end
202
- # # # end
203
- # # #
204
- # # # def handle_auto_create(data, unique_fields, sync_strategy)
205
- # # # case sync_strategy
206
- # # # when :upsert
207
- # # # existing = find_by_unique_fields(data, unique_fields)
208
- # # # if existing
209
- # # # existing.update!(data)
210
- # # # Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
211
- # # # else
212
- # # # record = self.create!(data)
213
- # # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
214
- # # # end
215
- # # # when :create_only
216
- # # # record = self.create!(data)
217
- # # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
218
- # # # end
219
- # # # rescue => e
220
- # # # Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
221
- # # # raise
222
- # # # end
223
- # # #
224
- # # # def handle_auto_update(data, unique_fields, sync_strategy)
225
- # # # existing = find_by_unique_fields(data, unique_fields)
226
- # # # if existing
227
- # # # existing.update!(data)
228
- # # # Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
229
- # # # elsif sync_strategy == :upsert
230
- # # # record = self.create!(data)
231
- # # # Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
232
- # # # else
233
- # # # Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
234
- # # # end
235
- # # # rescue => e
236
- # # # Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
237
- # # # raise
238
- # # # end
239
- # # #
240
- # # # def handle_auto_delete(data, unique_fields)
241
- # # # existing = find_by_unique_fields(data, unique_fields)
242
- # # # if existing
243
- # # # existing.destroy!
244
- # # # Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
245
- # # # else
246
- # # # Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
247
- # # # end
248
- # # # rescue => e
249
- # # # Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
250
- # # # raise
251
- # # # end
252
- # # #
253
- # # # def find_by_unique_fields(data, unique_fields)
254
- # # # conditions = {}
255
- # # # unique_fields.each do |field|
256
- # # # field_str = field.to_s
257
- # # # if data.key?(field_str)
258
- # # # conditions[field] = data[field_str]
259
- # # # elsif data.key?(field.to_sym)
260
- # # # conditions[field] = data[field.to_sym]
261
- # # # end
262
- # # # end
263
- # # #
264
- # # # return nil if conditions.empty?
265
- # # # self.find_by(conditions)
266
- # # # end
267
- # # # end
268
- # # #
269
- # # # # Instance methods for publishing
270
- # # # def nats_wave_publish(action = nil)
271
- # # # action ||= determine_action_from_context
272
- # # #
273
- # # # self.class.nats_wave_publishing_configs.each do |subjects_key, config|
274
- # # # next unless config[:enabled]
275
- # # # next unless config[:actions].include?(action.to_sym)
276
- # # #
277
- # # # # Check conditions (only for publishing)
278
- # # # if config[:conditions].any? && !evaluate_conditions(config[:conditions])
279
- # # # Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
280
- # # # next
281
- # # # end
282
- # # #
283
- # # # # Get the raw data (current model attributes)
284
- # # # raw_data = get_raw_attributes
285
- # # #
286
- # # # # Process the data through mappings and transformations (same as subscription)
287
- # # # processed_data = self.class.process_data(raw_data, config)
288
- # # #
289
- # # # # If custom handler is provided, call it
290
- # # # if config[:handler]
291
- # # # Rails.logger.debug "📤 Calling custom publishing handler" if defined?(Rails)
292
- # # # config[:handler].call(self.class.name, action, processed_data, self)
293
- # # # else
294
- # # # # Default publishing behavior - publish the processed data
295
- # # # config[:subjects].each do |subject|
296
- # # # NatsWave.client.publish(
297
- # # # subject: subject,
298
- # # # model: self.class.name,
299
- # # # action: action,
300
- # # # data: processed_data, # This is the processed data, not raw attributes
301
- # # # metadata: build_publishing_metadata
302
- # # # )
303
- # # #
304
- # # # Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
305
- # # # end
306
- # # # end
307
- # # # end
308
- # # # rescue StandardError => e
309
- # # # Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
310
- # # # # Don't re-raise to avoid breaking transactions
311
- # # # end
312
- # # #
313
- # # # private
314
- # # #
315
- # # # def determine_action_from_context
316
- # # # # Try to determine action from ActiveRecord context
317
- # # # if defined?(ActiveRecord) && is_a?(ActiveRecord::Base)
318
- # # # return 'create' if previously_new_record?
319
- # # # return 'update' if saved_changes.any?
320
- # # # return 'destroy' if destroyed?
321
- # # # end
322
- # # #
323
- # # # 'update' # Default fallback
324
- # # # end
325
- # # #
326
- # # # def get_raw_attributes
327
- # # # # Get attributes (works for both ActiveRecord and other objects)
328
- # # # if respond_to?(:attributes)
329
- # # # attributes
330
- # # # else
331
- # # # # For non-ActiveRecord objects, get instance variables
332
- # # # instance_variables.map { |v| [v.to_s.delete('@'), instance_variable_get(v)] }.to_h
333
- # # # end
334
- # # # end
335
- # # #
336
- # # # def evaluate_conditions(conditions)
337
- # # # conditions.all? do |condition, expected_value|
338
- # # # case condition
339
- # # # when Proc
340
- # # # condition.call(self)
341
- # # # when Symbol, String
342
- # # # if respond_to?(condition, true)
343
- # # # result = send(condition)
344
- # # # expected_value.nil? ? result : result == expected_value
345
- # # # else
346
- # # # false
347
- # # # end
348
- # # # else
349
- # # # false
350
- # # # end
351
- # # # end
352
- # # # end
353
- # # #
354
- # # # def build_publishing_metadata
355
- # # # {
356
- # # # source_model: self.class.name,
357
- # # # source_id: respond_to?(:id) ? id : object_id,
358
- # # # published_at: Time.current.iso8601
359
- # # # }
360
- # # # end
361
- # # # end
362
- # # # end
363
- # # # end
364
- # #
365
1
  # # # frozen_string_literal: true
366
2
  # #
367
3
  # # module NatsWave
@@ -378,9 +14,10 @@
378
14
  # # class_methods do
379
15
  # # # Configure subscriptions with optional custom handler
380
16
  # # def nats_wave_subscribes_to(*subjects, **options, &block)
381
- # # Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
17
+ # # NatsWave.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}"
382
18
  # #
383
- # # handler = options[:handler] || block
19
+ # # # Custom handler is now optional and runs AFTER default behavior
20
+ # # custom_handler = options[:handler] || block
384
21
  # #
385
22
  # # subscription_config = {
386
23
  # # subjects: subjects.flatten,
@@ -389,7 +26,7 @@
389
26
  # # skip_fields: options[:skip_fields] || [],
390
27
  # # unique_fields: options[:unique_fields] || [:id],
391
28
  # # sync_strategy: options[:sync_strategy] || :upsert,
392
- # # handler: handler,
29
+ # # custom_handler: custom_handler, # Renamed to be clear it's optional
393
30
  # # queue_group: options[:queue_group],
394
31
  # # auto_sync: options[:auto_sync] != false # Default to true, can be disabled
395
32
  # # }
@@ -409,14 +46,15 @@
409
46
  # # queue_group: subscription_config[:queue_group]
410
47
  # # )
411
48
  # #
412
- # # Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
49
+ # # NatsWave.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}"
413
50
  # # end
414
51
  # #
415
52
  # # # Configure publishing with optional custom handler AND auto-publishing callbacks
416
53
  # # def nats_wave_publishes_to(*subjects, **options, &block)
417
- # # Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
54
+ # # NatsWave.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}"
418
55
  # #
419
- # # handler = options[:handler] || block
56
+ # # # Custom handler is now optional and runs AFTER default behavior
57
+ # # custom_handler = options[:handler] || block
420
58
  # #
421
59
  # # publishing_config = {
422
60
  # # subjects: subjects.flatten,
@@ -425,19 +63,20 @@
425
63
  # # skip_fields: options[:skip_fields] || [],
426
64
  # # conditions: options[:conditions] || {},
427
65
  # # actions: options[:actions] || [:create, :update, :destroy],
428
- # # handler: handler,
66
+ # # custom_handler: custom_handler, # Renamed to be clear it's optional
429
67
  # # async: options[:async] != false, # Default to true
430
- # # enabled: options[:enabled] != false # Default to true
68
+ # # enabled: options[:enabled] != false, # Default to true
69
+ # # only_mapped_fields: options[:only_mapped_fields] != false, # Default to true
431
70
  # # }
432
71
  # #
433
72
  # # # Store the config
434
73
  # # config_key = subjects.join(',')
435
74
  # # self.nats_wave_publishing_config[config_key] = publishing_config
436
75
  # #
437
- # # # Add ActiveRecord callbacks for auto-publishing
438
- # # setup_publishing_callbacks(publishing_config)
76
+ # # # Add ActiveRecord callbacks for auto-publishing (only once per model)
77
+ # # setup_publishing_callbacks_once
439
78
  # #
440
- # # Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
79
+ # # NatsWave.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}"
441
80
  # # end
442
81
  # #
443
82
  # # # Get all subscription configurations
@@ -450,45 +89,29 @@
450
89
  # # nats_wave_publishing_config
451
90
  # # end
452
91
  # #
453
- # # # Get all subjects this model subscribes to
454
- # # def nats_wave_subscribed_subjects
455
- # # nats_wave_subscription_config.values.flat_map { |config| config[:subjects] }.uniq
456
- # # end
457
- # #
458
- # # # Get all subjects this model publishes to
459
- # # def nats_wave_published_subjects
460
- # # nats_wave_publishing_config.values.flat_map { |config| config[:subjects] }.uniq
461
- # # end
462
- # #
463
92
  # # private
464
93
  # #
465
- # # # Setup ActiveRecord callbacks for auto-publishing
466
- # # def setup_publishing_callbacks(config)
467
- # # # Only add callbacks if we're in ActiveRecord and actions are specified
94
+ # # # Setup ActiveRecord callbacks for auto-publishing (only once per model)
95
+ # # def setup_publishing_callbacks_once
96
+ # # # Only add callbacks if we're in ActiveRecord and haven't added them yet
468
97
  # # return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
98
+ # # return if @nats_wave_callbacks_added
469
99
  # #
470
- # # actions = config[:actions]
471
- # #
472
- # # if actions.include?(:create)
473
- # # after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
474
- # # end
475
- # #
476
- # # if actions.include?(:update)
477
- # # after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
478
- # # end
100
+ # # after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
101
+ # # after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
102
+ # # after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
479
103
  # #
480
- # # if actions.include?(:destroy)
481
- # # after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
482
- # # end
104
+ # # @nats_wave_callbacks_added = true
105
+ # # NatsWave.logger.debug "📤 #{self.name}: Added publishing callbacks"
483
106
  # # end
484
107
  # #
485
- # # # Create a subscription handler that processes data and calls custom handler or auto-sync
108
+ # # # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
486
109
  # # def create_subscription_handler(config)
487
110
  # # model_class = self
488
111
  # #
489
112
  # # lambda do |message|
490
113
  # # begin
491
- # # Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
114
+ # # NatsWave.logger.debug "📨 Processing subscription message for #{model_class.name}"
492
115
  # #
493
116
  # # # Extract the raw data
494
117
  # # raw_data = message['data'] || {}
@@ -496,29 +119,29 @@
496
119
  # # action = message['action']
497
120
  # #
498
121
  # # # Process the data through mappings and transformations
499
- # # processed_data = process_subscription_data(raw_data, config)
500
- # #
501
- # # # If custom handler is provided, call it with model_name, action, processed_data
502
- # # if config[:handler]
503
- # # Rails.logger.debug "📨 Calling custom subscription handler" if defined?(Rails)
504
- # # config[:handler].call(model_name, action, processed_data, message)
505
- # # elsif config[:auto_sync]
506
- # # Rails.logger.debug "📨 Performing auto-sync" if defined?(Rails)
507
- # # # Default auto-sync behavior
122
+ # # processed_data = model_class.process_subscription_data(raw_data, config)
123
+ # #
124
+ # # # Always perform auto-sync first (if enabled)
125
+ # # if config[:auto_sync]
126
+ # # NatsWave.logger.debug "📨 Performing auto-sync first"
508
127
  # # model_class.perform_auto_sync(model_name, action, processed_data, config)
509
- # # else
510
- # # Rails.logger.debug "📨 No handler provided and auto_sync disabled" if defined?(Rails)
128
+ # # end
129
+ # #
130
+ # # # Then call custom handler if provided (optional)
131
+ # # if config[:custom_handler]
132
+ # # NatsWave.logger.debug "📨 Calling custom subscription handler after auto-sync"
133
+ # # config[:custom_handler].call(model_name, action, processed_data, message)
511
134
  # # end
512
135
  # #
513
136
  # # rescue => e
514
- # # Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
515
- # # Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
137
+ # # NatsWave.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}"
138
+ # # NatsWave.logger.error e.backtrace.join("\n")
516
139
  # # raise
517
140
  # # end
518
141
  # # end
519
142
  # # end
520
143
  # #
521
- # # # Process subscription data through field mappings and transformations (CLASS METHOD)
144
+ # # # Process subscription data through field mappings and transformations (PUBLIC CLASS METHOD)
522
145
  # # def process_subscription_data(raw_data, config)
523
146
  # # processed_data = {}
524
147
  # # field_mappings = config[:field_mappings]
@@ -532,7 +155,7 @@
532
155
  # # # Skip if in skip_fields
533
156
  # # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
534
157
  # #
535
- # # # Apply field mapping
158
+ # # # Apply field mapping (external -> local)
536
159
  # # mapped_field = field_mappings[field_str] ||
537
160
  # # field_mappings[field_sym] ||
538
161
  # # field
@@ -546,7 +169,7 @@
546
169
  # # processed_data
547
170
  # # end
548
171
  # #
549
- # # # Apply transformations to field values (CLASS METHOD)
172
+ # # # Apply transformations to field values (PUBLIC CLASS METHOD)
550
173
  # # def apply_transformation(value, field, transformations, full_record)
551
174
  # # transformation = transformations[field] || transformations[field.to_sym]
552
175
  # #
@@ -563,7 +186,7 @@
563
186
  # # elsif value.respond_to?(transformation)
564
187
  # # value.send(transformation)
565
188
  # # else
566
- # # Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
189
+ # # NatsWave.logger.warn "Transformation method #{transformation} not found"
567
190
  # # value
568
191
  # # end
569
192
  # # else
@@ -571,7 +194,7 @@
571
194
  # # end
572
195
  # # end
573
196
  # #
574
- # # # Default auto-sync behavior (CLASS METHOD)
197
+ # # # Default auto-sync behavior (PUBLIC CLASS METHOD)
575
198
  # # def perform_auto_sync(model_name, action, processed_data, config)
576
199
  # # unique_fields = config[:unique_fields]
577
200
  # # sync_strategy = config[:sync_strategy]
@@ -584,7 +207,7 @@
584
207
  # # when 'delete', 'deleted', 'destroy', 'destroyed'
585
208
  # # handle_auto_delete(processed_data, unique_fields)
586
209
  # # else
587
- # # Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
210
+ # # NatsWave.logger.warn "Unknown action for auto-sync: #{action}"
588
211
  # # end
589
212
  # # end
590
213
  # #
@@ -594,17 +217,17 @@
594
217
  # # existing = find_by_unique_fields(data, unique_fields)
595
218
  # # if existing
596
219
  # # existing.update!(data)
597
- # # Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
220
+ # # NatsWave.logger.info "✅ Updated existing #{self.name}: #{existing.id}"
598
221
  # # else
599
222
  # # record = self.create!(data)
600
- # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
223
+ # # NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
601
224
  # # end
602
225
  # # when :create_only
603
226
  # # record = self.create!(data)
604
- # # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
227
+ # # NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
605
228
  # # end
606
229
  # # rescue => e
607
- # # Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
230
+ # # NatsWave.logger.error "❌ Failed to create #{self.name}: #{e.message}"
608
231
  # # raise
609
232
  # # end
610
233
  # #
@@ -612,15 +235,15 @@
612
235
  # # existing = find_by_unique_fields(data, unique_fields)
613
236
  # # if existing
614
237
  # # existing.update!(data)
615
- # # Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
238
+ # # NatsWave.logger.info "✅ Updated #{self.name}: #{existing.id}"
616
239
  # # elsif sync_strategy == :upsert
617
240
  # # record = self.create!(data)
618
- # # Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
241
+ # # NatsWave.logger.info "✅ Created new #{self.name} during update: #{record.id}"
619
242
  # # else
620
- # # Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
243
+ # # NatsWave.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}"
621
244
  # # end
622
245
  # # rescue => e
623
- # # Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
246
+ # # NatsWave.logger.error "❌ Failed to update #{self.name}: #{e.message}"
624
247
  # # raise
625
248
  # # end
626
249
  # #
@@ -628,12 +251,12 @@
628
251
  # # existing = find_by_unique_fields(data, unique_fields)
629
252
  # # if existing
630
253
  # # existing.destroy!
631
- # # Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
254
+ # # NatsWave.logger.info "✅ Deleted #{self.name}: #{existing.id}"
632
255
  # # else
633
- # # Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
256
+ # # NatsWave.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}"
634
257
  # # end
635
258
  # # rescue => e
636
- # # Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
259
+ # # NatsWave.logger.error "❌ Failed to delete #{self.name}: #{e.message}"
637
260
  # # raise
638
261
  # # end
639
262
  # #
@@ -663,7 +286,7 @@
663
286
  # #
664
287
  # # # Check conditions (only for publishing)
665
288
  # # if config[:conditions].any? && !evaluate_conditions(config[:conditions])
666
- # # Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
289
+ # # NatsWave.logger.debug "📤 Skipping publish - conditions not met"
667
290
  # # next
668
291
  # # end
669
292
  # #
@@ -673,44 +296,62 @@
673
296
  # # # Process the data through mappings and transformations
674
297
  # # processed_data = process_publishing_data(raw_data, config)
675
298
  # #
676
- # # # If custom handler is provided, call it
677
- # # if config[:handler]
678
- # # Rails.logger.debug "📤 Calling custom publishing handler" if defined?(Rails)
679
- # # config[:handler].call(self.class.name, action, processed_data, self)
680
- # # else
681
- # # # Default publishing behavior - publish the processed data
682
- # # config[:subjects].each do |subject|
683
- # # NatsWave.client.publish(
684
- # # subject: subject,
685
- # # model: self.class.name,
686
- # # action: action,
687
- # # data: processed_data, # This is the processed data, not raw attributes
688
- # # metadata: build_publishing_metadata
689
- # # )
690
- # #
691
- # # Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
692
- # # end
299
+ # # # Determine which subjects to publish to based on action
300
+ # # subjects_to_publish = determine_subjects_for_action(config[:subjects], action)
301
+ # #
302
+ # # # Always publish first (default behavior)
303
+ # # subjects_to_publish.each do |subject|
304
+ # # NatsWave.client.publish(
305
+ # # subject: subject,
306
+ # # model: self.class.name,
307
+ # # action: action,
308
+ # # data: processed_data, # This is the processed data, not raw attributes
309
+ # # metadata: build_publishing_metadata
310
+ # # )
311
+ # #
312
+ # # NatsWave.logger.info "📤 Published #{self.class.name} to #{subject}"
313
+ # # end
314
+ # #
315
+ # # # Then call custom handler if provided (optional)
316
+ # # if config[:custom_handler]
317
+ # # NatsWave.logger.debug "📤 Calling custom publishing handler after publishing"
318
+ # # config[:custom_handler].call(self.class.name, action, processed_data, self)
693
319
  # # end
694
320
  # # end
695
321
  # # rescue StandardError => e
696
- # # Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
322
+ # # NatsWave.logger.error("Failed to publish: #{e.message}")
697
323
  # # # Don't re-raise to avoid breaking transactions
698
324
  # # end
699
325
  # #
700
- # # # Auto-publishing callback methods
326
+ # # # Auto-publishing callback methods (only called once per action)
701
327
  # # def trigger_nats_wave_auto_publish_on_create
702
- # # Rails.logger.debug "🚀 Auto-publishing on create" if defined?(Rails)
328
+ # # return if @nats_wave_publishing_in_progress
329
+ # # @nats_wave_publishing_in_progress = true
330
+ # #
331
+ # # NatsWave.logger.debug "🚀 Auto-publishing on create"
703
332
  # # nats_wave_publish('create')
333
+ # #
334
+ # # @nats_wave_publishing_in_progress = false
704
335
  # # end
705
336
  # #
706
337
  # # def trigger_nats_wave_auto_publish_on_update
707
- # # Rails.logger.debug "🚀 Auto-publishing on update" if defined?(Rails)
338
+ # # return if @nats_wave_publishing_in_progress
339
+ # # @nats_wave_publishing_in_progress = true
340
+ # #
341
+ # # NatsWave.logger.debug "🚀 Auto-publishing on update"
708
342
  # # nats_wave_publish('update')
343
+ # #
344
+ # # @nats_wave_publishing_in_progress = false
709
345
  # # end
710
346
  # #
711
347
  # # def trigger_nats_wave_auto_publish_on_destroy
712
- # # Rails.logger.debug "🚀 Auto-publishing on destroy" if defined?(Rails)
348
+ # # return if @nats_wave_publishing_in_progress
349
+ # # @nats_wave_publishing_in_progress = true
350
+ # #
351
+ # # NatsWave.logger.debug "🚀 Auto-publishing on destroy"
713
352
  # # nats_wave_publish('destroy')
353
+ # #
354
+ # # @nats_wave_publishing_in_progress = false
714
355
  # # end
715
356
  # #
716
357
  # # private
@@ -736,31 +377,49 @@
736
377
  # # end
737
378
  # # end
738
379
  # #
739
- # # # Process publishing data through field mappings and transformations (INSTANCE METHOD)
740
380
  # # def process_publishing_data(raw_data, config)
741
381
  # # processed_data = {}
742
- # # field_mappings = config[:field_mappings]
743
- # # transformations = config[:transformations]
744
- # # skip_fields = config[:skip_fields]
382
+ # # field_mappings = config[:field_mappings] || {}
383
+ # # transformations = config[:transformations] || {}
384
+ # # skip_fields = config[:skip_fields] || []
385
+ # # only_mapped_fields = config[:only_mapped_fields]
745
386
  # #
746
- # # raw_data.each do |field, value|
747
- # # field_str = field.to_s
748
- # # field_sym = field.to_sym
387
+ # # # If only_mapped_fields is true, only process fields that have explicit mappings
388
+ # # if only_mapped_fields && field_mappings.any?
389
+ # # field_mappings.each do |local_field, external_field|
390
+ # # local_field_str = local_field.to_s
749
391
  # #
750
- # # # Skip if in skip_fields
751
- # # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
392
+ # # # Skip if this field is in skip_fields
393
+ # # next if skip_fields.include?(local_field_str) || skip_fields.include?(local_field.to_sym)
752
394
  # #
753
- # # # Apply field mapping (local -> external)
754
- # # mapped_field = field_mappings[field_str] ||
755
- # # field_mappings[field_sym] ||
756
- # # field
395
+ # # # Get the value from raw_data
396
+ # # value = raw_data[local_field_str] || raw_data[local_field.to_sym]
757
397
  # #
758
- # # # Apply transformation if any
759
- # # transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
398
+ # # # Apply transformation if any (use external field name for transformation lookup)
399
+ # # transformed_value = apply_publishing_transformation(value, external_field, transformations, raw_data)
760
400
  # #
761
- # # processed_data[mapped_field.to_s] = transformed_value
762
- # # end
401
+ # # processed_data[external_field.to_s] = transformed_value
402
+ # # end
403
+ # # else
404
+ # # # Original behavior - process all fields
405
+ # # raw_data.each do |field, value|
406
+ # # field_str = field.to_s
407
+ # # field_sym = field.to_sym
408
+ # #
409
+ # # # Skip if in skip_fields
410
+ # # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
763
411
  # #
412
+ # # # Apply field mapping (local -> external) - ONLY if mapping exists
413
+ # # mapped_field = field_mappings[field_str] ||
414
+ # # field_mappings[field_sym] ||
415
+ # # field # Use original field name if no mapping
416
+ # #
417
+ # # # Apply transformation if any
418
+ # # transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
419
+ # #
420
+ # # processed_data[mapped_field.to_s] = transformed_value
421
+ # # end
422
+ # # end
764
423
  # # processed_data
765
424
  # # end
766
425
  # #
@@ -780,7 +439,7 @@
780
439
  # # elsif value.respond_to?(transformation)
781
440
  # # value.send(transformation)
782
441
  # # else
783
- # # Rails.logger.warn "Publishing transformation method #{transformation} not found" if defined?(Rails)
442
+ # # NatsWave.logger.warn "Publishing transformation method #{transformation} not found"
784
443
  # # value
785
444
  # # end
786
445
  # # else
@@ -788,6 +447,20 @@
788
447
  # # end
789
448
  # # end
790
449
  # #
450
+ # # def determine_subjects_for_action(configured_subjects, action)
451
+ # # # If subjects contain placeholders like {action}, replace them
452
+ # # configured_subjects.map do |subject|
453
+ # # if subject.include?('{action}')
454
+ # # subject.gsub('{action}', action.to_s)
455
+ # # elsif subject.include?('*')
456
+ # # # Replace wildcard with specific action
457
+ # # subject.gsub('*', action.to_s)
458
+ # # else
459
+ # # subject
460
+ # # end
461
+ # # end
462
+ # # end
463
+ # #
791
464
  # # def evaluate_conditions(conditions)
792
465
  # # conditions.all? do |condition, expected_value|
793
466
  # # case condition
@@ -833,7 +506,7 @@
833
506
  # class_methods do
834
507
  # # Configure subscriptions with optional custom handler
835
508
  # def nats_wave_subscribes_to(*subjects, **options, &block)
836
- # Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
509
+ # NatsWave.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}"
837
510
  #
838
511
  # # Custom handler is now optional and runs AFTER default behavior
839
512
  # custom_handler = options[:handler] || block
@@ -865,12 +538,12 @@
865
538
  # queue_group: subscription_config[:queue_group]
866
539
  # )
867
540
  #
868
- # Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
541
+ # NatsWave.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}"
869
542
  # end
870
543
  #
871
544
  # # Configure publishing with optional custom handler AND auto-publishing callbacks
872
545
  # def nats_wave_publishes_to(*subjects, **options, &block)
873
- # Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
546
+ # NatsWave.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}"
874
547
  #
875
548
  # # Custom handler is now optional and runs AFTER default behavior
876
549
  # custom_handler = options[:handler] || block
@@ -885,7 +558,7 @@
885
558
  # custom_handler: custom_handler, # Renamed to be clear it's optional
886
559
  # async: options[:async] != false, # Default to true
887
560
  # enabled: options[:enabled] != false, # Default to true
888
- # only_mapped_fields: options[:only_mapped_fields] != false # Default to true - only send mapped fields
561
+ # only_mapped_fields: options[:only_mapped_fields] # Changed: don't default to true
889
562
  # }
890
563
  #
891
564
  # # Store the config
@@ -895,7 +568,7 @@
895
568
  # # Add ActiveRecord callbacks for auto-publishing (only once per model)
896
569
  # setup_publishing_callbacks_once
897
570
  #
898
- # Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
571
+ # NatsWave.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}"
899
572
  # end
900
573
  #
901
574
  # # Get all subscription configurations
@@ -908,59 +581,9 @@
908
581
  # nats_wave_publishing_config
909
582
  # end
910
583
  #
911
- # private
912
- #
913
- # # Setup ActiveRecord callbacks for auto-publishing (only once per model)
914
- # def setup_publishing_callbacks_once
915
- # # Only add callbacks if we're in ActiveRecord and haven't added them yet
916
- # return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
917
- # return if @nats_wave_callbacks_added
918
- #
919
- # after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
920
- # after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
921
- # after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
922
- #
923
- # @nats_wave_callbacks_added = true
924
- # Rails.logger.debug "📤 #{self.name}: Added publishing callbacks" if defined?(Rails)
925
- # end
926
- #
927
- # # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
928
- # def create_subscription_handler(config)
929
- # model_class = self
584
+ # # PUBLIC METHODS - These need to be accessible from lambda context
930
585
  #
931
- # lambda do |message|
932
- # begin
933
- # Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
934
- #
935
- # # Extract the raw data
936
- # raw_data = message['data'] || {}
937
- # model_name = message['model']
938
- # action = message['action']
939
- #
940
- # # Process the data through mappings and transformations
941
- # processed_data = process_subscription_data(raw_data, config)
942
- #
943
- # # Always perform auto-sync first (if enabled)
944
- # if config[:auto_sync]
945
- # Rails.logger.debug "📨 Performing auto-sync first" if defined?(Rails)
946
- # model_class.perform_auto_sync(model_name, action, processed_data, config)
947
- # end
948
- #
949
- # # Then call custom handler if provided (optional)
950
- # if config[:custom_handler]
951
- # Rails.logger.debug "📨 Calling custom subscription handler after auto-sync" if defined?(Rails)
952
- # config[:custom_handler].call(model_name, action, processed_data, message)
953
- # end
954
- #
955
- # rescue => e
956
- # Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
957
- # Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
958
- # raise
959
- # end
960
- # end
961
- # end
962
- #
963
- # # Process subscription data through field mappings and transformations (CLASS METHOD)
586
+ # # Process subscription data through field mappings and transformations
964
587
  # def process_subscription_data(raw_data, config)
965
588
  # processed_data = {}
966
589
  # field_mappings = config[:field_mappings]
@@ -974,7 +597,7 @@
974
597
  # # Skip if in skip_fields
975
598
  # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
976
599
  #
977
- # # Apply field mapping
600
+ # # Apply field mapping (external -> local)
978
601
  # mapped_field = field_mappings[field_str] ||
979
602
  # field_mappings[field_sym] ||
980
603
  # field
@@ -988,7 +611,7 @@
988
611
  # processed_data
989
612
  # end
990
613
  #
991
- # # Apply transformations to field values (CLASS METHOD)
614
+ # # Apply transformations to field values
992
615
  # def apply_transformation(value, field, transformations, full_record)
993
616
  # transformation = transformations[field] || transformations[field.to_sym]
994
617
  #
@@ -1005,7 +628,7 @@
1005
628
  # elsif value.respond_to?(transformation)
1006
629
  # value.send(transformation)
1007
630
  # else
1008
- # Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
631
+ # NatsWave.logger.warn "Transformation method #{transformation} not found"
1009
632
  # value
1010
633
  # end
1011
634
  # else
@@ -1013,7 +636,7 @@
1013
636
  # end
1014
637
  # end
1015
638
  #
1016
- # # Default auto-sync behavior (CLASS METHOD)
639
+ # # Default auto-sync behavior
1017
640
  # def perform_auto_sync(model_name, action, processed_data, config)
1018
641
  # unique_fields = config[:unique_fields]
1019
642
  # sync_strategy = config[:sync_strategy]
@@ -1026,7 +649,7 @@
1026
649
  # when 'delete', 'deleted', 'destroy', 'destroyed'
1027
650
  # handle_auto_delete(processed_data, unique_fields)
1028
651
  # else
1029
- # Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
652
+ # NatsWave.logger.warn "Unknown action for auto-sync: #{action}"
1030
653
  # end
1031
654
  # end
1032
655
  #
@@ -1036,17 +659,17 @@
1036
659
  # existing = find_by_unique_fields(data, unique_fields)
1037
660
  # if existing
1038
661
  # existing.update!(data)
1039
- # Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
662
+ # NatsWave.logger.info "✅ Updated existing #{self.name}: #{existing.id}"
1040
663
  # else
1041
664
  # record = self.create!(data)
1042
- # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
665
+ # NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1043
666
  # end
1044
667
  # when :create_only
1045
668
  # record = self.create!(data)
1046
- # Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
669
+ # NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1047
670
  # end
1048
671
  # rescue => e
1049
- # Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
672
+ # NatsWave.logger.error "❌ Failed to create #{self.name}: #{e.message}"
1050
673
  # raise
1051
674
  # end
1052
675
  #
@@ -1054,15 +677,15 @@
1054
677
  # existing = find_by_unique_fields(data, unique_fields)
1055
678
  # if existing
1056
679
  # existing.update!(data)
1057
- # Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
680
+ # NatsWave.logger.info "✅ Updated #{self.name}: #{existing.id}"
1058
681
  # elsif sync_strategy == :upsert
1059
682
  # record = self.create!(data)
1060
- # Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
683
+ # NatsWave.logger.info "✅ Created new #{self.name} during update: #{record.id}"
1061
684
  # else
1062
- # Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
685
+ # NatsWave.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}"
1063
686
  # end
1064
687
  # rescue => e
1065
- # Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
688
+ # NatsWave.logger.error "❌ Failed to update #{self.name}: #{e.message}"
1066
689
  # raise
1067
690
  # end
1068
691
  #
@@ -1070,12 +693,12 @@
1070
693
  # existing = find_by_unique_fields(data, unique_fields)
1071
694
  # if existing
1072
695
  # existing.destroy!
1073
- # Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
696
+ # NatsWave.logger.info "✅ Deleted #{self.name}: #{existing.id}"
1074
697
  # else
1075
- # Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
698
+ # NatsWave.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}"
1076
699
  # end
1077
700
  # rescue => e
1078
- # Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
701
+ # NatsWave.logger.error "❌ Failed to delete #{self.name}: #{e.message}"
1079
702
  # raise
1080
703
  # end
1081
704
  #
@@ -1093,6 +716,58 @@
1093
716
  # return nil if conditions.empty?
1094
717
  # self.find_by(conditions)
1095
718
  # end
719
+ #
720
+ # private
721
+ #
722
+ # # Setup ActiveRecord callbacks for auto-publishing (only once per model)
723
+ # def setup_publishing_callbacks_once
724
+ # # Only add callbacks if we're in ActiveRecord and haven't added them yet
725
+ # return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
726
+ # return if @nats_wave_callbacks_added
727
+ #
728
+ # after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
729
+ # after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
730
+ # after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
731
+ #
732
+ # @nats_wave_callbacks_added = true
733
+ # NatsWave.logger.debug "📤 #{self.name}: Added publishing callbacks"
734
+ # end
735
+ #
736
+ # # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
737
+ # def create_subscription_handler(config)
738
+ # model_class = self
739
+ #
740
+ # lambda do |message|
741
+ # begin
742
+ # NatsWave.logger.debug "📨 Processing subscription message for #{model_class.name}"
743
+ #
744
+ # # Extract the raw data
745
+ # raw_data = message['data'] || {}
746
+ # model_name = message['model']
747
+ # action = message['action']
748
+ #
749
+ # # Process the data through mappings and transformations
750
+ # processed_data = model_class.process_subscription_data(raw_data, config)
751
+ #
752
+ # # Always perform auto-sync first (if enabled)
753
+ # if config[:auto_sync]
754
+ # NatsWave.logger.debug "📨 Performing auto-sync first"
755
+ # model_class.perform_auto_sync(model_name, action, processed_data, config)
756
+ # end
757
+ #
758
+ # # Then call custom handler if provided (optional)
759
+ # if config[:custom_handler]
760
+ # NatsWave.logger.debug "📨 Calling custom subscription handler after auto-sync"
761
+ # config[:custom_handler].call(model_name, action, processed_data, message)
762
+ # end
763
+ #
764
+ # rescue => e
765
+ # NatsWave.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}"
766
+ # NatsWave.logger.error e.backtrace.join("\n")
767
+ # raise
768
+ # end
769
+ # end
770
+ # end
1096
771
  # end
1097
772
  #
1098
773
  # # Instance methods for publishing
@@ -1105,7 +780,7 @@
1105
780
  #
1106
781
  # # Check conditions (only for publishing)
1107
782
  # if config[:conditions].any? && !evaluate_conditions(config[:conditions])
1108
- # Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
783
+ # NatsWave.logger.debug "📤 Skipping publish - conditions not met"
1109
784
  # next
1110
785
  # end
1111
786
  #
@@ -1128,17 +803,17 @@
1128
803
  # metadata: build_publishing_metadata
1129
804
  # )
1130
805
  #
1131
- # Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
806
+ # NatsWave.logger.info "📤 Published #{self.class.name} to #{subject}"
1132
807
  # end
1133
808
  #
1134
809
  # # Then call custom handler if provided (optional)
1135
810
  # if config[:custom_handler]
1136
- # Rails.logger.debug "📤 Calling custom publishing handler after publishing" if defined?(Rails)
811
+ # NatsWave.logger.debug "📤 Calling custom publishing handler after publishing"
1137
812
  # config[:custom_handler].call(self.class.name, action, processed_data, self)
1138
813
  # end
1139
814
  # end
1140
815
  # rescue StandardError => e
1141
- # Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
816
+ # NatsWave.logger.error("Failed to publish: #{e.message}")
1142
817
  # # Don't re-raise to avoid breaking transactions
1143
818
  # end
1144
819
  #
@@ -1147,7 +822,7 @@
1147
822
  # return if @nats_wave_publishing_in_progress
1148
823
  # @nats_wave_publishing_in_progress = true
1149
824
  #
1150
- # Rails.logger.debug "🚀 Auto-publishing on create" if defined?(Rails)
825
+ # NatsWave.logger.debug "🚀 Auto-publishing on create"
1151
826
  # nats_wave_publish('create')
1152
827
  #
1153
828
  # @nats_wave_publishing_in_progress = false
@@ -1157,7 +832,7 @@
1157
832
  # return if @nats_wave_publishing_in_progress
1158
833
  # @nats_wave_publishing_in_progress = true
1159
834
  #
1160
- # Rails.logger.debug "🚀 Auto-publishing on update" if defined?(Rails)
835
+ # NatsWave.logger.debug "🚀 Auto-publishing on update"
1161
836
  # nats_wave_publish('update')
1162
837
  #
1163
838
  # @nats_wave_publishing_in_progress = false
@@ -1167,7 +842,7 @@
1167
842
  # return if @nats_wave_publishing_in_progress
1168
843
  # @nats_wave_publishing_in_progress = true
1169
844
  #
1170
- # Rails.logger.debug "🚀 Auto-publishing on destroy" if defined?(Rails)
845
+ # NatsWave.logger.debug "🚀 Auto-publishing on destroy"
1171
846
  # nats_wave_publish('destroy')
1172
847
  #
1173
848
  # @nats_wave_publishing_in_progress = false
@@ -1196,45 +871,49 @@
1196
871
  # end
1197
872
  # end
1198
873
  #
1199
- # # Process publishing data through field mappings and transformations (INSTANCE METHOD)
1200
874
  # def process_publishing_data(raw_data, config)
1201
875
  # processed_data = {}
1202
- # field_mappings = config[:field_mappings]
1203
- # transformations = config[:transformations]
1204
- # skip_fields = config[:skip_fields]
876
+ # field_mappings = config[:field_mappings] || {}
877
+ # transformations = config[:transformations] || {}
878
+ # skip_fields = config[:skip_fields] || []
1205
879
  # only_mapped_fields = config[:only_mapped_fields]
1206
880
  #
1207
- # # If only_mapped_fields is true, only process fields that have mappings or transformations
1208
- # fields_to_process = if only_mapped_fields && field_mappings.any?
1209
- # # Only process fields that are explicitly mapped or have transformations
1210
- # mapped_source_fields = field_mappings.keys.map(&:to_s)
1211
- # transformation_fields = transformations.keys.map(&:to_s)
1212
- # all_relevant_fields = (mapped_source_fields + transformation_fields).uniq
881
+ # # If only_mapped_fields is true, only process fields that have explicit mappings
882
+ # if only_mapped_fields && field_mappings.any?
883
+ # field_mappings.each do |local_field, external_field|
884
+ # local_field_str = local_field.to_s
1213
885
  #
1214
- # raw_data.select { |field, _| all_relevant_fields.include?(field.to_s) }
1215
- # else
1216
- # # Process all fields (existing behavior)
1217
- # raw_data
1218
- # end
886
+ # # Skip if this field is in skip_fields
887
+ # next if skip_fields.include?(local_field_str) || skip_fields.include?(local_field.to_sym)
1219
888
  #
1220
- # fields_to_process.each do |field, value|
1221
- # field_str = field.to_s
1222
- # field_sym = field.to_sym
889
+ # # Get the value from raw_data
890
+ # value = raw_data[local_field_str] || raw_data[local_field.to_sym]
1223
891
  #
1224
- # # Skip if in skip_fields
1225
- # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
892
+ # # Apply transformation if any (use external field name for transformation lookup)
893
+ # transformed_value = apply_publishing_transformation(value, external_field, transformations, raw_data)
1226
894
  #
1227
- # # Apply field mapping (local -> external)
1228
- # mapped_field = field_mappings[field_str] ||
1229
- # field_mappings[field_sym] ||
1230
- # field
895
+ # processed_data[external_field.to_s] = transformed_value
896
+ # end
897
+ # else
898
+ # # Original behavior - process all fields
899
+ # raw_data.each do |field, value|
900
+ # field_str = field.to_s
901
+ # field_sym = field.to_sym
1231
902
  #
1232
- # # Apply transformation if any
1233
- # transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
903
+ # # Skip if in skip_fields
904
+ # next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
1234
905
  #
1235
- # processed_data[mapped_field.to_s] = transformed_value
1236
- # end
906
+ # # Apply field mapping (local -> external) - ONLY if mapping exists
907
+ # mapped_field = field_mappings[field_str] ||
908
+ # field_mappings[field_sym] ||
909
+ # field # Use original field name if no mapping
910
+ #
911
+ # # Apply transformation if any
912
+ # transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
1237
913
  #
914
+ # processed_data[mapped_field.to_s] = transformed_value
915
+ # end
916
+ # end
1238
917
  # processed_data
1239
918
  # end
1240
919
  #
@@ -1254,7 +933,7 @@
1254
933
  # elsif value.respond_to?(transformation)
1255
934
  # value.send(transformation)
1256
935
  # else
1257
- # Rails.logger.warn "Publishing transformation method #{transformation} not found" if defined?(Rails)
936
+ # NatsWave.logger.warn "Publishing transformation method #{transformation} not found"
1258
937
  # value
1259
938
  # end
1260
939
  # else
@@ -1304,6 +983,7 @@
1304
983
  # end
1305
984
  # end
1306
985
  # end
986
+
1307
987
  # frozen_string_literal: true
1308
988
 
1309
989
  module NatsWave
@@ -1320,7 +1000,7 @@ module NatsWave
1320
1000
  class_methods do
1321
1001
  # Configure subscriptions with optional custom handler
1322
1002
  def nats_wave_subscribes_to(*subjects, **options, &block)
1323
- Rails.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}" if defined?(Rails)
1003
+ NatsWave.logger.debug "📡 #{self.name}: Setting up subscription to subjects: #{subjects.inspect}"
1324
1004
 
1325
1005
  # Custom handler is now optional and runs AFTER default behavior
1326
1006
  custom_handler = options[:handler] || block
@@ -1352,12 +1032,12 @@ module NatsWave
1352
1032
  queue_group: subscription_config[:queue_group]
1353
1033
  )
1354
1034
 
1355
- Rails.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}" if defined?(Rails)
1035
+ NatsWave.logger.debug "📡 #{self.name}: Registered subscription for subjects: #{subjects}"
1356
1036
  end
1357
1037
 
1358
1038
  # Configure publishing with optional custom handler AND auto-publishing callbacks
1359
1039
  def nats_wave_publishes_to(*subjects, **options, &block)
1360
- Rails.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}" if defined?(Rails)
1040
+ NatsWave.logger.debug "📤 #{self.name}: Setting up publishing to subjects: #{subjects.inspect}"
1361
1041
 
1362
1042
  # Custom handler is now optional and runs AFTER default behavior
1363
1043
  custom_handler = options[:handler] || block
@@ -1371,7 +1051,8 @@ module NatsWave
1371
1051
  actions: options[:actions] || [:create, :update, :destroy],
1372
1052
  custom_handler: custom_handler, # Renamed to be clear it's optional
1373
1053
  async: options[:async] != false, # Default to true
1374
- enabled: options[:enabled] != false # Default to true
1054
+ enabled: options[:enabled] != false, # Default to true
1055
+ only_mapped_fields: options[:only_mapped_fields] != false, # Default to true
1375
1056
  }
1376
1057
 
1377
1058
  # Store the config
@@ -1381,7 +1062,7 @@ module NatsWave
1381
1062
  # Add ActiveRecord callbacks for auto-publishing (only once per model)
1382
1063
  setup_publishing_callbacks_once
1383
1064
 
1384
- Rails.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}" if defined?(Rails)
1065
+ NatsWave.logger.debug "📤 #{self.name}: Registered publishing config for subjects: #{subjects}"
1385
1066
  end
1386
1067
 
1387
1068
  # Get all subscription configurations
@@ -1394,58 +1075,6 @@ module NatsWave
1394
1075
  nats_wave_publishing_config
1395
1076
  end
1396
1077
 
1397
- private
1398
-
1399
- # Setup ActiveRecord callbacks for auto-publishing (only once per model)
1400
- def setup_publishing_callbacks_once
1401
- # Only add callbacks if we're in ActiveRecord and haven't added them yet
1402
- return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
1403
- return if @nats_wave_callbacks_added
1404
-
1405
- after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
1406
- after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
1407
- after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
1408
-
1409
- @nats_wave_callbacks_added = true
1410
- Rails.logger.debug "📤 #{self.name}: Added publishing callbacks" if defined?(Rails)
1411
- end
1412
-
1413
- # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
1414
- def create_subscription_handler(config)
1415
- model_class = self
1416
-
1417
- lambda do |message|
1418
- begin
1419
- Rails.logger.debug "📨 Processing subscription message for #{model_class.name}" if defined?(Rails)
1420
-
1421
- # Extract the raw data
1422
- raw_data = message['data'] || {}
1423
- model_name = message['model']
1424
- action = message['action']
1425
-
1426
- # Process the data through mappings and transformations
1427
- processed_data = model_class.process_subscription_data(raw_data, config)
1428
-
1429
- # Always perform auto-sync first (if enabled)
1430
- if config[:auto_sync]
1431
- Rails.logger.debug "📨 Performing auto-sync first" if defined?(Rails)
1432
- model_class.perform_auto_sync(model_name, action, processed_data, config)
1433
- end
1434
-
1435
- # Then call custom handler if provided (optional)
1436
- if config[:custom_handler]
1437
- Rails.logger.debug "📨 Calling custom subscription handler after auto-sync" if defined?(Rails)
1438
- config[:custom_handler].call(model_name, action, processed_data, message)
1439
- end
1440
-
1441
- rescue => e
1442
- Rails.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}" if defined?(Rails)
1443
- Rails.logger.error e.backtrace.join("\n") if defined?(Rails)
1444
- raise
1445
- end
1446
- end
1447
- end
1448
-
1449
1078
  # Process subscription data through field mappings and transformations (PUBLIC CLASS METHOD)
1450
1079
  def process_subscription_data(raw_data, config)
1451
1080
  processed_data = {}
@@ -1491,7 +1120,7 @@ module NatsWave
1491
1120
  elsif value.respond_to?(transformation)
1492
1121
  value.send(transformation)
1493
1122
  else
1494
- Rails.logger.warn "Transformation method #{transformation} not found" if defined?(Rails)
1123
+ NatsWave.logger.warn "Transformation method #{transformation} not found"
1495
1124
  value
1496
1125
  end
1497
1126
  else
@@ -1512,7 +1141,7 @@ module NatsWave
1512
1141
  when 'delete', 'deleted', 'destroy', 'destroyed'
1513
1142
  handle_auto_delete(processed_data, unique_fields)
1514
1143
  else
1515
- Rails.logger.warn "Unknown action for auto-sync: #{action}" if defined?(Rails)
1144
+ NatsWave.logger.warn "Unknown action for auto-sync: #{action}"
1516
1145
  end
1517
1146
  end
1518
1147
 
@@ -1522,17 +1151,17 @@ module NatsWave
1522
1151
  existing = find_by_unique_fields(data, unique_fields)
1523
1152
  if existing
1524
1153
  existing.update!(data)
1525
- Rails.logger.info "✅ Updated existing #{self.name}: #{existing.id}" if defined?(Rails)
1154
+ NatsWave.logger.info "✅ Updated existing #{self.name}: #{existing.id}"
1526
1155
  else
1527
1156
  record = self.create!(data)
1528
- Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
1157
+ NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1529
1158
  end
1530
1159
  when :create_only
1531
1160
  record = self.create!(data)
1532
- Rails.logger.info "✅ Created new #{self.name}: #{record.id}" if defined?(Rails)
1161
+ NatsWave.logger.info "✅ Created new #{self.name}: #{record.id}"
1533
1162
  end
1534
1163
  rescue => e
1535
- Rails.logger.error "❌ Failed to create #{self.name}: #{e.message}" if defined?(Rails)
1164
+ NatsWave.logger.error "❌ Failed to create #{self.name}: #{e.message}"
1536
1165
  raise
1537
1166
  end
1538
1167
 
@@ -1540,15 +1169,15 @@ module NatsWave
1540
1169
  existing = find_by_unique_fields(data, unique_fields)
1541
1170
  if existing
1542
1171
  existing.update!(data)
1543
- Rails.logger.info "✅ Updated #{self.name}: #{existing.id}" if defined?(Rails)
1172
+ NatsWave.logger.info "✅ Updated #{self.name}: #{existing.id}"
1544
1173
  elsif sync_strategy == :upsert
1545
1174
  record = self.create!(data)
1546
- Rails.logger.info "✅ Created new #{self.name} during update: #{record.id}" if defined?(Rails)
1175
+ NatsWave.logger.info "✅ Created new #{self.name} during update: #{record.id}"
1547
1176
  else
1548
- Rails.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
1177
+ NatsWave.logger.warn "⚠️ Record not found for update: #{data.slice(*unique_fields.map(&:to_s))}"
1549
1178
  end
1550
1179
  rescue => e
1551
- Rails.logger.error "❌ Failed to update #{self.name}: #{e.message}" if defined?(Rails)
1180
+ NatsWave.logger.error "❌ Failed to update #{self.name}: #{e.message}"
1552
1181
  raise
1553
1182
  end
1554
1183
 
@@ -1556,12 +1185,12 @@ module NatsWave
1556
1185
  existing = find_by_unique_fields(data, unique_fields)
1557
1186
  if existing
1558
1187
  existing.destroy!
1559
- Rails.logger.info "✅ Deleted #{self.name}: #{existing.id}" if defined?(Rails)
1188
+ NatsWave.logger.info "✅ Deleted #{self.name}: #{existing.id}"
1560
1189
  else
1561
- Rails.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}" if defined?(Rails)
1190
+ NatsWave.logger.warn "⚠️ Record not found for deletion: #{data.slice(*unique_fields.map(&:to_s))}"
1562
1191
  end
1563
1192
  rescue => e
1564
- Rails.logger.error "❌ Failed to delete #{self.name}: #{e.message}" if defined?(Rails)
1193
+ NatsWave.logger.error "❌ Failed to delete #{self.name}: #{e.message}"
1565
1194
  raise
1566
1195
  end
1567
1196
 
@@ -1579,6 +1208,58 @@ module NatsWave
1579
1208
  return nil if conditions.empty?
1580
1209
  self.find_by(conditions)
1581
1210
  end
1211
+
1212
+ private
1213
+
1214
+ # Setup ActiveRecord callbacks for auto-publishing (only once per model)
1215
+ def setup_publishing_callbacks_once
1216
+ # Only add callbacks if we're in ActiveRecord and haven't added them yet
1217
+ return unless defined?(ActiveRecord::Base) && self < ActiveRecord::Base
1218
+ return if @nats_wave_callbacks_added
1219
+
1220
+ after_commit :trigger_nats_wave_auto_publish_on_create, on: :create
1221
+ after_commit :trigger_nats_wave_auto_publish_on_update, on: :update
1222
+ after_commit :trigger_nats_wave_auto_publish_on_destroy, on: :destroy
1223
+
1224
+ @nats_wave_callbacks_added = true
1225
+ NatsWave.logger.debug "📤 #{self.name}: Added publishing callbacks"
1226
+ end
1227
+
1228
+ # Create a subscription handler that processes data and calls custom handler AFTER auto-sync
1229
+ def create_subscription_handler(config)
1230
+ model_class = self
1231
+
1232
+ lambda do |message|
1233
+ begin
1234
+ NatsWave.logger.debug "📨 Processing subscription message for #{model_class.name}"
1235
+
1236
+ # Extract the raw data
1237
+ raw_data = message['data'] || {}
1238
+ model_name = message['model']
1239
+ action = message['action']
1240
+
1241
+ # Process the data through mappings and transformations
1242
+ processed_data = model_class.process_subscription_data(raw_data, config)
1243
+
1244
+ # Always perform auto-sync first (if enabled)
1245
+ if config[:auto_sync]
1246
+ NatsWave.logger.debug "📨 Performing auto-sync first"
1247
+ model_class.perform_auto_sync(model_name, action, processed_data, config)
1248
+ end
1249
+
1250
+ # Then call custom handler if provided (optional)
1251
+ if config[:custom_handler]
1252
+ NatsWave.logger.debug "📨 Calling custom subscription handler after auto-sync"
1253
+ config[:custom_handler].call(model_name, action, processed_data, message)
1254
+ end
1255
+
1256
+ rescue => e
1257
+ NatsWave.logger.error "Error in subscription handler for #{model_class.name}: #{e.message}"
1258
+ NatsWave.logger.error e.backtrace.join("\n")
1259
+ raise
1260
+ end
1261
+ end
1262
+ end
1582
1263
  end
1583
1264
 
1584
1265
  # Instance methods for publishing
@@ -1591,7 +1272,7 @@ module NatsWave
1591
1272
 
1592
1273
  # Check conditions (only for publishing)
1593
1274
  if config[:conditions].any? && !evaluate_conditions(config[:conditions])
1594
- Rails.logger.debug "📤 Skipping publish - conditions not met" if defined?(Rails)
1275
+ NatsWave.logger.debug "📤 Skipping publish - conditions not met"
1595
1276
  next
1596
1277
  end
1597
1278
 
@@ -1614,17 +1295,17 @@ module NatsWave
1614
1295
  metadata: build_publishing_metadata
1615
1296
  )
1616
1297
 
1617
- Rails.logger.info "📤 Published #{self.class.name}##{id} to #{subject} (#{action})" if defined?(Rails)
1298
+ NatsWave.logger.info "📤 Published #{self.class.name} to #{subject}"
1618
1299
  end
1619
1300
 
1620
1301
  # Then call custom handler if provided (optional)
1621
1302
  if config[:custom_handler]
1622
- Rails.logger.debug "📤 Calling custom publishing handler after publishing" if defined?(Rails)
1303
+ NatsWave.logger.debug "📤 Calling custom publishing handler after publishing"
1623
1304
  config[:custom_handler].call(self.class.name, action, processed_data, self)
1624
1305
  end
1625
1306
  end
1626
1307
  rescue StandardError => e
1627
- Rails.logger.error("Failed to publish: #{e.message}") if defined?(Rails)
1308
+ NatsWave.logger.error("Failed to publish: #{e.message}")
1628
1309
  # Don't re-raise to avoid breaking transactions
1629
1310
  end
1630
1311
 
@@ -1633,7 +1314,7 @@ module NatsWave
1633
1314
  return if @nats_wave_publishing_in_progress
1634
1315
  @nats_wave_publishing_in_progress = true
1635
1316
 
1636
- Rails.logger.debug "🚀 Auto-publishing on create" if defined?(Rails)
1317
+ NatsWave.logger.debug "🚀 Auto-publishing on create"
1637
1318
  nats_wave_publish('create')
1638
1319
 
1639
1320
  @nats_wave_publishing_in_progress = false
@@ -1643,7 +1324,7 @@ module NatsWave
1643
1324
  return if @nats_wave_publishing_in_progress
1644
1325
  @nats_wave_publishing_in_progress = true
1645
1326
 
1646
- Rails.logger.debug "🚀 Auto-publishing on update" if defined?(Rails)
1327
+ NatsWave.logger.debug "🚀 Auto-publishing on update"
1647
1328
  nats_wave_publish('update')
1648
1329
 
1649
1330
  @nats_wave_publishing_in_progress = false
@@ -1653,7 +1334,7 @@ module NatsWave
1653
1334
  return if @nats_wave_publishing_in_progress
1654
1335
  @nats_wave_publishing_in_progress = true
1655
1336
 
1656
- Rails.logger.debug "🚀 Auto-publishing on destroy" if defined?(Rails)
1337
+ NatsWave.logger.debug "🚀 Auto-publishing on destroy"
1657
1338
  nats_wave_publish('destroy')
1658
1339
 
1659
1340
  @nats_wave_publishing_in_progress = false
@@ -1682,31 +1363,49 @@ module NatsWave
1682
1363
  end
1683
1364
  end
1684
1365
 
1685
- # Process publishing data - much simpler now! (INSTANCE METHOD)
1686
1366
  def process_publishing_data(raw_data, config)
1687
1367
  processed_data = {}
1688
- field_mappings = config[:field_mappings]
1689
- transformations = config[:transformations]
1690
- skip_fields = config[:skip_fields]
1368
+ field_mappings = config[:field_mappings] || {}
1369
+ transformations = config[:transformations] || {}
1370
+ skip_fields = config[:skip_fields] || []
1371
+ only_mapped_fields = config[:only_mapped_fields]
1691
1372
 
1692
- raw_data.each do |field, value|
1693
- field_str = field.to_s
1694
- field_sym = field.to_sym
1695
-
1696
- # Skip if in skip_fields
1697
- next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
1698
-
1699
- # Apply field mapping (local -> external) - ONLY if mapping exists
1700
- mapped_field = field_mappings[field_str] ||
1701
- field_mappings[field_sym] ||
1702
- field # Use original field name if no mapping
1703
-
1704
- # Apply transformation if any
1705
- transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
1706
-
1707
- processed_data[mapped_field.to_s] = transformed_value
1373
+ # If only_mapped_fields is true, only process fields that have explicit mappings
1374
+ if only_mapped_fields && field_mappings.any?
1375
+ field_mappings.each do |local_field, external_field|
1376
+ local_field_str = local_field.to_s
1377
+
1378
+ # Skip if this field is in skip_fields
1379
+ next if skip_fields.include?(local_field_str) || skip_fields.include?(local_field.to_sym)
1380
+
1381
+ # Get the value from raw_data
1382
+ value = raw_data[local_field_str] || raw_data[local_field.to_sym]
1383
+
1384
+ # Apply transformation if any (use external field name for transformation lookup)
1385
+ transformed_value = apply_publishing_transformation(value, external_field, transformations, raw_data)
1386
+
1387
+ processed_data[external_field.to_s] = transformed_value
1388
+ end
1389
+ else
1390
+ # Original behavior - process all fields
1391
+ raw_data.each do |field, value|
1392
+ field_str = field.to_s
1393
+ field_sym = field.to_sym
1394
+
1395
+ # Skip if in skip_fields
1396
+ next if skip_fields.include?(field_str) || skip_fields.include?(field_sym)
1397
+
1398
+ # Apply field mapping (local -> external) - ONLY if mapping exists
1399
+ mapped_field = field_mappings[field_str] ||
1400
+ field_mappings[field_sym] ||
1401
+ field # Use original field name if no mapping
1402
+
1403
+ # Apply transformation if any
1404
+ transformed_value = apply_publishing_transformation(value, mapped_field, transformations, raw_data)
1405
+
1406
+ processed_data[mapped_field.to_s] = transformed_value
1407
+ end
1708
1408
  end
1709
-
1710
1409
  processed_data
1711
1410
  end
1712
1411
 
@@ -1726,7 +1425,7 @@ module NatsWave
1726
1425
  elsif value.respond_to?(transformation)
1727
1426
  value.send(transformation)
1728
1427
  else
1729
- Rails.logger.warn "Publishing transformation method #{transformation} not found" if defined?(Rails)
1428
+ NatsWave.logger.warn "Publishing transformation method #{transformation} not found"
1730
1429
  value
1731
1430
  end
1732
1431
  else