smart_message 0.0.10 → 0.0.12

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/deploy-github-pages.yml +38 -0
  3. data/.gitignore +5 -0
  4. data/CHANGELOG.md +30 -0
  5. data/Gemfile.lock +35 -4
  6. data/README.md +169 -71
  7. data/Rakefile +29 -4
  8. data/docs/assets/images/ddq_architecture.svg +130 -0
  9. data/docs/assets/images/dlq_architecture.svg +115 -0
  10. data/docs/assets/images/enhanced-dual-publishing.svg +136 -0
  11. data/docs/assets/images/enhanced-fluent-api.svg +149 -0
  12. data/docs/assets/images/enhanced-microservices-routing.svg +115 -0
  13. data/docs/assets/images/enhanced-pattern-matching.svg +107 -0
  14. data/docs/assets/images/fluent-api-demo.svg +59 -0
  15. data/docs/assets/images/performance-comparison.svg +161 -0
  16. data/docs/assets/images/redis-basic-architecture.svg +53 -0
  17. data/docs/assets/images/redis-enhanced-architecture.svg +88 -0
  18. data/docs/assets/images/redis-queue-architecture.svg +101 -0
  19. data/docs/assets/images/smart_message.jpg +0 -0
  20. data/docs/assets/images/smart_message_walking.jpg +0 -0
  21. data/docs/assets/images/smartmessage_architecture_overview.svg +173 -0
  22. data/docs/assets/images/transport-comparison-matrix.svg +171 -0
  23. data/docs/assets/javascripts/mathjax.js +17 -0
  24. data/docs/assets/stylesheets/extra.css +51 -0
  25. data/docs/{addressing.md → core-concepts/addressing.md} +5 -7
  26. data/docs/{architecture.md → core-concepts/architecture.md} +78 -138
  27. data/docs/{dispatcher.md → core-concepts/dispatcher.md} +21 -21
  28. data/docs/{message_filtering.md → core-concepts/message-filtering.md} +2 -3
  29. data/docs/{message_processing.md → core-concepts/message-processing.md} +17 -17
  30. data/docs/{troubleshooting.md → development/troubleshooting.md} +7 -7
  31. data/docs/{examples.md → getting-started/examples.md} +115 -89
  32. data/docs/{getting-started.md → getting-started/quick-start.md} +47 -18
  33. data/docs/guides/redis-queue-getting-started.md +697 -0
  34. data/docs/guides/redis-queue-patterns.md +889 -0
  35. data/docs/guides/redis-queue-production.md +1091 -0
  36. data/docs/index.md +64 -0
  37. data/docs/{dead_letter_queue.md → reference/dead-letter-queue.md} +2 -3
  38. data/docs/{logging.md → reference/logging.md} +1 -1
  39. data/docs/{message_deduplication.md → reference/message-deduplication.md} +1 -0
  40. data/docs/{proc_handlers_summary.md → reference/proc-handlers.md} +7 -6
  41. data/docs/{serializers.md → reference/serializers.md} +3 -5
  42. data/docs/{transports.md → reference/transports.md} +133 -11
  43. data/docs/transports/memory-transport.md +374 -0
  44. data/docs/transports/redis-enhanced-transport.md +524 -0
  45. data/docs/transports/redis-queue-transport.md +1304 -0
  46. data/docs/transports/redis-transport-comparison.md +496 -0
  47. data/docs/transports/redis-transport.md +509 -0
  48. data/examples/README.md +98 -5
  49. data/examples/city_scenario/911_emergency_call_flow.svg +99 -0
  50. data/examples/city_scenario/README.md +515 -0
  51. data/examples/city_scenario/ai_visitor_intelligence_flow.svg +108 -0
  52. data/examples/city_scenario/citizen.rb +195 -0
  53. data/examples/city_scenario/city_diagram.svg +125 -0
  54. data/examples/city_scenario/common/health_monitor.rb +80 -0
  55. data/examples/city_scenario/common/logger.rb +30 -0
  56. data/examples/city_scenario/emergency_dispatch_center.rb +270 -0
  57. data/examples/city_scenario/fire_department.rb +446 -0
  58. data/examples/city_scenario/fire_emergency_flow.svg +95 -0
  59. data/examples/city_scenario/health_department.rb +100 -0
  60. data/examples/city_scenario/health_monitoring_system.svg +130 -0
  61. data/examples/city_scenario/house.rb +244 -0
  62. data/examples/city_scenario/local_bank.rb +217 -0
  63. data/examples/city_scenario/messages/emergency_911_message.rb +81 -0
  64. data/examples/city_scenario/messages/emergency_resolved_message.rb +43 -0
  65. data/examples/city_scenario/messages/fire_dispatch_message.rb +43 -0
  66. data/examples/city_scenario/messages/fire_emergency_message.rb +45 -0
  67. data/examples/city_scenario/messages/health_check_message.rb +22 -0
  68. data/examples/city_scenario/messages/health_status_message.rb +35 -0
  69. data/examples/city_scenario/messages/police_dispatch_message.rb +46 -0
  70. data/examples/city_scenario/messages/silent_alarm_message.rb +38 -0
  71. data/examples/city_scenario/police_department.rb +316 -0
  72. data/examples/city_scenario/redis_monitor.rb +129 -0
  73. data/examples/city_scenario/redis_stats.rb +743 -0
  74. data/examples/city_scenario/room_for_improvement.md +240 -0
  75. data/examples/city_scenario/security_emergency_flow.svg +95 -0
  76. data/examples/city_scenario/service_internal_architecture.svg +154 -0
  77. data/examples/city_scenario/smart_message_ai_agent.rb +364 -0
  78. data/examples/city_scenario/start_demo.sh +236 -0
  79. data/examples/city_scenario/stop_demo.sh +106 -0
  80. data/examples/city_scenario/visitor.rb +631 -0
  81. data/examples/{10_message_deduplication.rb → memory/01_message_deduplication_demo.rb} +1 -1
  82. data/examples/{09_dead_letter_queue_demo.rb → memory/02_dead_letter_queue_demo.rb} +13 -40
  83. data/examples/{01_point_to_point_orders.rb → memory/03_point_to_point_orders.rb} +1 -1
  84. data/examples/{02_publish_subscribe_events.rb → memory/04_publish_subscribe_events.rb} +2 -2
  85. data/examples/{03_many_to_many_chat.rb → memory/05_many_to_many_chat.rb} +4 -4
  86. data/examples/{show_me.rb → memory/06_pretty_print_demo.rb} +1 -1
  87. data/examples/{05_proc_handlers.rb → memory/07_proc_handlers_demo.rb} +2 -2
  88. data/examples/{06_custom_logger_example.rb → memory/08_custom_logger_demo.rb} +17 -14
  89. data/examples/{07_error_handling_scenarios.rb → memory/09_error_handling_demo.rb} +4 -4
  90. data/examples/{08_entity_addressing_basic.rb → memory/10_entity_addressing_basic.rb} +8 -8
  91. data/examples/{08_entity_addressing_with_filtering.rb → memory/11_entity_addressing_with_filtering.rb} +6 -6
  92. data/examples/{09_regex_filtering_microservices.rb → memory/12_regex_filtering_microservices.rb} +2 -2
  93. data/examples/{10_header_block_configuration.rb → memory/13_header_block_configuration.rb} +6 -6
  94. data/examples/{11_global_configuration_example.rb → memory/14_global_configuration_demo.rb} +19 -8
  95. data/examples/{show_logger.rb → memory/15_logger_demo.rb} +1 -1
  96. data/examples/memory/README.md +163 -0
  97. data/examples/memory/memory_transport_architecture.svg +90 -0
  98. data/examples/memory/point_to_point_pattern.svg +94 -0
  99. data/examples/memory/publish_subscribe_pattern.svg +125 -0
  100. data/examples/{04_redis_smart_home_iot.rb → redis/01_smart_home_iot_demo.rb} +5 -5
  101. data/examples/redis/README.md +230 -0
  102. data/examples/redis/alert_system_flow.svg +127 -0
  103. data/examples/redis/dashboard_status_flow.svg +107 -0
  104. data/examples/redis/device_command_flow.svg +113 -0
  105. data/examples/redis/redis_transport_architecture.svg +115 -0
  106. data/examples/{smart_home_iot_dataflow.md → redis/smart_home_iot_dataflow.md} +4 -116
  107. data/examples/redis/smart_home_system_architecture.svg +133 -0
  108. data/examples/redis_enhanced/README.md +319 -0
  109. data/examples/redis_enhanced/enhanced_01_basic_patterns.rb +233 -0
  110. data/examples/redis_enhanced/enhanced_02_fluent_api.rb +331 -0
  111. data/examples/redis_enhanced/enhanced_03_dual_publishing.rb +281 -0
  112. data/examples/redis_enhanced/enhanced_04_advanced_routing.rb +419 -0
  113. data/examples/redis_queue/01_basic_messaging.rb +221 -0
  114. data/examples/redis_queue/01_comprehensive_examples.rb +508 -0
  115. data/examples/redis_queue/02_pattern_routing.rb +405 -0
  116. data/examples/redis_queue/03_fluent_api.rb +422 -0
  117. data/examples/redis_queue/04_load_balancing.rb +486 -0
  118. data/examples/redis_queue/05_microservices.rb +735 -0
  119. data/examples/redis_queue/06_emergency_alerts.rb +777 -0
  120. data/examples/redis_queue/07_queue_management.rb +587 -0
  121. data/examples/redis_queue/README.md +366 -0
  122. data/examples/redis_queue/enhanced_01_basic_patterns.rb +233 -0
  123. data/examples/redis_queue/enhanced_02_fluent_api.rb +331 -0
  124. data/examples/redis_queue/enhanced_03_dual_publishing.rb +281 -0
  125. data/examples/redis_queue/enhanced_04_advanced_routing.rb +419 -0
  126. data/examples/redis_queue/redis_queue_architecture.svg +148 -0
  127. data/ideas/README.md +41 -0
  128. data/ideas/agents.md +1001 -0
  129. data/ideas/database_transport.md +980 -0
  130. data/ideas/improvement.md +359 -0
  131. data/ideas/meshage.md +1788 -0
  132. data/ideas/message_discovery.md +178 -0
  133. data/ideas/message_schema.md +1381 -0
  134. data/lib/smart_message/.idea/.gitignore +8 -0
  135. data/lib/smart_message/.idea/markdown.xml +6 -0
  136. data/lib/smart_message/.idea/misc.xml +4 -0
  137. data/lib/smart_message/.idea/modules.xml +8 -0
  138. data/lib/smart_message/.idea/smart_message.iml +16 -0
  139. data/lib/smart_message/.idea/vcs.xml +6 -0
  140. data/lib/smart_message/addressing.rb +15 -0
  141. data/lib/smart_message/base.rb +0 -2
  142. data/lib/smart_message/configuration.rb +1 -1
  143. data/lib/smart_message/logger.rb +15 -4
  144. data/lib/smart_message/plugins.rb +5 -2
  145. data/lib/smart_message/serializer.rb +14 -0
  146. data/lib/smart_message/transport/redis_enhanced_transport.rb +399 -0
  147. data/lib/smart_message/transport/redis_queue_transport.rb +555 -0
  148. data/lib/smart_message/transport/registry.rb +1 -0
  149. data/lib/smart_message/transport.rb +34 -1
  150. data/lib/smart_message/version.rb +1 -1
  151. data/lib/smart_message.rb +5 -52
  152. data/mkdocs.yml +184 -0
  153. data/p2p_plan.md +326 -0
  154. data/p2p_roadmap.md +287 -0
  155. data/smart_message.gemspec +2 -0
  156. data/smart_message.svg +51 -0
  157. metadata +170 -44
  158. data/docs/README.md +0 -57
  159. data/examples/dead_letters.jsonl +0 -12
  160. data/examples/temp.txt +0 -94
  161. data/examples/tmux_chat/README.md +0 -283
  162. data/examples/tmux_chat/bot_agent.rb +0 -278
  163. data/examples/tmux_chat/human_agent.rb +0 -199
  164. data/examples/tmux_chat/room_monitor.rb +0 -160
  165. data/examples/tmux_chat/shared_chat_system.rb +0 -328
  166. data/examples/tmux_chat/start_chat_demo.sh +0 -190
  167. data/examples/tmux_chat/stop_chat_demo.sh +0 -22
  168. /data/docs/{properties.md → core-concepts/properties.md} +0 -0
  169. /data/docs/{ideas_to_think_about.md → development/ideas.md} +0 -0
data/README.md CHANGED
@@ -1,13 +1,29 @@
1
+ <table border="0">
2
+ <tr>
3
+ <td width="30%" valign="top">
4
+
5
+ <img src="docs/assets/images/smart_message.jpg" alt="SmartMessage Logo" />
6
+ <br/>
7
+ See <a href="https://madbomber.github.io/smart_message/">Documentation Websit</a>
8
+ </td>
9
+ <td width="70%" valign="top">
10
+
1
11
  # SmartMessage
2
12
 
3
- [![Gem Version](https://badge.fury.io/rb/smart_message.svg)](https://badge.fury.io/rb/smart_message)
4
- [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-ruby.svg)](https://www.ruby-lang.org/en/)
13
+ Can Walk, Talk, and Think at the Same Time
14
+
15
+ **SmartMessage** is a powerful Ruby framework that transforms ordinary messages into intelligent, self-aware entities capable of routing themselves, validating their contents, and executing business logic. By abstracting away the complexities of transport mechanisms (Redis, RabbitMQ, Kafka) and serialization formats (JSON, MessagePack), SmartMessage lets you focus on what matters: your business logic.
5
16
 
6
- SmartMessage is a message abstraction framework that decouples business logic from message transports and serialization formats. Much like ActiveRecord abstracts models from database implementations, SmartMessage abstracts messages from their backend transport and serialization mechanisms.
17
+ Think of SmartMessage as ActiveRecord for messaging - just as ActiveRecord frees you from database-specific SQL, SmartMessage liberates your messages from transport-specific implementations. Each message knows how to validate itself, where it came from, where it's going, and what to do when it arrives. With built-in support for filtering, versioning, deduplication, and concurrent processing, SmartMessage provides enterprise-grade messaging capabilities with the simplicity Ruby developers love.
18
+
19
+ </td>
20
+ </tr>
21
+ </table>
7
22
 
8
23
  ## Features
9
24
 
10
25
  - **Transport Abstraction**: Plugin architecture supporting multiple message transports (Redis, RabbitMQ, Kafka, etc.)
26
+ - **🌟 Redis Queue Transport**: Advanced transport with RabbitMQ-style routing patterns, persistent FIFO queues, load balancing, and 10x faster performance than traditional message brokers. Built on Ruby's Async framework for fiber-based concurrency supporting thousands of concurrent subscriptions - [see full documentation](docs/transports/redis-queue.md)
11
27
  - **Serialization Flexibility**: Pluggable serialization formats (JSON, MessagePack, etc.)
12
28
  - **Entity-to-Entity Addressing**: Built-in FROM/TO/REPLY_TO addressing for point-to-point and broadcast messaging patterns
13
29
  - **Advanced Message Filtering**: Filter subscriptions using exact strings, regular expressions, or mixed arrays for precise message routing
@@ -16,7 +32,7 @@ SmartMessage is a message abstraction framework that decouples business logic fr
16
32
  - **Message Documentation**: Built-in documentation support for message classes and properties with automatic defaults
17
33
  - **Flexible Message Handlers**: Multiple subscription patterns - default methods, custom methods, blocks, procs, and lambdas
18
34
  - **Dual-Level Configuration**: Class and instance-level plugin overrides for gateway patterns
19
- - **Concurrent Processing**: Thread-safe message routing using `Concurrent::CachedThreadPool`
35
+ - **Concurrent Processing**: Thread-safe message routing using `Concurrent::CachedThreadPool` with Async/Fiber-based Redis Queue Transport for massive scalability
20
36
  - **Advanced Logging System**: Comprehensive logging with colorized console output, JSON structured logging, and file rolling
21
37
  - **Built-in Statistics**: Message processing metrics and monitoring
22
38
  - **Message Deduplication**: Handler-scoped deduplication queues (DDQ) with memory or Redis storage for preventing duplicate message processing
@@ -35,78 +51,106 @@ gem 'smart_message'
35
51
 
36
52
  And then execute:
37
53
 
38
- $ bundle install
54
+ bundle install
39
55
 
40
56
  Or install it yourself as:
41
57
 
42
- $ gem install smart_message
58
+ gem install smart_message
59
+
60
+ ### Redis Transport Setup
61
+
62
+ To use the built-in Redis transport, you'll need to have Redis server installed:
63
+
64
+ **macOS:**
65
+ ```bash
66
+ brew install redis
67
+ brew services start redis # To start Redis as a service
68
+ ```
69
+
70
+ **Ubuntu/Debian:**
71
+ ```bash
72
+ sudo apt-get update
73
+ sudo apt-get install redis-server
74
+ ```
75
+
76
+ **CentOS/RHEL/Fedora:**
77
+ ```bash
78
+ sudo yum install redis
79
+ sudo systemctl start redis
80
+ ```
43
81
 
44
82
  ## Quick Start
45
83
 
46
84
  ### 1. Define a Message Class
47
85
 
48
86
  ```ruby
87
+ require 'smart_message'
88
+
49
89
  class OrderMessage < SmartMessage::Base
50
90
  # Declare schema version for compatibility tracking
51
91
  version 2
52
-
92
+
53
93
  # Add a description for the message class
54
94
  description "Represents customer order data for processing and fulfillment"
55
-
95
+
56
96
  # Configure entity addressing (Method 1: Direct methods)
57
97
  from 'order-service'
58
98
  to 'fulfillment-service' # Point-to-point message
59
99
  reply_to 'order-service' # Responses come back here
60
-
100
+
61
101
  # Alternative Method 2: Using header block
62
102
  # header do
63
103
  # from 'order-service'
64
104
  # to 'fulfillment-service'
65
105
  # reply_to 'order-service'
66
106
  # end
67
-
107
+
68
108
  # Required properties with validation
69
- property :order_id,
109
+ property :order_id,
70
110
  required: true,
71
111
  message: "Order ID is required",
72
112
  validate: ->(v) { v.is_a?(String) && v.length > 0 },
73
113
  validation_message: "Order ID must be a non-empty string",
74
114
  description: "Unique order identifier"
75
-
76
- property :customer_id,
115
+
116
+ property :customer_id,
77
117
  required: true,
78
118
  message: "Customer ID is required",
79
119
  description: "Customer's unique ID"
80
-
81
- property :amount,
120
+
121
+ property :amount,
82
122
  required: true,
83
123
  message: "Amount is required",
84
124
  validate: ->(v) { v.is_a?(Numeric) && v > 0 },
85
125
  validation_message: "Amount must be a positive number",
86
126
  description: "Total order amount in dollars"
87
-
88
- property :items,
127
+
128
+ property :items,
89
129
  default: [],
90
130
  description: "Array of ordered items"
91
131
 
92
132
  # Configure transport and serializer at class level
93
133
  config do
134
+ # Option 1: Simple STDOUT for development
94
135
  transport SmartMessage::Transport.create(:stdout, loopback: true)
136
+
137
+ # Option 2: Redis Queue for production (10x faster than RabbitMQ!)
138
+ # transport SmartMessage::Transport.create(:redis_queue,
139
+ # url: 'redis://localhost:6379',
140
+ # queue_prefix: 'myapp'
141
+ # )
142
+
95
143
  serializer SmartMessage::Serializer::JSON.new
96
144
  end
97
145
 
98
146
  # Business logic for processing received messages
99
- def self.process(message_header, message_payload)
100
- # Decode the message
101
- order_data = JSON.parse(message_payload)
102
- order = new(order_data)
103
-
104
- # Process the order
105
- puts "Processing order #{order.order_id} for customer #{order.customer_id}"
106
- puts "Amount: $#{order.amount}"
107
-
147
+ def self.process(message_instance)
148
+ # Message instance is already decoded and validated
149
+ puts "Processing order #{message_instance.order_id} for customer #{message_instance.customer_id}"
150
+ puts "Amount: $#{message_instance.amount}"
151
+
108
152
  # Your business logic here
109
- process_order(order)
153
+ process_order(message_instance)
110
154
  end
111
155
 
112
156
  private
@@ -123,7 +167,7 @@ end
123
167
  # Create and publish a message (automatically validated before publishing)
124
168
  order = OrderMessage.new(
125
169
  order_id: "ORD-123",
126
- customer_id: "CUST-456",
170
+ customer_id: "CUST-456",
127
171
  amount: 99.99,
128
172
  items: ["Widget A", "Widget B"]
129
173
  )
@@ -152,20 +196,23 @@ OrderMessage.subscribe
152
196
  OrderMessage.subscribe("PaymentService.process_order")
153
197
 
154
198
  # 3. Block handler (NEW!)
155
- OrderMessage.subscribe do |header, payload|
199
+ OrderMessage.subscribe do |wrapper|
200
+ header, payload = wrapper.split
156
201
  order_data = JSON.parse(payload)
157
202
  puts "Quick processing: Order #{order_data['order_id']}"
158
203
  end
159
204
 
160
205
  # 4. Proc handler (NEW!)
161
- order_processor = proc do |header, payload|
206
+ order_processor = proc do |wrapper|
207
+ header, payload = wrapper.split
162
208
  order_data = JSON.parse(payload)
163
209
  EmailService.send_confirmation(order_data['customer_id'])
164
210
  end
165
211
  OrderMessage.subscribe(order_processor)
166
212
 
167
213
  # 5. Lambda handler (NEW!)
168
- audit_handler = lambda do |header, payload|
214
+ audit_handler = lambda do |wrapper|
215
+ header, payload = wrapper.split
169
216
  AuditLog.record("Order processed at #{header.published_at}")
170
217
  end
171
218
  OrderMessage.subscribe(audit_handler)
@@ -193,7 +240,7 @@ OrderMessage.subscribe(to: /^(dev|staging)-.*/)
193
240
 
194
241
  # Combined filtering
195
242
  OrderMessage.subscribe(
196
- from: /^admin-.*/,
243
+ from: /^admin-.*/,
197
244
  to: ['order-service', /^fulfillment-.*/]
198
245
  )
199
246
 
@@ -213,16 +260,16 @@ class OrderMessage < SmartMessage::Base
213
260
  version 1
214
261
  property :order_id, required: true
215
262
  property :amount, required: true
216
-
263
+
217
264
  from "order-service"
218
-
265
+
219
266
  # Configure deduplication
220
267
  ddq_size 100 # Track last 100 message UUIDs
221
268
  ddq_storage :memory # Use memory storage (or :redis for distributed)
222
269
  enable_deduplication! # Enable deduplication for this message class
223
-
224
- def self.process(message)
225
- puts "Processing order: #{message.order_id}"
270
+
271
+ def self.process(message_instance)
272
+ puts "Processing order: #{message_instance.order_id}"
226
273
  # Business logic here
227
274
  end
228
275
  end
@@ -309,7 +356,7 @@ class PaymentMessage < SmartMessage::Base
309
356
  from 'payment-service' # Required: sender identity
310
357
  to 'bank-gateway' # Optional: specific recipient
311
358
  reply_to 'payment-service' # Optional: where responses go
312
-
359
+
313
360
  property :amount, required: true
314
361
  property :account_id, required: true
315
362
  end
@@ -319,14 +366,14 @@ end
319
366
  ```ruby
320
367
  class PaymentMessage < SmartMessage::Base
321
368
  version 1
322
-
369
+
323
370
  # Configure all addressing in a single block
324
371
  header do
325
372
  from 'payment-service'
326
373
  to 'bank-gateway'
327
374
  reply_to 'payment-service'
328
375
  end
329
-
376
+
330
377
  property :amount, required: true
331
378
  property :account_id, required: true
332
379
  end
@@ -364,13 +411,13 @@ payment.publish
364
411
  ```ruby
365
412
  class SystemAnnouncementMessage < SmartMessage::Base
366
413
  version 1
367
-
414
+
368
415
  # Using header block for broadcast configuration
369
416
  header do
370
417
  from 'admin-service' # Required: sender identity
371
418
  # No 'to' field = broadcast to all subscribers
372
419
  end
373
-
420
+
374
421
  property :message, required: true
375
422
  property :priority, default: 'normal'
376
423
  end
@@ -379,7 +426,7 @@ end
379
426
  #### Messaging Patterns Supported
380
427
 
381
428
  - **Point-to-Point**: Set `to` field for direct entity targeting
382
- - **Broadcast**: Omit `to` field (nil) for message broadcast to all subscribers
429
+ - **Broadcast**: Omit `to` field (nil) for message broadcast to all subscribers
383
430
  - **Request-Reply**: Use `reply_to` field to specify response routing
384
431
  - **Gateway Patterns**: Override addressing at instance level for message forwarding
385
432
 
@@ -433,9 +480,9 @@ SmartMessage.configure do |config|
433
480
  end
434
481
 
435
482
  logger = SmartMessage.configuration.default_logger
436
- logger.info("User action",
437
- user_id: 12345,
438
- action: "login",
483
+ logger.info("User action",
484
+ user_id: 12345,
485
+ action: "login",
439
486
  ip_address: "192.168.1.1")
440
487
  # Output: {"timestamp":"2025-01-15T10:30:45.123Z","level":"INFO","message":"User action","user_id":12345,"action":"login","ip_address":"192.168.1.1","source":"app.rb:42:in `authenticate`"}
441
488
  ```
@@ -449,7 +496,7 @@ SmartMessage.configure do |config|
449
496
  roll_by_size: true,
450
497
  max_file_size: 10 * 1024 * 1024, # 10 MB
451
498
  keep_files: 5, # Keep 5 old files
452
-
499
+
453
500
  # Date-based rolling (alternative to size-based)
454
501
  roll_by_date: false, # Set to true for date-based
455
502
  date_pattern: '%Y-%m-%d' # Daily rolling pattern
@@ -465,11 +512,11 @@ SmartMessage classes automatically use the configured logger:
465
512
  class OrderMessage < SmartMessage::Base
466
513
  property :order_id, required: true
467
514
  property :amount, required: true
468
-
515
+
469
516
  def process
470
517
  # Logger is automatically available
471
- logger.info("Processing order",
472
- order_id: order_id,
518
+ logger.info("Processing order",
519
+ order_id: order_id,
473
520
  amount: amount,
474
521
  header: _sm_header.to_h,
475
522
  payload: _sm_payload)
@@ -539,6 +586,57 @@ This enables gateway patterns where messages can be received from one transport/
539
586
 
540
587
  ## Transport Implementations
541
588
 
589
+ ### Redis Queue Transport (Featured) 🌟
590
+
591
+ The Redis Queue Transport provides enterprise-grade message routing with exceptional performance:
592
+
593
+ ```ruby
594
+ # Configure with RabbitMQ-style routing
595
+ transport = SmartMessage::Transport.create(:redis_queue,
596
+ url: 'redis://localhost:6379',
597
+ queue_prefix: 'myapp',
598
+ consumer_group: 'workers'
599
+ )
600
+
601
+ # Pattern-based subscriptions (RabbitMQ compatible)
602
+ transport.subscribe_pattern("#.*.payment_service") # All messages TO payment_service
603
+ transport.subscribe_pattern("#.api_gateway.*") # All messages FROM api_gateway
604
+ transport.subscribe_pattern("order.#.*.*") # All order messages
605
+
606
+ # Fluent API for complex routing
607
+ transport.where
608
+ .from('web_app')
609
+ .to('analytics')
610
+ .consumer_group('analytics_workers')
611
+ .subscribe
612
+
613
+ # Configure message class
614
+ class OrderMessage < SmartMessage::Base
615
+ transport :redis_queue
616
+
617
+ property :order_id, required: true
618
+ property :amount, required: true
619
+ end
620
+
621
+ # Publish with enhanced routing
622
+ OrderMessage.new(
623
+ order_id: 'ORD-001',
624
+ amount: 99.99,
625
+ _sm_header: { from: 'api_gateway', to: 'payment_service' }
626
+ ).publish
627
+ ```
628
+
629
+ **Key Features:**
630
+ - 10x faster than RabbitMQ (0.5ms vs 5ms latency)
631
+ - Pattern routing with `#` and `*` wildcards
632
+ - Persistent FIFO queues using Redis Lists
633
+ - Load balancing via consumer groups
634
+ - Enhanced routing keys: `namespace.type.from.to`
635
+ - Queue monitoring and management
636
+ - Production-ready with circuit breakers and dead letter queues
637
+
638
+ 📚 **Full Documentation:** [Redis Queue Transport Guide](docs/transports/redis-queue.md) | [Getting Started](docs/guides/redis-queue-getting-started.md) | [Examples](examples/redis_queue/)
639
+
542
640
  ### STDOUT Transport (Development)
543
641
 
544
642
  ```ruby
@@ -571,7 +669,7 @@ transport.process_all # Process all pending messages
571
669
 
572
670
  ```ruby
573
671
  # Basic Redis configuration
574
- transport = SmartMessage::Transport.create(:redis,
672
+ transport = SmartMessage::Transport.create(:redis,
575
673
  url: 'redis://localhost:6379',
576
674
  db: 0
577
675
  )
@@ -606,7 +704,7 @@ The Redis transport uses the message class name as the Redis channel name, enabl
606
704
  ```ruby
607
705
  class WebhookTransport < SmartMessage::Transport::Base
608
706
  def default_options
609
- {
707
+ {
610
708
  webhook_url: "https://api.example.com/webhooks",
611
709
  timeout: 30,
612
710
  retries: 3
@@ -621,19 +719,19 @@ class WebhookTransport < SmartMessage::Transport::Base
621
719
  def publish(message_header, message_payload)
622
720
  http = Net::HTTP.new(@uri.host, @uri.port)
623
721
  http.use_ssl = @uri.scheme == 'https'
624
-
722
+
625
723
  request = Net::HTTP::Post.new(@uri)
626
724
  request['Content-Type'] = 'application/json'
627
725
  request['X-Message-Class'] = message_header.message_class
628
726
  request.body = message_payload
629
-
727
+
630
728
  response = http.request(request)
631
729
  raise "Webhook failed: #{response.code}" unless response.code.to_i < 400
632
730
  end
633
731
 
634
732
  def subscribe(message_class, process_method)
635
733
  super
636
- # For webhooks, subscription would typically be configured
734
+ # For webhooks, subscription would typically be configured
637
735
  # externally on the webhook provider's side
638
736
  end
639
737
  end
@@ -643,7 +741,7 @@ SmartMessage::Transport.register(:webhook, WebhookTransport)
643
741
 
644
742
  # Use the transport
645
743
  MyMessage.config do
646
- transport SmartMessage::Transport.create(:webhook,
744
+ transport SmartMessage::Transport.create(:webhook,
647
745
  webhook_url: "https://api.myservice.com/messages"
648
746
  )
649
747
  end
@@ -674,7 +772,7 @@ Declare your message schema version using the `version` class method:
674
772
  ```ruby
675
773
  class OrderMessage < SmartMessage::Base
676
774
  version 2 # Schema version 2
677
-
775
+
678
776
  property :order_id, required: true
679
777
  property :customer_email # Added in version 2
680
778
  end
@@ -687,22 +785,22 @@ Properties support multiple validation types with custom error messages:
687
785
  ```ruby
688
786
  class UserMessage < SmartMessage::Base
689
787
  version 1
690
-
788
+
691
789
  # Required field validation (Hashie built-in)
692
- property :user_id,
790
+ property :user_id,
693
791
  required: true,
694
792
  message: "User ID is required and cannot be blank"
695
-
793
+
696
794
  # Custom validation with lambda
697
795
  property :age,
698
796
  validate: ->(v) { v.is_a?(Integer) && v.between?(1, 120) },
699
797
  validation_message: "Age must be an integer between 1 and 120"
700
-
798
+
701
799
  # Email validation with regex
702
800
  property :email,
703
801
  validate: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i,
704
802
  validation_message: "Must be a valid email address"
705
-
803
+
706
804
  # Inclusion validation with array
707
805
  property :status,
708
806
  validate: ['active', 'inactive', 'pending'],
@@ -780,20 +878,20 @@ Use the `description` DSL method to document what your message class represents:
780
878
  ```ruby
781
879
  class OrderMessage < SmartMessage::Base
782
880
  description "Represents customer order data for processing and fulfillment"
783
-
881
+
784
882
  property :order_id, required: true
785
883
  property :amount, required: true
786
884
  end
787
885
 
788
- class UserMessage < SmartMessage::Base
886
+ class UserMessage < SmartMessage::Base
789
887
  description "Handles user management operations including registration and updates"
790
-
888
+
791
889
  property :user_id, required: true
792
890
  property :email, required: true
793
891
  end
794
892
 
795
893
  # Access descriptions
796
- puts OrderMessage.description
894
+ puts OrderMessage.description
797
895
  # => "Represents customer order data for processing and fulfillment"
798
896
 
799
897
  puts UserMessage.description
@@ -814,7 +912,7 @@ class MyMessage < SmartMessage::Base
814
912
  property :data
815
913
  end
816
914
 
817
- puts MyMessage.description
915
+ puts MyMessage.description
818
916
  # => "MyMessage is a SmartMessage"
819
917
  ```
820
918
 
@@ -825,10 +923,10 @@ Combine class descriptions with property descriptions for comprehensive document
825
923
  ```ruby
826
924
  class FullyDocumented < SmartMessage::Base
827
925
  description "A fully documented message class for demonstration purposes"
828
-
829
- property :id,
926
+
927
+ property :id,
830
928
  description: "Unique identifier for the record"
831
- property :name,
929
+ property :name,
832
930
  description: "Display name for the entity"
833
931
  property :status,
834
932
  description: "Current processing status",
@@ -1043,4 +1141,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/MadBom
1043
1141
 
1044
1142
  ## License
1045
1143
 
1046
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
1144
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,10 +1,35 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
4
+ # Main test task - runs all tests with proper environment setup
5
+ task :test do
6
+ ENV['SM_LOGGER_TEST'] = 'true'
7
+
8
+ puts "Running SmartMessage test suite..."
9
+ puts "=" * 40
10
+
11
+ # Check for Redis availability for informational purposes
12
+ begin
13
+ require 'redis'
14
+ redis = Redis.new(url: 'redis://localhost:6379')
15
+ redis.ping
16
+ puts "✅ Redis available - all tests including Redis Queue Transport will run"
17
+ redis.quit
18
+ rescue => e
19
+ puts "⚠️ Redis not available: #{e.message}"
20
+ puts " Redis Queue Transport tests will be skipped automatically"
21
+ end
22
+
23
+ puts ""
24
+
25
+ # Run the actual tests
26
+ Rake::TestTask.new(:run_tests) do |t|
27
+ t.libs << "test"
28
+ t.libs << "lib"
29
+ t.test_files = FileList["test/**/*_test.rb"]
30
+ end
31
+
32
+ Rake::Task[:run_tests].invoke
8
33
  end
9
34
 
10
35
  task :default => :test