smart_message 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.irbrc +24 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile.lock +6 -1
- data/README.md +289 -15
- data/docs/README.md +3 -1
- data/docs/addressing.md +119 -13
- data/docs/architecture.md +68 -0
- data/docs/dead_letter_queue.md +673 -0
- data/docs/dispatcher.md +87 -0
- data/docs/examples.md +59 -1
- data/docs/getting-started.md +8 -1
- data/docs/logging.md +382 -326
- data/docs/message_filtering.md +451 -0
- data/examples/01_point_to_point_orders.rb +54 -53
- data/examples/02_publish_subscribe_events.rb +14 -10
- data/examples/03_many_to_many_chat.rb +16 -8
- data/examples/04_redis_smart_home_iot.rb +20 -10
- data/examples/05_proc_handlers.rb +12 -11
- data/examples/06_custom_logger_example.rb +95 -100
- data/examples/07_error_handling_scenarios.rb +4 -2
- data/examples/08_entity_addressing_basic.rb +18 -6
- data/examples/08_entity_addressing_with_filtering.rb +27 -9
- data/examples/09_dead_letter_queue_demo.rb +559 -0
- data/examples/09_regex_filtering_microservices.rb +407 -0
- data/examples/10_header_block_configuration.rb +263 -0
- data/examples/11_global_configuration_example.rb +219 -0
- data/examples/README.md +102 -0
- data/examples/dead_letters.jsonl +12 -0
- data/examples/performance_metrics/benchmark_results_ractor_20250818_205603.json +135 -0
- data/examples/performance_metrics/benchmark_results_ractor_20250818_205831.json +135 -0
- data/examples/performance_metrics/benchmark_results_test_20250818_204942.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_204942.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_204959.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205044.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205109.json +130 -0
- data/examples/performance_metrics/benchmark_results_threadpool_20250818_205252.json +130 -0
- data/examples/performance_metrics/benchmark_results_unknown_20250819_172852.json +130 -0
- data/examples/performance_metrics/compare_benchmarks.rb +519 -0
- data/examples/performance_metrics/dead_letters.jsonl +3100 -0
- data/examples/performance_metrics/performance_benchmark.rb +344 -0
- data/examples/show_logger.rb +367 -0
- data/examples/show_me.rb +145 -0
- data/examples/temp.txt +94 -0
- data/examples/tmux_chat/bot_agent.rb +4 -2
- data/examples/tmux_chat/human_agent.rb +4 -2
- data/examples/tmux_chat/room_monitor.rb +4 -2
- data/examples/tmux_chat/shared_chat_system.rb +6 -3
- data/lib/smart_message/addressing.rb +259 -0
- data/lib/smart_message/base.rb +121 -599
- data/lib/smart_message/circuit_breaker.rb +2 -1
- data/lib/smart_message/configuration.rb +199 -0
- data/lib/smart_message/dead_letter_queue.rb +27 -10
- data/lib/smart_message/dispatcher.rb +90 -49
- data/lib/smart_message/header.rb +5 -0
- data/lib/smart_message/logger/base.rb +21 -1
- data/lib/smart_message/logger/default.rb +88 -138
- data/lib/smart_message/logger/lumberjack.rb +324 -0
- data/lib/smart_message/logger/null.rb +81 -0
- data/lib/smart_message/logger.rb +17 -9
- data/lib/smart_message/messaging.rb +100 -0
- data/lib/smart_message/plugins.rb +132 -0
- data/lib/smart_message/serializer/base.rb +25 -8
- data/lib/smart_message/serializer/json.rb +5 -4
- data/lib/smart_message/subscription.rb +193 -0
- data/lib/smart_message/transport/base.rb +72 -41
- data/lib/smart_message/transport/memory_transport.rb +7 -5
- data/lib/smart_message/transport/redis_transport.rb +15 -45
- data/lib/smart_message/transport/stdout_transport.rb +18 -8
- data/lib/smart_message/transport.rb +1 -34
- data/lib/smart_message/utilities.rb +142 -0
- data/lib/smart_message/version.rb +1 -1
- data/lib/smart_message/versioning.rb +85 -0
- data/lib/smart_message/wrapper.rb.bak +132 -0
- data/lib/smart_message.rb +74 -28
- data/smart_message.gemspec +3 -0
- metadata +76 -3
- data/lib/smart_message/serializer.rb +0 -10
- data/lib/smart_message/wrapper.rb +0 -43
data/docs/addressing.md
CHANGED
@@ -63,13 +63,14 @@ end
|
|
63
63
|
|
64
64
|
### Class-Level Configuration
|
65
65
|
|
66
|
-
Set default addressing for all instances of a message class:
|
66
|
+
Set default addressing for all instances of a message class using three different approaches:
|
67
67
|
|
68
|
+
#### Method 1: Direct Class Methods
|
68
69
|
```ruby
|
69
70
|
class PaymentMessage < SmartMessage::Base
|
70
71
|
version 1
|
71
72
|
|
72
|
-
# Class-level addressing
|
73
|
+
# Class-level addressing using direct methods
|
73
74
|
from 'payment-service'
|
74
75
|
to 'bank-gateway'
|
75
76
|
reply_to 'payment-service'
|
@@ -77,6 +78,42 @@ class PaymentMessage < SmartMessage::Base
|
|
77
78
|
property :amount, required: true
|
78
79
|
property :account_id, required: true
|
79
80
|
end
|
81
|
+
```
|
82
|
+
|
83
|
+
#### Method 2: Header Block DSL
|
84
|
+
```ruby
|
85
|
+
class PaymentMessage < SmartMessage::Base
|
86
|
+
version 1
|
87
|
+
|
88
|
+
# Class-level addressing using header block
|
89
|
+
header do
|
90
|
+
from 'payment-service'
|
91
|
+
to 'bank-gateway'
|
92
|
+
reply_to 'payment-service'
|
93
|
+
end
|
94
|
+
|
95
|
+
property :amount, required: true
|
96
|
+
property :account_id, required: true
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
#### Method 3: Mixed Approach
|
101
|
+
```ruby
|
102
|
+
class PaymentMessage < SmartMessage::Base
|
103
|
+
version 1
|
104
|
+
|
105
|
+
# You can mix approaches if needed
|
106
|
+
header do
|
107
|
+
from 'payment-service'
|
108
|
+
to 'bank-gateway'
|
109
|
+
end
|
110
|
+
|
111
|
+
# Additional addressing outside the block
|
112
|
+
reply_to 'payment-service'
|
113
|
+
|
114
|
+
property :amount, required: true
|
115
|
+
property :account_id, required: true
|
116
|
+
end
|
80
117
|
|
81
118
|
# All instances inherit class addressing
|
82
119
|
payment = PaymentMessage.new(amount: 100.00, account_id: "ACCT-123")
|
@@ -87,27 +124,54 @@ puts payment._sm_header.reply_to # => 'payment-service'
|
|
87
124
|
|
88
125
|
### Instance-Level Overrides
|
89
126
|
|
90
|
-
Override addressing for specific message instances:
|
127
|
+
Override addressing for specific message instances using multiple approaches:
|
91
128
|
|
129
|
+
#### Method Chaining
|
92
130
|
```ruby
|
93
131
|
class FlexibleMessage < SmartMessage::Base
|
94
|
-
|
95
|
-
|
132
|
+
header do
|
133
|
+
from 'service-a'
|
134
|
+
to 'service-b'
|
135
|
+
end
|
96
136
|
|
97
137
|
property :data
|
98
138
|
end
|
99
139
|
|
100
|
-
# Override addressing
|
140
|
+
# Override addressing using method chaining
|
101
141
|
message = FlexibleMessage.new(data: "test")
|
102
142
|
message.from('different-sender')
|
103
|
-
|
104
|
-
|
143
|
+
.to('different-recipient')
|
144
|
+
.reply_to('different-reply-service')
|
105
145
|
|
106
146
|
puts message.from # => 'different-sender'
|
107
147
|
puts message.to # => 'different-recipient'
|
108
148
|
puts message.reply_to # => 'different-reply-service'
|
149
|
+
```
|
150
|
+
|
151
|
+
#### Setter Methods
|
152
|
+
```ruby
|
153
|
+
# Override addressing using setter syntax
|
154
|
+
message = FlexibleMessage.new(data: "test")
|
155
|
+
message.from = 'different-sender'
|
156
|
+
message.to = 'different-recipient'
|
157
|
+
message.reply_to = 'different-reply-service'
|
158
|
+
```
|
109
159
|
|
110
|
-
|
160
|
+
#### Accessing Addressing Values
|
161
|
+
```ruby
|
162
|
+
# Three ways to access addressing values
|
163
|
+
|
164
|
+
# 1. Direct shortcut methods
|
165
|
+
puts message.from # => 'different-sender'
|
166
|
+
puts message.to # => 'different-recipient'
|
167
|
+
puts message.reply_to # => 'different-reply-service'
|
168
|
+
|
169
|
+
# 2. Via header object
|
170
|
+
puts message._sm_header.from # => 'different-sender'
|
171
|
+
puts message._sm_header.to # => 'different-recipient'
|
172
|
+
puts message._sm_header.reply_to # => 'different-reply-service'
|
173
|
+
|
174
|
+
# 3. Class defaults remain unchanged
|
111
175
|
puts FlexibleMessage.from # => 'service-a'
|
112
176
|
puts FlexibleMessage.to # => 'service-b'
|
113
177
|
```
|
@@ -257,27 +321,69 @@ message.publish # Raises SmartMessage::Errors::ValidationError
|
|
257
321
|
# => "The property 'from' From entity ID is required for message routing and replies"
|
258
322
|
```
|
259
323
|
|
324
|
+
### Checking Address Configuration
|
325
|
+
```ruby
|
326
|
+
class ValidatedMessage < SmartMessage::Base
|
327
|
+
header do
|
328
|
+
from 'my-service'
|
329
|
+
to 'target-service'
|
330
|
+
end
|
331
|
+
|
332
|
+
property :data
|
333
|
+
end
|
334
|
+
|
335
|
+
# Class-level checks
|
336
|
+
puts ValidatedMessage.from_configured? # => true
|
337
|
+
puts ValidatedMessage.to_configured? # => true
|
338
|
+
puts ValidatedMessage.reply_to_configured? # => false
|
339
|
+
puts ValidatedMessage.reply_to_missing? # => true
|
340
|
+
|
341
|
+
# Instance-level checks
|
342
|
+
message = ValidatedMessage.new(data: "test")
|
343
|
+
puts message.from_configured? # => true
|
344
|
+
puts message.to_missing? # => false
|
345
|
+
|
346
|
+
# Reset addressing
|
347
|
+
message.reset_from
|
348
|
+
puts message.from_configured? # => false
|
349
|
+
puts message.from # => nil
|
350
|
+
```
|
351
|
+
|
260
352
|
## Header Access
|
261
353
|
|
262
354
|
Access addressing information from message headers:
|
263
355
|
|
264
356
|
```ruby
|
265
357
|
class SampleMessage < SmartMessage::Base
|
266
|
-
|
267
|
-
|
268
|
-
|
358
|
+
# Using header block for configuration
|
359
|
+
header do
|
360
|
+
from 'sample-service'
|
361
|
+
to 'target-service'
|
362
|
+
reply_to 'callback-service'
|
363
|
+
end
|
269
364
|
|
270
365
|
property :content
|
271
366
|
end
|
272
367
|
|
273
368
|
message = SampleMessage.new(content: "Hello")
|
274
|
-
header = message._sm_header
|
275
369
|
|
370
|
+
# Access via shortcut methods (recommended)
|
371
|
+
puts message.from # => 'sample-service'
|
372
|
+
puts message.to # => 'target-service'
|
373
|
+
puts message.reply_to # => 'callback-service'
|
374
|
+
|
375
|
+
# Access via header object
|
376
|
+
header = message._sm_header
|
276
377
|
puts header.from # => 'sample-service'
|
277
378
|
puts header.to # => 'target-service'
|
278
379
|
puts header.reply_to # => 'callback-service'
|
279
380
|
puts header.uuid # => Generated UUID
|
280
381
|
puts header.message_class # => 'SampleMessage'
|
382
|
+
|
383
|
+
# Headers automatically sync with instance changes
|
384
|
+
message.to = 'new-target'
|
385
|
+
puts message.to # => 'new-target'
|
386
|
+
puts header.to # => 'new-target' (automatically updated)
|
281
387
|
```
|
282
388
|
|
283
389
|
## Integration with Dispatcher
|
data/docs/architecture.md
CHANGED
@@ -345,6 +345,74 @@ module SmartMessage::Errors
|
|
345
345
|
end
|
346
346
|
```
|
347
347
|
|
348
|
+
## Reliability & Fault Tolerance
|
349
|
+
|
350
|
+
### Circuit Breaker Integration
|
351
|
+
|
352
|
+
SmartMessage integrates BreakerMachines for production-grade reliability:
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
# Transport operations protected by circuit breakers
|
356
|
+
class MyTransport < SmartMessage::Transport::Base
|
357
|
+
circuit :transport_publish do
|
358
|
+
threshold failures: 5, within: 30.seconds
|
359
|
+
reset_after 15.seconds
|
360
|
+
fallback SmartMessage::CircuitBreaker::Fallbacks.dead_letter_queue
|
361
|
+
end
|
362
|
+
end
|
363
|
+
```
|
364
|
+
|
365
|
+
**Circuit Breaker States:**
|
366
|
+
- **Closed**: Normal operation, requests pass through
|
367
|
+
- **Open**: Threshold exceeded, requests fail fast
|
368
|
+
- **Half-Open**: Testing if service recovered
|
369
|
+
|
370
|
+
### Dead Letter Queue
|
371
|
+
|
372
|
+
Failed messages are automatically captured in the Dead Letter Queue:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
# Automatic capture when circuit breaker trips
|
376
|
+
message.publish # If transport fails, goes to DLQ
|
377
|
+
|
378
|
+
# Manual capture for business logic failures
|
379
|
+
dlq = SmartMessage::DeadLetterQueue.default
|
380
|
+
dlq.enqueue(header, payload, error: "Validation failed")
|
381
|
+
```
|
382
|
+
|
383
|
+
**DLQ Architecture:**
|
384
|
+
|
385
|
+
```
|
386
|
+
┌─────────────────────────────────────────────────────────────┐
|
387
|
+
│ Message Publishing │
|
388
|
+
│ │ │
|
389
|
+
│ ▼ │
|
390
|
+
│ ┌─────────────────┐ │
|
391
|
+
│ │ Circuit Breaker │ │
|
392
|
+
│ │ (Monitoring) │ │
|
393
|
+
│ └─────────────────┘ │
|
394
|
+
│ │ │ │
|
395
|
+
│ Success │ │ Failure │
|
396
|
+
│ ▼ ▼ │
|
397
|
+
│ ┌──────────┐ ┌─────────────┐ │
|
398
|
+
│ │Transport │ │Dead Letter │ │
|
399
|
+
│ │ │ │ Queue │ │
|
400
|
+
│ └──────────┘ └─────────────┘ │
|
401
|
+
│ │ │
|
402
|
+
│ ▼ │
|
403
|
+
│ ┌─────────────┐ │
|
404
|
+
│ │ Replay │ │
|
405
|
+
│ │ Mechanism │ │
|
406
|
+
│ └─────────────┘ │
|
407
|
+
└─────────────────────────────────────────────────────────────┘
|
408
|
+
```
|
409
|
+
|
410
|
+
**DLQ Features:**
|
411
|
+
- JSON Lines format for efficient append operations
|
412
|
+
- FIFO queue operations with thread safety
|
413
|
+
- Replay capabilities with transport override
|
414
|
+
- Administrative tools for filtering and analysis
|
415
|
+
|
348
416
|
## Statistics & Monitoring
|
349
417
|
|
350
418
|
### Built-in Statistics
|