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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.irbrc +24 -0
  4. data/CHANGELOG.md +96 -0
  5. data/Gemfile.lock +6 -1
  6. data/README.md +289 -15
  7. data/docs/README.md +3 -1
  8. data/docs/addressing.md +119 -13
  9. data/docs/architecture.md +68 -0
  10. data/docs/dead_letter_queue.md +673 -0
  11. data/docs/dispatcher.md +87 -0
  12. data/docs/examples.md +59 -1
  13. data/docs/getting-started.md +8 -1
  14. data/docs/logging.md +382 -326
  15. data/docs/message_filtering.md +451 -0
  16. data/examples/01_point_to_point_orders.rb +54 -53
  17. data/examples/02_publish_subscribe_events.rb +14 -10
  18. data/examples/03_many_to_many_chat.rb +16 -8
  19. data/examples/04_redis_smart_home_iot.rb +20 -10
  20. data/examples/05_proc_handlers.rb +12 -11
  21. data/examples/06_custom_logger_example.rb +95 -100
  22. data/examples/07_error_handling_scenarios.rb +4 -2
  23. data/examples/08_entity_addressing_basic.rb +18 -6
  24. data/examples/08_entity_addressing_with_filtering.rb +27 -9
  25. data/examples/09_dead_letter_queue_demo.rb +559 -0
  26. data/examples/09_regex_filtering_microservices.rb +407 -0
  27. data/examples/10_header_block_configuration.rb +263 -0
  28. data/examples/11_global_configuration_example.rb +219 -0
  29. data/examples/README.md +102 -0
  30. data/examples/dead_letters.jsonl +12 -0
  31. data/examples/performance_metrics/benchmark_results_ractor_20250818_205603.json +135 -0
  32. data/examples/performance_metrics/benchmark_results_ractor_20250818_205831.json +135 -0
  33. data/examples/performance_metrics/benchmark_results_test_20250818_204942.json +130 -0
  34. data/examples/performance_metrics/benchmark_results_threadpool_20250818_204942.json +130 -0
  35. data/examples/performance_metrics/benchmark_results_threadpool_20250818_204959.json +130 -0
  36. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205044.json +130 -0
  37. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205109.json +130 -0
  38. data/examples/performance_metrics/benchmark_results_threadpool_20250818_205252.json +130 -0
  39. data/examples/performance_metrics/benchmark_results_unknown_20250819_172852.json +130 -0
  40. data/examples/performance_metrics/compare_benchmarks.rb +519 -0
  41. data/examples/performance_metrics/dead_letters.jsonl +3100 -0
  42. data/examples/performance_metrics/performance_benchmark.rb +344 -0
  43. data/examples/show_logger.rb +367 -0
  44. data/examples/show_me.rb +145 -0
  45. data/examples/temp.txt +94 -0
  46. data/examples/tmux_chat/bot_agent.rb +4 -2
  47. data/examples/tmux_chat/human_agent.rb +4 -2
  48. data/examples/tmux_chat/room_monitor.rb +4 -2
  49. data/examples/tmux_chat/shared_chat_system.rb +6 -3
  50. data/lib/smart_message/addressing.rb +259 -0
  51. data/lib/smart_message/base.rb +121 -599
  52. data/lib/smart_message/circuit_breaker.rb +2 -1
  53. data/lib/smart_message/configuration.rb +199 -0
  54. data/lib/smart_message/dead_letter_queue.rb +27 -10
  55. data/lib/smart_message/dispatcher.rb +90 -49
  56. data/lib/smart_message/header.rb +5 -0
  57. data/lib/smart_message/logger/base.rb +21 -1
  58. data/lib/smart_message/logger/default.rb +88 -138
  59. data/lib/smart_message/logger/lumberjack.rb +324 -0
  60. data/lib/smart_message/logger/null.rb +81 -0
  61. data/lib/smart_message/logger.rb +17 -9
  62. data/lib/smart_message/messaging.rb +100 -0
  63. data/lib/smart_message/plugins.rb +132 -0
  64. data/lib/smart_message/serializer/base.rb +25 -8
  65. data/lib/smart_message/serializer/json.rb +5 -4
  66. data/lib/smart_message/subscription.rb +193 -0
  67. data/lib/smart_message/transport/base.rb +72 -41
  68. data/lib/smart_message/transport/memory_transport.rb +7 -5
  69. data/lib/smart_message/transport/redis_transport.rb +15 -45
  70. data/lib/smart_message/transport/stdout_transport.rb +18 -8
  71. data/lib/smart_message/transport.rb +1 -34
  72. data/lib/smart_message/utilities.rb +142 -0
  73. data/lib/smart_message/version.rb +1 -1
  74. data/lib/smart_message/versioning.rb +85 -0
  75. data/lib/smart_message/wrapper.rb.bak +132 -0
  76. data/lib/smart_message.rb +74 -28
  77. data/smart_message.gemspec +3 -0
  78. metadata +76 -3
  79. data/lib/smart_message/serializer.rb +0 -10
  80. 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
- from 'service-a'
95
- to 'service-b'
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 for this instance
140
+ # Override addressing using method chaining
101
141
  message = FlexibleMessage.new(data: "test")
102
142
  message.from('different-sender')
103
- message.to('different-recipient')
104
- message.reply_to('different-reply-service')
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
- # Class defaults remain unchanged
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
- from 'sample-service'
267
- to 'target-service'
268
- reply_to 'callback-service'
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