smart_message 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c388c9738746603d14a57d6c4e04fb7d6e48156c4e571cd82dffd461217e111
4
- data.tar.gz: 975779de0b52686b8b08baa94070fea52578c86f5fb1a3752aa25cad98a812d7
3
+ metadata.gz: 118cf15fea99493c202bd383a547358a44a3873284cfe656665701213b40b51e
4
+ data.tar.gz: 7e542557b5b88f2963291232a875ba4dab44c682673251d7e976ac913ff41c14
5
5
  SHA512:
6
- metadata.gz: b425fa9d66a2716394a1dc695b8ba82c9acc9c82dc616fc00cf8eeab2639a7833640e71240969614f31836ee0d325ae8980fa4f4d266e6961dfd6a8971172420
7
- data.tar.gz: 711381ff80115a8582551fc58f22630c9c103c24d46f04b1edc54b87d41fd181d80a0f730cc6d14a000ec3b5478330062385edb6e5344fe1e541559e82652c97
6
+ metadata.gz: 637591235fcdf1feb8708f244d1f2f6b416d7330bca7f06c597581ea9ffcb3eb55e74610bcc045c7839e50304f978fd24092c870528a7f3277cd0d8be2620ae4
7
+ data.tar.gz: 35773299f97565981fc778bd76358c2560eef1d6c4885367ddb66d81448136c8a8a9f402d26477d2c7ac29c885f07906a7e3f0396fb827fdf15e5bbe3e5a43bc
data/CHANGELOG.md CHANGED
@@ -6,6 +6,128 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
+ ## [0.0.7] 2025-08-19
10
+ ### Added
11
+ - **Production-Grade Circuit Breaker Integration**: Comprehensive reliability patterns using BreakerMachines gem
12
+ - Circuit breaker protection for message processing operations with configurable failure thresholds
13
+ - Transport-level circuit breakers for publish/subscribe operations with automatic fallback
14
+ - Integrated circuit breaker DSL throughout SmartMessage components for production reliability
15
+ - Memory and Redis storage backends for circuit breaker state persistence
16
+ - Built-in fallback mechanisms including dead letter queue, retry with exponential backoff, and graceful degradation
17
+ - Circuit breaker statistics and introspection capabilities for monitoring and debugging
18
+
19
+ ### Fixed
20
+ - **Critical: Redis Transport Header Preservation**: Fixed message header information loss during Redis pub/sub transport
21
+ - **Root Cause**: Redis transport was only sending message payload through channels, reconstructing generic headers on receive
22
+ - **Impact**: Message addressing information (`from`, `to`, `reply_to`) was lost, breaking entity-aware filtering and routing
23
+ - **Solution**: Modified Redis transport to combine header and payload into JSON structure during publish/subscribe
24
+ - **Result**: Full header information now preserved across Redis transport with backward compatibility fallback
25
+ - Redis IoT example now displays all expected sensor data, alerts, and real-time device monitoring output
26
+ - **Performance: Dispatcher Shutdown Optimization**: Dramatically improved dispatcher shutdown speed
27
+ - **Previous Issue**: Slow 1-second polling with no timeout mechanism caused delays up to several minutes
28
+ - **Optimization**: Replaced with native `wait_for_termination(3)` using Concurrent::ThreadPool built-in timeout
29
+ - **Performance Gain**: Shutdown now completes in milliseconds instead of seconds
30
+ - Removed unnecessary circuit breaker wrapper - thread pool handles timeout and fallback natively
31
+ - **Code Quality: Transport Method Signature Consistency**: Ensured all transport `do_publish` methods use consistent parameters
32
+ - Standardized `do_publish(message_header, message_payload)` signature across all transport implementations
33
+ - Updated Redis, STDOUT, and Memory transports for consistent interface
34
+
35
+ ### Changed
36
+ - **Dispatcher Architecture**: Simplified shutdown mechanism leveraging Concurrent::ThreadPool native capabilities
37
+ - Removed custom timeout polling logic in favor of built-in `wait_for_termination` method
38
+ - Eliminated redundant circuit breaker for shutdown operations - thread pool provides timeout and fallback
39
+ - **BREAKING**: Removed `router_pool_shutdown` circuit breaker configuration (no longer needed)
40
+ - **Redis Transport Protocol**: Enhanced message format to preserve complete header information
41
+ - Redis messages now contain both header and payload: `{header: {...}, payload: "..."}`
42
+ - Automatic fallback to legacy behavior for malformed or old-format messages
43
+ - Maintains full backward compatibility with existing Redis deployments
44
+
45
+ ### Enhanced
46
+ - **Circuit Breaker Integration**: Strategic application of reliability patterns where most beneficial
47
+ - Message processing operations protected with configurable failure thresholds and fallback behavior
48
+ - Transport publish/subscribe operations wrapped with circuit breakers for external service protection
49
+ - Clean separation between internal operations (thread pools) and external dependencies (Redis, etc.)
50
+ - **Redis Transport Reliability**: Production-ready Redis pub/sub with complete message fidelity
51
+ - Full message header preservation enables proper entity-aware filtering and routing
52
+ - IoT examples now demonstrate complete real-time messaging with sensor data, alerts, and device commands
53
+ - Enhanced error handling with JSON parsing fallbacks for malformed messages
54
+ - **Developer Experience**: Cleaner, more maintainable codebase with proper separation of concerns
55
+ - Circuit breakers applied strategically for external dependencies, not internal thread management
56
+ - Simplified shutdown logic leverages proven Concurrent::ThreadPool patterns
57
+ - Clear distinction between reliability mechanisms and business logic
58
+
59
+ ### Documentation
60
+ - **Circuit Breaker Patterns**: Examples of proper BreakerMachines DSL usage throughout codebase
61
+ - Strategic application for external service protection vs internal thread management
62
+ - Configuration examples for different failure scenarios and recovery patterns
63
+ - Best practices for production-grade messaging reliability
64
+
65
+ ## [0.0.6] 2025-08-19
66
+
67
+ ### Added
68
+ - **Entity-Aware Message Filtering**: Advanced subscription filtering system enabling precise message routing
69
+ - New subscription filter parameters: `broadcast:`, `to:`, `from:` for `subscribe` method
70
+ - Filter by broadcast messages only: `MyMessage.subscribe(broadcast: true)`
71
+ - Filter by destination entity: `MyMessage.subscribe(to: 'service-name')`
72
+ - Filter by sender entity: `MyMessage.subscribe(from: 'sender-service')`
73
+ - Support for array-based filters: `subscribe(from: ['admin', 'system'])`
74
+ - Combined filters with OR logic: `subscribe(broadcast: true, to: 'my-service')`
75
+ - String-to-array automatic conversion for convenience: `subscribe(to: 'service')` becomes `['service']`
76
+ - Full backward compatibility - existing subscriptions work unchanged
77
+ - **Real-Time Header Synchronization**: Message headers now update automatically when addressing fields change
78
+ - Instance-level `from()`, `to()`, `reply_to()` methods now update both instance variables and message headers
79
+ - Enables filtering to work correctly when addressing is changed after message creation
80
+ - Reset methods (`reset_from`, `reset_to`, `reset_reply_to`) also update headers
81
+ - Critical for entity-aware filtering functionality
82
+ - **Enhanced Example Programs**
83
+ - New comprehensive filtering example: `examples/08_entity_addressing_with_filtering.rb`
84
+ - Demonstrates all filtering capabilities with real-world microservice scenarios
85
+ - Improved timing with sleep statements for better output visualization
86
+ - Updated basic addressing example: `examples/08_entity_addressing_basic.rb`
87
+ - Both examples now show clear interleaved publish/receive output flow
88
+
89
+ ### Changed
90
+ - **Message Subscription Architecture**: Subscription storage updated to support filtering
91
+ - Dispatcher now stores subscription objects with filter criteria instead of simple method strings
92
+ - Subscription objects contain `{process_method: string, filters: hash}` structure
93
+ - All transport implementations updated to pass filter options through subscription chain
94
+ - RedisTransport updated to accept new filter_options parameter
95
+ - **Header Addressing Behavior**: Message headers now reflect real-time addressing changes
96
+ - **BREAKING**: Headers are no longer immutable after creation - they update when addressing methods are called
97
+ - This change enables entity-aware filtering to work correctly with dynamic addressing
98
+ - Previous behavior kept original addressing in headers while instance methods showed new values
99
+
100
+ ### Fixed
101
+ - **Message Filtering Logic**: Resolved critical filtering implementation issues
102
+ - Fixed message_matches_filters? method to properly evaluate filter criteria
103
+ - Corrected AND/OR logic for combined broadcast and entity-specific filters
104
+ - Ensured filtering works with both class-level and instance-level addressing
105
+ - **Test Suite Compatibility**: Updated all tests to work with new subscription structure
106
+ - Fixed ProcHandlerTest to expect subscription objects instead of string arrays
107
+ - Updated TransportTest to handle new subscription object format
108
+ - Fixed AddressingTest to reflect new real-time header update behavior
109
+ - All existing functionality preserved with full backward compatibility
110
+
111
+ ### Enhanced
112
+ - **Message Processing Performance**: Filtering happens at subscription level, reducing processing overhead
113
+ - Messages not matching filter criteria are ignored by handlers, improving efficiency
114
+ - Enables microservices to process only relevant messages
115
+ - Reduces unnecessary handler invocations and processing cycles
116
+ - **Developer Experience**: Clear examples demonstrate filtering benefits and usage patterns
117
+ - Examples show both what DOES and DOESN'T get processed
118
+ - Demonstrates gateway patterns, admin message handling, and microservice communication
119
+ - Educational value enhanced with comprehensive console output and timing
120
+
121
+ ### Documentation
122
+ - **Entity-Aware Filtering Guide**: Comprehensive examples showing all filtering capabilities
123
+ - Broadcast vs directed message handling patterns
124
+ - Admin/monitoring system integration examples
125
+ - Request-reply routing with filters
126
+ - Gateway pattern implementations with dynamic routing
127
+ - Best practices for microservice message filtering
128
+ - **Breaking Change Documentation**: Clear explanation of header behavior changes
129
+ - Migration guide for applications depending on immutable headers
130
+ - Benefits of real-time header updates for filtering functionality
9
131
 
10
132
  ## [0.0.5] 2025-08-18
11
133
 
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_message (0.0.4)
4
+ smart_message (0.0.7)
5
5
  activesupport
6
+ breaker_machines
6
7
  concurrent-ruby
7
8
  hashie
8
9
  redis
@@ -27,6 +28,11 @@ GEM
27
28
  base64 (0.3.0)
28
29
  benchmark (0.4.1)
29
30
  bigdecimal (3.2.2)
31
+ breaker_machines (0.4.0)
32
+ activesupport (>= 7.2)
33
+ concurrent-ruby (~> 1.3)
34
+ state_machines (>= 0.50.0)
35
+ zeitwerk (~> 2.7)
30
36
  concurrent-ruby (1.3.5)
31
37
  connection_pool (2.5.3)
32
38
  debug_me (1.1.1)
@@ -53,9 +59,11 @@ GEM
53
59
  shoulda-context (2.0.0)
54
60
  shoulda-matchers (4.5.1)
55
61
  activesupport (>= 4.2.0)
62
+ state_machines (0.100.1)
56
63
  tzinfo (2.0.6)
57
64
  concurrent-ruby (~> 1.0)
58
65
  uri (1.0.3)
66
+ zeitwerk (2.7.3)
59
67
 
60
68
  PLATFORMS
61
69
  arm64-darwin-24
data/README.md CHANGED
@@ -9,6 +9,7 @@ SmartMessage is a message abstraction framework that decouples business logic fr
9
9
 
10
10
  - **Transport Abstraction**: Plugin architecture supporting multiple message transports (Redis, RabbitMQ, Kafka, etc.)
11
11
  - **Serialization Flexibility**: Pluggable serialization formats (JSON, MessagePack, etc.)
12
+ - **Entity-to-Entity Addressing**: Built-in FROM/TO/REPLY_TO addressing for point-to-point and broadcast messaging patterns
12
13
  - **Schema Versioning**: Built-in version management with automatic compatibility validation
13
14
  - **Comprehensive Validation**: Property validation with custom error messages and automatic validation before publishing
14
15
  - **Message Documentation**: Built-in documentation support for message classes and properties with automatic defaults
@@ -47,6 +48,11 @@ class OrderMessage < SmartMessage::Base
47
48
  # Add a description for the message class
48
49
  description "Represents customer order data for processing and fulfillment"
49
50
 
51
+ # Configure entity addressing
52
+ from 'order-service'
53
+ to 'fulfillment-service' # Point-to-point message
54
+ reply_to 'order-service' # Responses come back here
55
+
50
56
  # Required properties with validation
51
57
  property :order_id,
52
58
  required: true,
@@ -153,6 +159,50 @@ end
153
159
  OrderMessage.subscribe(audit_handler)
154
160
  ```
155
161
 
162
+ ### 4. Entity Addressing
163
+
164
+ SmartMessage supports entity-to-entity addressing with FROM/TO/REPLY_TO fields for advanced message routing:
165
+
166
+ ```ruby
167
+ # Point-to-point messaging
168
+ class PaymentMessage < SmartMessage::Base
169
+ version 1
170
+ from 'payment-service' # Required: sender identity
171
+ to 'bank-gateway' # Optional: specific recipient
172
+ reply_to 'payment-service' # Optional: where responses go
173
+
174
+ property :amount, required: true
175
+ property :account_id, required: true
176
+ end
177
+
178
+ # Broadcast messaging (no 'to' specified)
179
+ class SystemAnnouncementMessage < SmartMessage::Base
180
+ version 1
181
+ from 'admin-service' # Required: sender identity
182
+ # No 'to' field = broadcast to all subscribers
183
+
184
+ property :message, required: true
185
+ property :priority, default: 'normal'
186
+ end
187
+
188
+ # Instance-level addressing override
189
+ payment = PaymentMessage.new(amount: 100.00, account_id: "ACCT-123")
190
+ payment.to('backup-gateway') # Override destination for this instance
191
+ payment.publish
192
+
193
+ # Access addressing information
194
+ puts payment._sm_header.from # => 'payment-service'
195
+ puts payment._sm_header.to # => 'backup-gateway'
196
+ puts payment._sm_header.reply_to # => 'payment-service'
197
+ ```
198
+
199
+ #### Messaging Patterns Supported
200
+
201
+ - **Point-to-Point**: Set `to` field for direct entity targeting
202
+ - **Broadcast**: Omit `to` field (nil) for message broadcast to all subscribers
203
+ - **Request-Reply**: Use `reply_to` field to specify response routing
204
+ - **Gateway Patterns**: Override addressing at instance level for message forwarding
205
+
156
206
  ## Architecture
157
207
 
158
208
  ### Core Components
@@ -323,15 +373,16 @@ end
323
373
  ## Message Lifecycle
324
374
 
325
375
  1. **Definition**: Create message class inheriting from `SmartMessage::Base`
326
- 2. **Configuration**: Set transport, serializer, and logger plugins
327
- 3. **Validation**: Messages are automatically validated before publishing (properties, header, version compatibility)
328
- 4. **Publishing**: Message instance is encoded and sent through transport
376
+ 2. **Configuration**: Set transport, serializer, logger plugins, and entity addressing (from/to/reply_to)
377
+ 3. **Validation**: Messages are automatically validated before publishing (properties, header, addressing, version compatibility)
378
+ 4. **Publishing**: Message instance is encoded with addressing metadata and sent through transport
329
379
  5. **Subscription**: Message classes register handlers with dispatcher for processing
330
380
  - Default handlers (`self.process` method)
331
381
  - Custom method handlers (`"ClassName.method_name"`)
332
382
  - Block handlers (`subscribe do |h,p|...end`)
333
383
  - Proc/Lambda handlers (`subscribe(proc {...})`)
334
- 6. **Processing**: Received messages are decoded and routed to registered handlers
384
+ 6. **Routing**: Dispatcher uses addressing metadata to route messages (point-to-point vs broadcast)
385
+ 7. **Processing**: Received messages are decoded and routed to registered handlers
335
386
 
336
387
  ## Schema Versioning and Validation
337
388
 
@@ -588,6 +639,9 @@ puts message._sm_header.uuid
588
639
  puts message._sm_header.message_class
589
640
  puts message._sm_header.published_at
590
641
  puts message._sm_header.publisher_pid
642
+ puts message._sm_header.from
643
+ puts message._sm_header.to
644
+ puts message._sm_header.reply_to
591
645
  ```
592
646
 
593
647
  ## Development
data/docs/README.md CHANGED
@@ -16,6 +16,7 @@ Welcome to the comprehensive documentation for SmartMessage, a Ruby gem that abs
16
16
  ### Components
17
17
  - [SmartMessage::Base](base.md)
18
18
  - [Property System](properties.md)
19
+ - [Entity Addressing](addressing.md)
19
20
  - [Transport Layer](transports.md)
20
21
  - [Serializers](serializers.md)
21
22
  - [Logging System](logging.md)
@@ -0,0 +1,364 @@
1
+ # Entity Addressing
2
+
3
+ SmartMessage supports entity-to-entity addressing through built-in FROM/TO/REPLY_TO fields in message headers. This enables sophisticated messaging patterns including point-to-point communication, broadcast messaging, and request-reply workflows.
4
+
5
+ ## Overview
6
+
7
+ Entity addressing in SmartMessage provides:
8
+
9
+ - **Sender Identification**: Required `from` field identifies the sending entity
10
+ - **Recipient Targeting**: Optional `to` field for point-to-point messaging
11
+ - **Response Routing**: Optional `reply_to` field for request-reply patterns
12
+ - **Broadcast Support**: Omitting `to` field enables broadcast to all subscribers
13
+ - **Dual-Level Configuration**: Class and instance-level addressing configuration
14
+
15
+ ## Address Fields
16
+
17
+ ### FROM (Required)
18
+ The `from` field identifies the entity sending the message. This is required for all messages.
19
+
20
+ ```ruby
21
+ class MyMessage < SmartMessage::Base
22
+ from 'order-service' # Required sender identity
23
+
24
+ property :data
25
+ end
26
+ ```
27
+
28
+ ### TO (Optional)
29
+ The `to` field specifies the intended recipient entity. When present, creates point-to-point messaging. When `nil`, the message is broadcast to all subscribers.
30
+
31
+ ```ruby
32
+ # Point-to-point messaging
33
+ class DirectMessage < SmartMessage::Base
34
+ from 'sender-service'
35
+ to 'recipient-service' # Specific target
36
+
37
+ property :content
38
+ end
39
+
40
+ # Broadcast messaging
41
+ class AnnouncementMessage < SmartMessage::Base
42
+ from 'admin-service'
43
+ # No 'to' field = broadcast to all subscribers
44
+
45
+ property :announcement
46
+ end
47
+ ```
48
+
49
+ ### REPLY_TO (Optional)
50
+ The `reply_to` field specifies where responses should be sent. Defaults to the `from` entity if not specified.
51
+
52
+ ```ruby
53
+ class RequestMessage < SmartMessage::Base
54
+ from 'client-service'
55
+ to 'api-service'
56
+ reply_to 'client-callback-service' # Responses go here
57
+
58
+ property :request_data
59
+ end
60
+ ```
61
+
62
+ ## Configuration Patterns
63
+
64
+ ### Class-Level Configuration
65
+
66
+ Set default addressing for all instances of a message class:
67
+
68
+ ```ruby
69
+ class PaymentMessage < SmartMessage::Base
70
+ version 1
71
+
72
+ # Class-level addressing
73
+ from 'payment-service'
74
+ to 'bank-gateway'
75
+ reply_to 'payment-service'
76
+
77
+ property :amount, required: true
78
+ property :account_id, required: true
79
+ end
80
+
81
+ # All instances inherit class addressing
82
+ payment = PaymentMessage.new(amount: 100.00, account_id: "ACCT-123")
83
+ puts payment._sm_header.from # => 'payment-service'
84
+ puts payment._sm_header.to # => 'bank-gateway'
85
+ puts payment._sm_header.reply_to # => 'payment-service'
86
+ ```
87
+
88
+ ### Instance-Level Overrides
89
+
90
+ Override addressing for specific message instances:
91
+
92
+ ```ruby
93
+ class FlexibleMessage < SmartMessage::Base
94
+ from 'service-a'
95
+ to 'service-b'
96
+
97
+ property :data
98
+ end
99
+
100
+ # Override addressing for this instance
101
+ message = FlexibleMessage.new(data: "test")
102
+ message.from('different-sender')
103
+ message.to('different-recipient')
104
+ message.reply_to('different-reply-service')
105
+
106
+ puts message.from # => 'different-sender'
107
+ puts message.to # => 'different-recipient'
108
+ puts message.reply_to # => 'different-reply-service'
109
+
110
+ # Class defaults remain unchanged
111
+ puts FlexibleMessage.from # => 'service-a'
112
+ puts FlexibleMessage.to # => 'service-b'
113
+ ```
114
+
115
+ ## Messaging Patterns
116
+
117
+ ### Point-to-Point Messaging
118
+
119
+ Direct communication between two specific entities:
120
+
121
+ ```ruby
122
+ class OrderProcessingMessage < SmartMessage::Base
123
+ from 'order-service'
124
+ to 'inventory-service' # Direct target
125
+ reply_to 'order-service'
126
+
127
+ property :order_id, required: true
128
+ property :items, required: true
129
+ end
130
+
131
+ # Message goes directly to inventory-service
132
+ order = OrderProcessingMessage.new(
133
+ order_id: "ORD-123",
134
+ items: ["widget-1", "widget-2"]
135
+ )
136
+ order.publish # Only inventory-service receives this
137
+ ```
138
+
139
+ ### Broadcast Messaging
140
+
141
+ Send message to all subscribers by omitting the `to` field:
142
+
143
+ ```ruby
144
+ class SystemMaintenanceMessage < SmartMessage::Base
145
+ from 'admin-service'
146
+ # No 'to' field = broadcast
147
+
148
+ property :message, required: true
149
+ property :scheduled_time, required: true
150
+ end
151
+
152
+ # Message goes to all subscribers
153
+ maintenance = SystemMaintenanceMessage.new(
154
+ message: "System maintenance tonight at 2 AM",
155
+ scheduled_time: Time.parse("2024-01-15 02:00:00")
156
+ )
157
+ maintenance.publish # All subscribers receive this
158
+ ```
159
+
160
+ ### Request-Reply Pattern
161
+
162
+ Structured request-response communication:
163
+
164
+ ```ruby
165
+ # Request message
166
+ class UserLookupRequest < SmartMessage::Base
167
+ from 'web-service'
168
+ to 'user-service'
169
+ reply_to 'web-service' # Responses come back here
170
+
171
+ property :user_id, required: true
172
+ property :request_id, required: true # For correlation
173
+ end
174
+
175
+ # Response message
176
+ class UserLookupResponse < SmartMessage::Base
177
+ from 'user-service'
178
+ # 'to' will be set to the original 'reply_to' value
179
+
180
+ property :user_id, required: true
181
+ property :request_id, required: true # Correlation ID
182
+ property :user_data
183
+ property :success, default: true
184
+ end
185
+
186
+ # Send request
187
+ request = UserLookupRequest.new(
188
+ user_id: "USER-123",
189
+ request_id: SecureRandom.uuid
190
+ )
191
+ request.publish
192
+
193
+ # In user-service handler:
194
+ class UserLookupRequest
195
+ def self.process(header, payload)
196
+ request_data = JSON.parse(payload)
197
+
198
+ # Process lookup...
199
+ user_data = UserService.find(request_data['user_id'])
200
+
201
+ # Send response back to reply_to address
202
+ response = UserLookupResponse.new(
203
+ user_id: request_data['user_id'],
204
+ request_id: request_data['request_id'],
205
+ user_data: user_data
206
+ )
207
+ response.to(header.reply_to) # Send to original reply_to
208
+ response.publish
209
+ end
210
+ end
211
+ ```
212
+
213
+ ### Gateway Pattern
214
+
215
+ Forward messages between different transports/formats:
216
+
217
+ ```ruby
218
+ class GatewayMessage < SmartMessage::Base
219
+ from 'gateway-service'
220
+
221
+ property :original_message
222
+ property :source_format
223
+ property :target_format
224
+ end
225
+
226
+ # Receive from one transport/format
227
+ incoming = SomeMessage.new(data: "from system A")
228
+
229
+ # Forward to different system with different addressing
230
+ gateway_msg = GatewayMessage.new(
231
+ original_message: incoming.to_h,
232
+ source_format: 'json',
233
+ target_format: 'xml'
234
+ )
235
+
236
+ # Override transport and addressing for forwarding
237
+ gateway_msg.config do
238
+ transport DifferentTransport.new
239
+ serializer DifferentSerializer.new
240
+ end
241
+ gateway_msg.to('system-b')
242
+ gateway_msg.publish
243
+ ```
244
+
245
+ ## Address Validation
246
+
247
+ The `from` field is required and validated automatically:
248
+
249
+ ```ruby
250
+ class InvalidMessage < SmartMessage::Base
251
+ # No 'from' specified - will fail validation
252
+ property :data
253
+ end
254
+
255
+ message = InvalidMessage.new(data: "test")
256
+ message.publish # Raises SmartMessage::Errors::ValidationError
257
+ # => "The property 'from' From entity ID is required for message routing and replies"
258
+ ```
259
+
260
+ ## Header Access
261
+
262
+ Access addressing information from message headers:
263
+
264
+ ```ruby
265
+ class SampleMessage < SmartMessage::Base
266
+ from 'sample-service'
267
+ to 'target-service'
268
+ reply_to 'callback-service'
269
+
270
+ property :content
271
+ end
272
+
273
+ message = SampleMessage.new(content: "Hello")
274
+ header = message._sm_header
275
+
276
+ puts header.from # => 'sample-service'
277
+ puts header.to # => 'target-service'
278
+ puts header.reply_to # => 'callback-service'
279
+ puts header.uuid # => Generated UUID
280
+ puts header.message_class # => 'SampleMessage'
281
+ ```
282
+
283
+ ## Integration with Dispatcher
284
+
285
+ The dispatcher can use addressing metadata for advanced routing logic:
286
+
287
+ ```ruby
288
+ # Future enhancement: Dispatcher filtering by recipient
289
+ # dispatcher.route(message_header, payload) do |header|
290
+ # if header.to.nil?
291
+ # # Broadcast to all subscribers
292
+ # route_to_all_subscribers(header.message_class)
293
+ # else
294
+ # # Route only to specific recipient
295
+ # route_to_entity(header.to, header.message_class)
296
+ # end
297
+ # end
298
+ ```
299
+
300
+ ## Best Practices
301
+
302
+ ### Entity Naming
303
+ Use consistent, descriptive entity identifiers:
304
+
305
+ ```ruby
306
+ # Good: Descriptive service names
307
+ from 'order-management-service'
308
+ to 'inventory-tracking-service'
309
+ reply_to 'order-status-service'
310
+
311
+ # Avoid: Generic or unclear names
312
+ from 'service1'
313
+ to 'app'
314
+ ```
315
+
316
+ ### Address Consistency
317
+ Maintain consistent addressing patterns across your application:
318
+
319
+ ```ruby
320
+ # Consistent pattern for microservices
321
+ class OrderMessage < SmartMessage::Base
322
+ from 'order-service'
323
+ to 'fulfillment-service'
324
+ reply_to 'order-service'
325
+ end
326
+
327
+ class PaymentMessage < SmartMessage::Base
328
+ from 'payment-service'
329
+ to 'billing-service'
330
+ reply_to 'payment-service'
331
+ end
332
+ ```
333
+
334
+ ### Gateway Configuration
335
+ For gateway patterns, use instance-level overrides:
336
+
337
+ ```ruby
338
+ # Class defines default routing
339
+ class APIMessage < SmartMessage::Base
340
+ from 'api-gateway'
341
+ to 'internal-service'
342
+ end
343
+
344
+ # Override for external routing
345
+ message = APIMessage.new(data: "external request")
346
+ message.to('external-partner-service')
347
+ message.config do
348
+ transport ExternalTransport.new
349
+ serializer SecureSerializer.new
350
+ end
351
+ message.publish
352
+ ```
353
+
354
+ ## Future Enhancements
355
+
356
+ The addressing system provides the foundation for advanced features:
357
+
358
+ - **Dispatcher Filtering**: Route messages based on recipient targeting
359
+ - **Security Integration**: Entity-based authentication and authorization
360
+ - **Audit Trails**: Track message flow between entities
361
+ - **Load Balancing**: Distribute messages across entity instances
362
+ - **Circuit Breakers**: Per-entity failure handling
363
+
364
+ Entity addressing enables sophisticated messaging architectures while maintaining the simplicity and flexibility that makes SmartMessage powerful.