smart_message 0.0.9 → 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 (176) 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 +53 -0
  5. data/Gemfile.lock +35 -4
  6. data/README.md +265 -69
  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} +129 -119
  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/reference/message-deduplication.md +489 -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/memory/01_message_deduplication_demo.rb +209 -0
  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 +2 -2
  142. data/lib/smart_message/configuration.rb +1 -1
  143. data/lib/smart_message/ddq/base.rb +71 -0
  144. data/lib/smart_message/ddq/memory.rb +109 -0
  145. data/lib/smart_message/ddq/redis.rb +168 -0
  146. data/lib/smart_message/ddq.rb +31 -0
  147. data/lib/smart_message/deduplication.rb +174 -0
  148. data/lib/smart_message/dispatcher.rb +175 -18
  149. data/lib/smart_message/logger.rb +15 -4
  150. data/lib/smart_message/plugins.rb +5 -2
  151. data/lib/smart_message/serializer.rb +14 -0
  152. data/lib/smart_message/subscription.rb +10 -7
  153. data/lib/smart_message/transport/redis_enhanced_transport.rb +399 -0
  154. data/lib/smart_message/transport/redis_queue_transport.rb +555 -0
  155. data/lib/smart_message/transport/registry.rb +1 -0
  156. data/lib/smart_message/transport.rb +34 -1
  157. data/lib/smart_message/version.rb +1 -1
  158. data/lib/smart_message.rb +5 -52
  159. data/mkdocs.yml +184 -0
  160. data/p2p_plan.md +326 -0
  161. data/p2p_roadmap.md +287 -0
  162. data/smart_message.gemspec +2 -0
  163. data/smart_message.svg +51 -0
  164. metadata +175 -42
  165. data/docs/README.md +0 -57
  166. data/examples/dead_letters.jsonl +0 -12
  167. data/examples/temp.txt +0 -94
  168. data/examples/tmux_chat/README.md +0 -283
  169. data/examples/tmux_chat/bot_agent.rb +0 -278
  170. data/examples/tmux_chat/human_agent.rb +0 -199
  171. data/examples/tmux_chat/room_monitor.rb +0 -160
  172. data/examples/tmux_chat/shared_chat_system.rb +0 -328
  173. data/examples/tmux_chat/start_chat_demo.sh +0 -190
  174. data/examples/tmux_chat/stop_chat_demo.sh +0 -22
  175. /data/docs/{properties.md → core-concepts/properties.md} +0 -0
  176. /data/docs/{ideas_to_think_about.md → development/ideas.md} +0 -0
data/docs/index.md ADDED
@@ -0,0 +1,64 @@
1
+ # SmartMessage Documentation
2
+
3
+ <table border="0">
4
+ <tr>
5
+ <td width="30%" valign="top">
6
+ <img src="assets/images/smart_message.jpg" alt="SmartMessage Logo" width="200" />
7
+ </td>
8
+ <td width="70%" valign="top">
9
+
10
+ <string>SmartMessage</strong> 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.
11
+ <br/><br/>
12
+ 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.
13
+
14
+ </td>
15
+ </tr>
16
+ </table>
17
+
18
+ ## Table of Contents
19
+
20
+ ### Getting Started
21
+ - [Quick Start](getting-started/quick-start.md)
22
+ - [Basic Usage Examples](getting-started/examples.md)
23
+
24
+ ### Core Concepts
25
+ - [Architecture Overview](core-concepts/architecture.md)
26
+ - [Property System](core-concepts/properties.md)
27
+ - [Entity Addressing](core-concepts/addressing.md)
28
+ - [Message Filtering](core-concepts/message-filtering.md)
29
+ - [Message Processing](core-concepts/message-processing.md)
30
+ - [Dispatcher & Routing](core-concepts/dispatcher.md)
31
+
32
+ ### Transports
33
+ - [Transport Layer](reference/transports.md)
34
+ - [Redis Queue Transport](transports/redis-queue-transport.md) ⭐ **Featured**
35
+ - [Redis Transport Comparison](transports/redis-transport-comparison.md)
36
+
37
+ ### Guides
38
+ - [Redis Queue Getting Started](guides/redis-queue-getting-started.md)
39
+ - [Advanced Routing Patterns](guides/redis-queue-patterns.md)
40
+ - [Production Deployment](guides/redis-queue-production.md)
41
+
42
+ ### Reference
43
+ - [Serializers](reference/serializers.md)
44
+ - [Logging System](reference/logging.md)
45
+ - [Dead Letter Queue](reference/dead-letter-queue.md)
46
+ - [Message Deduplication](reference/message-deduplication.md)
47
+ - [Proc Handlers](reference/proc-handlers.md)
48
+
49
+ ### Development
50
+ - [Troubleshooting](development/troubleshooting.md)
51
+ - [Ideas & Roadmap](development/ideas.md)
52
+
53
+ ## Quick Navigation
54
+
55
+ - **New to SmartMessage?** Start with [Quick Start](getting-started/quick-start.md)
56
+ - **Need examples?** Check out [Examples](getting-started/examples.md)
57
+ - **Understanding the architecture?** Read [Architecture Overview](core-concepts/architecture.md)
58
+ - **Having issues?** Visit [Troubleshooting](development/troubleshooting.md)
59
+
60
+ ## Version
61
+
62
+ This documentation is for SmartMessage v0.0.8.
63
+
64
+ For older versions, please check the git tags and corresponding documentation.
@@ -93,10 +93,9 @@ The DLQ operates as a First-In-First-Out queue:
93
93
  ```ruby
94
94
  dlq = SmartMessage::DeadLetterQueue.default
95
95
 
96
- # Add a failed message
96
+ # Add a failed message (accepts decoded message instance)
97
97
  entry = dlq.enqueue(
98
- message_header, # SmartMessage::Header object
99
- message_payload, # Serialized message string
98
+ decoded_message, # SmartMessage::Base instance
100
99
  error: "Connection timeout",
101
100
  retry_count: 0,
102
101
  transport: "Redis",
@@ -505,4 +505,4 @@ logger.info("Test message")
505
505
  assert_includes log_output.string, "Test message"
506
506
  ```
507
507
 
508
- For more information, see the comprehensive logging example at `examples/show_logger.rb`.
508
+ For more information, see the comprehensive logging examples at `examples/memory/15_logger_demo.rb` and `examples/memory/08_custom_logger_demo.rb`.
@@ -0,0 +1,489 @@
1
+
2
+ # Message Deduplication
3
+
4
+ SmartMessage provides a comprehensive message deduplication system using Deduplication Queues (DDQ) to prevent duplicate processing of messages with the same UUID. The system is designed with handler-scoped isolation, ensuring that different message handlers maintain independent deduplication state.
5
+
6
+ ## Overview
7
+
8
+ Message deduplication in SmartMessage works by:
9
+
10
+ 1. **Handler-Scoped Tracking**: Each message handler (subscription) gets its own DDQ instance
11
+ 2. **UUID-Based Detection**: Message UUIDs are tracked in circular buffers for O(1) lookup performance
12
+ 3. **Configurable Storage**: Support for both memory-based and Redis-based storage backends
13
+ 4. **Automatic Integration**: Seamlessly integrates with the existing dispatcher and subscription system
14
+
15
+ ## Architecture
16
+
17
+ ### Handler-Only Scoping
18
+
19
+ The key innovation in SmartMessage's deduplication system is **handler-only scoping**. DDQ keys are automatically derived from the combination of message class and handler method:
20
+
21
+ ```
22
+ DDQ Key Format: "MessageClass:HandlerMethod"
23
+ ```
24
+
25
+ Examples:
26
+ - `"OrderMessage:PaymentService.process"`
27
+ - `"OrderMessage:FulfillmentService.handle"`
28
+ - `"InvoiceMessage:PaymentService.process"`
29
+
30
+ This design provides:
31
+ - **Natural Isolation**: Each handler has its own deduplication context
32
+ - **Cross-Process Support**: Same handler across different processes gets isolated DDQs
33
+ - **No Parameter Pollution**: No need for explicit subscriber identification in the API
34
+
35
+ ### DDQ Data Structure
36
+
37
+ Each DDQ uses a hybrid data structure for optimal performance:
38
+
39
+ ```ruby
40
+ # Hybrid Array + Set Design
41
+ @circular_array = Array.new(size) # Maintains insertion order for eviction
42
+ @lookup_set = Set.new # Provides O(1) UUID lookup
43
+ @index = 0 # Current insertion position
44
+ ```
45
+
46
+ Benefits:
47
+ - **O(1) Lookup**: Set provides constant-time duplicate detection
48
+ - **O(1) Insertion**: Array provides constant-time insertion and eviction
49
+ - **Memory Bounded**: Circular buffer automatically evicts oldest entries
50
+ - **Thread Safe**: Mutex protection for concurrent access
51
+
52
+ ## Configuration
53
+
54
+ ### Basic Setup
55
+
56
+ Enable deduplication for a message class:
57
+
58
+ ```ruby
59
+ class OrderMessage < SmartMessage::Base
60
+ version 1
61
+ property :order_id, required: true
62
+ property :amount, required: true
63
+
64
+ # Configure deduplication
65
+ ddq_size 100 # Track last 100 UUIDs (default: 100)
66
+ ddq_storage :memory # Storage backend (default: :memory)
67
+ enable_deduplication! # Enable DDQ for this message class
68
+
69
+ def self.process(message)
70
+ puts "Processing order: #{message.order_id}"
71
+ end
72
+ end
73
+ ```
74
+
75
+ ### Storage Backends
76
+
77
+ #### Memory Storage
78
+
79
+ Best for single-process applications:
80
+
81
+ ```ruby
82
+ class LocalMessage < SmartMessage::Base
83
+ ddq_size 50
84
+ ddq_storage :memory
85
+ enable_deduplication!
86
+ end
87
+ ```
88
+
89
+ Memory Usage (approximate):
90
+ - 10 UUIDs: ~480 bytes
91
+ - 100 UUIDs: ~4.8 KB
92
+ - 1000 UUIDs: ~48 KB
93
+
94
+ #### Redis Storage
95
+
96
+ Best for distributed/multi-process applications:
97
+
98
+ ```ruby
99
+ class DistributedMessage < SmartMessage::Base
100
+ ddq_size 1000
101
+ ddq_storage :redis,
102
+ redis_url: 'redis://localhost:6379',
103
+ redis_db: 1,
104
+ key_prefix: 'ddq'
105
+ enable_deduplication!
106
+ end
107
+ ```
108
+
109
+ Redis DDQ features:
110
+ - **Distributed State**: Shared across multiple processes
111
+ - **Persistence**: Survives process restarts
112
+ - **TTL Support**: Automatic expiration of old entries
113
+ - **Atomic Operations**: Transaction safety for concurrent access
114
+
115
+ ### Configuration Options
116
+
117
+ | Option | Type | Default | Description |
118
+ |--------|------|---------|-------------|
119
+ | `ddq_size` | Integer | 100 | Maximum UUIDs to track in circular buffer |
120
+ | `ddq_storage` | Symbol | `:memory` | Storage backend (`:memory` or `:redis`) |
121
+ | `redis_url` | String | `'redis://localhost:6379'` | Redis connection URL |
122
+ | `redis_db` | Integer | 0 | Redis database number |
123
+ | `key_prefix` | String | `'ddq'` | Prefix for Redis keys |
124
+ | `ttl` | Integer | 3600 | TTL for Redis entries (seconds) |
125
+
126
+ ## Usage Examples
127
+
128
+ ### Multiple Handlers per Message Class
129
+
130
+ ```ruby
131
+ class OrderMessage < SmartMessage::Base
132
+ ddq_size 200
133
+ ddq_storage :memory
134
+ enable_deduplication!
135
+ end
136
+
137
+ # Each gets separate DDQ tracking
138
+ OrderMessage.subscribe('PaymentService.process') # DDQ: "OrderMessage:PaymentService.process"
139
+ OrderMessage.subscribe('FulfillmentService.handle') # DDQ: "OrderMessage:FulfillmentService.handle"
140
+ OrderMessage.subscribe('AuditService.log_order') # DDQ: "OrderMessage:AuditService.log_order"
141
+
142
+ # Same UUID can be processed by each handler independently
143
+ order = OrderMessage.new(order_id: "12345", amount: 99.99)
144
+ order.publish # All three handlers will process this message
145
+ ```
146
+
147
+ ### Cross-Message-Class Handlers
148
+
149
+ ```ruby
150
+ class PaymentService
151
+ def self.process(message)
152
+ puts "PaymentService processing: #{message.class.name}"
153
+ end
154
+ end
155
+
156
+ # Same handler, different message classes = separate DDQs
157
+ OrderMessage.subscribe('PaymentService.process') # DDQ: "OrderMessage:PaymentService.process"
158
+ InvoiceMessage.subscribe('PaymentService.process') # DDQ: "InvoiceMessage:PaymentService.process"
159
+ RefundMessage.subscribe('PaymentService.process') # DDQ: "RefundMessage:PaymentService.process"
160
+ ```
161
+
162
+ ### Distributed Processing
163
+
164
+ ```ruby
165
+ # Process A (payment-service-1)
166
+ class OrderMessage < SmartMessage::Base
167
+ ddq_storage :redis, redis_url: 'redis://shared-redis:6379'
168
+ enable_deduplication!
169
+ end
170
+
171
+ OrderMessage.subscribe('PaymentService.process')
172
+
173
+ # Process B (payment-service-2)
174
+ # Same configuration, same handler = shared DDQ in Redis
175
+ OrderMessage.subscribe('PaymentService.process')
176
+
177
+ # Only one process will handle each unique UUID
178
+ ```
179
+
180
+ ## API Reference
181
+
182
+ ### Class Methods
183
+
184
+ #### `ddq_size(size)`
185
+ Configure the maximum number of UUIDs to track:
186
+ ```ruby
187
+ OrderMessage.ddq_size(500) # Track last 500 UUIDs
188
+ ```
189
+
190
+ #### `ddq_storage(storage, **options)`
191
+ Configure the storage backend:
192
+ ```ruby
193
+ OrderMessage.ddq_storage(:memory)
194
+ OrderMessage.ddq_storage(:redis, redis_url: 'redis://localhost:6379', redis_db: 2)
195
+ ```
196
+
197
+ #### `enable_deduplication!`
198
+ Enable deduplication for the message class:
199
+ ```ruby
200
+ OrderMessage.enable_deduplication!
201
+ ```
202
+
203
+ #### `disable_deduplication!`
204
+ Disable deduplication for the message class:
205
+ ```ruby
206
+ OrderMessage.disable_deduplication!
207
+ ```
208
+
209
+ #### `ddq_enabled?`
210
+ Check if deduplication is enabled:
211
+ ```ruby
212
+ puts OrderMessage.ddq_enabled? # => true/false
213
+ ```
214
+
215
+ #### `ddq_config`
216
+ Get current DDQ configuration:
217
+ ```ruby
218
+ config = OrderMessage.ddq_config
219
+ # => {enabled: true, size: 100, storage: :memory, options: {}}
220
+ ```
221
+
222
+ #### `ddq_stats`
223
+ Get DDQ statistics for all handlers:
224
+ ```ruby
225
+ stats = OrderMessage.ddq_stats
226
+ # => {enabled: true, current_count: 45, utilization: 45.0, ...}
227
+ ```
228
+
229
+ #### `clear_ddq!`
230
+ Clear all DDQ instances for the message class:
231
+ ```ruby
232
+ OrderMessage.clear_ddq!
233
+ ```
234
+
235
+ #### `duplicate_uuid?(uuid)`
236
+ Check if a UUID is tracked as duplicate:
237
+ ```ruby
238
+ is_dup = OrderMessage.duplicate_uuid?("some-uuid-123") # => true/false
239
+ ```
240
+
241
+ ### Instance Methods
242
+
243
+ #### `duplicate?`
244
+ Check if this message instance is a duplicate:
245
+ ```ruby
246
+ message = OrderMessage.new(order_id: "123", amount: 99.99)
247
+ puts message.duplicate? # => true/false
248
+ ```
249
+
250
+ #### `mark_as_processed!`
251
+ Manually mark this message as processed:
252
+ ```ruby
253
+ message.mark_as_processed! # Adds UUID to DDQ
254
+ ```
255
+
256
+ ## Integration with Dispatcher
257
+
258
+ The deduplication system integrates seamlessly with SmartMessage's dispatcher:
259
+
260
+ ### Message Flow with DDQ
261
+
262
+ 1. **Message Receipt**: Dispatcher receives decoded message
263
+ 2. **Handler Iteration**: For each subscribed handler:
264
+ - **DDQ Check**: Check handler's DDQ for message UUID
265
+ - **Skip Duplicates**: If UUID found, log and skip to next handler
266
+ - **Process New**: If UUID not found, route to handler
267
+ - **Mark Processed**: After successful processing, add UUID to handler's DDQ
268
+
269
+ ### Logging
270
+
271
+ The dispatcher provides detailed logging for deduplication events:
272
+
273
+ ```
274
+ [INFO] [SmartMessage::Dispatcher] Skipping duplicate for PaymentService.process: uuid-123
275
+ [DEBUG] [SmartMessage::Dispatcher] Marked UUID as processed for FulfillmentService.handle: uuid-456
276
+ ```
277
+
278
+ ### Statistics Integration
279
+
280
+ DDQ statistics are integrated with SmartMessage's built-in statistics system:
281
+
282
+ ```ruby
283
+ # Access via dispatcher
284
+ dispatcher = SmartMessage::Dispatcher.new
285
+ ddq_stats = dispatcher.ddq_stats
286
+
287
+ # Example output:
288
+ # {
289
+ # "OrderMessage:PaymentService.process" => {
290
+ # size: 100, current_count: 23, utilization: 23.0,
291
+ # storage_type: :memory, implementation: "SmartMessage::DDQ::Memory"
292
+ # },
293
+ # "OrderMessage:FulfillmentService.handle" => { ... }
294
+ # }
295
+ ```
296
+
297
+ ## Performance Characteristics
298
+
299
+ ### Memory DDQ Performance
300
+
301
+ - **Lookup Time**: O(1) - Set provides constant-time contains check
302
+ - **Insertion Time**: O(1) - Array provides constant-time insertion
303
+ - **Memory Usage**: ~48 bytes per UUID (including Set and Array overhead)
304
+ - **Thread Safety**: Mutex-protected for concurrent access
305
+
306
+ ### Redis DDQ Performance
307
+
308
+ - **Lookup Time**: O(1) - Redis SET provides constant-time membership test
309
+ - **Insertion Time**: O(1) - Redis LPUSH + LTRIM for circular behavior
310
+ - **Network Overhead**: 1-2 Redis commands per duplicate check
311
+ - **Persistence**: Automatic persistence and cross-process sharing
312
+
313
+ ### Benchmarks
314
+
315
+ Memory DDQ (1000 entries):
316
+ - **Memory Usage**: ~57 KB
317
+ - **Lookup Performance**: 0.001ms average
318
+ - **Insertion Performance**: 0.002ms average
319
+
320
+ Redis DDQ (1000 entries):
321
+ - **Memory Usage**: Stored in Redis
322
+ - **Lookup Performance**: 0.5-2ms average (network dependent)
323
+ - **Insertion Performance**: 1-3ms average (network dependent)
324
+
325
+ ## Best Practices
326
+
327
+ ### 1. Choose Appropriate DDQ Size
328
+
329
+ Size DDQ based on your message volume and acceptable duplicate window:
330
+
331
+ ```ruby
332
+ # High-volume service: larger DDQ
333
+ class HighVolumeMessage < SmartMessage::Base
334
+ ddq_size 10000 # Track last 10k messages
335
+ ddq_storage :redis
336
+ enable_deduplication!
337
+ end
338
+
339
+ # Low-volume service: smaller DDQ
340
+ class LowVolumeMessage < SmartMessage::Base
341
+ ddq_size 50 # Track last 50 messages
342
+ ddq_storage :memory
343
+ enable_deduplication!
344
+ end
345
+ ```
346
+
347
+ ### 2. Use Redis for Distributed Systems
348
+
349
+ For multi-process deployments, always use Redis storage:
350
+
351
+ ```ruby
352
+ class DistributedMessage < SmartMessage::Base
353
+ ddq_storage :redis,
354
+ redis_url: ENV.fetch('REDIS_URL', 'redis://localhost:6379'),
355
+ redis_db: ENV.fetch('DDQ_REDIS_DB', 1).to_i
356
+ enable_deduplication!
357
+ end
358
+ ```
359
+
360
+ ### 3. Monitor DDQ Statistics
361
+
362
+ Regularly monitor DDQ utilization:
363
+
364
+ ```ruby
365
+ # In monitoring/health check code
366
+ stats = OrderMessage.ddq_stats
367
+ if stats[:utilization] > 90
368
+ logger.warn "DDQ utilization high: #{stats[:utilization]}%"
369
+ end
370
+ ```
371
+
372
+ ### 4. Handle DDQ Errors Gracefully
373
+
374
+ The system is designed to fail-open (process messages when DDQ fails):
375
+
376
+ ```ruby
377
+ # DDQ failures are logged but don't prevent message processing
378
+ # Monitor logs for DDQ-related errors:
379
+ # [ERROR] [SmartMessage::DDQ] Failed to check duplicate: Redis connection error
380
+ ```
381
+
382
+ ## Troubleshooting
383
+
384
+ ### Common Issues
385
+
386
+ #### 1. Messages Not Being Deduplicated
387
+
388
+ **Symptoms**: Same UUID processed multiple times by same handler
389
+ **Causes**:
390
+ - Deduplication not enabled: `enable_deduplication!` missing
391
+ - Different handlers: Each handler has separate DDQ
392
+ - DDQ size too small: Old UUIDs evicted too quickly
393
+
394
+ **Solutions**:
395
+ ```ruby
396
+ # Verify deduplication is enabled
397
+ puts OrderMessage.ddq_enabled? # Should be true
398
+
399
+ # Check DDQ configuration
400
+ puts OrderMessage.ddq_config
401
+
402
+ # Increase DDQ size if needed
403
+ OrderMessage.ddq_size(1000)
404
+ ```
405
+
406
+ #### 2. Redis Connection Errors
407
+
408
+ **Symptoms**: DDQ errors in logs, messages still processing
409
+ **Causes**: Redis connectivity issues
410
+
411
+ **Solutions**:
412
+ ```ruby
413
+ # Verify Redis connection
414
+ redis_config = OrderMessage.ddq_config[:options]
415
+ puts "Redis URL: #{redis_config[:redis_url]}"
416
+
417
+ # Test Redis connectivity
418
+ require 'redis'
419
+ redis = Redis.new(url: redis_config[:redis_url])
420
+ puts redis.ping # Should return "PONG"
421
+ ```
422
+
423
+ #### 3. High Memory Usage
424
+
425
+ **Symptoms**: Increasing memory usage in memory DDQ
426
+ **Causes**: DDQ size too large for available memory
427
+
428
+ **Solutions**:
429
+ ```ruby
430
+ # Check memory usage
431
+ stats = OrderMessage.ddq_stats
432
+ puts "Memory usage: #{stats[:current_count] * 48} bytes"
433
+
434
+ # Reduce DDQ size
435
+ OrderMessage.ddq_size(100) # Smaller size
436
+
437
+ # Or switch to Redis
438
+ OrderMessage.ddq_storage(:redis)
439
+ ```
440
+
441
+ ### Debugging DDQ Issues
442
+
443
+ ```ruby
444
+ # Enable debug logging
445
+ SmartMessage.configure do |config|
446
+ config.log_level = :debug
447
+ end
448
+
449
+ # Check specific UUID
450
+ uuid = "test-uuid-123"
451
+ puts "Is duplicate: #{OrderMessage.duplicate_uuid?(uuid)}"
452
+
453
+ # Clear DDQ for testing
454
+ OrderMessage.clear_ddq!
455
+
456
+ # Monitor DDQ stats
457
+ stats = OrderMessage.ddq_stats
458
+ puts "Current count: #{stats[:current_count]}"
459
+ puts "Utilization: #{stats[:utilization]}%"
460
+ ```
461
+
462
+ ## Migration Guide
463
+
464
+ ### From Class-Level to Handler-Level DDQ
465
+
466
+ If upgrading from a previous version with class-level deduplication:
467
+
468
+ **Before (hypothetical)**:
469
+ ```ruby
470
+ # All handlers shared one DDQ per message class
471
+ OrderMessage.subscribe('PaymentService.process')
472
+ OrderMessage.subscribe('FulfillmentService.handle')
473
+ # Both shared the same DDQ
474
+ ```
475
+
476
+ **After (current)**:
477
+ ```ruby
478
+ # Each handler gets its own DDQ automatically
479
+ OrderMessage.subscribe('PaymentService.process') # DDQ: "OrderMessage:PaymentService.process"
480
+ OrderMessage.subscribe('FulfillmentService.handle') # DDQ: "OrderMessage:FulfillmentService.handle"
481
+ # Separate DDQs with isolated tracking
482
+ ```
483
+
484
+ **Benefits of Migration**:
485
+ - **Better Isolation**: Handler failures don't affect other handlers' deduplication
486
+ - **Flexible Filtering**: Different handlers can have different subscription filters
487
+ - **Cross-Process Safety**: Handlers with same name across processes get separate DDQs
488
+
489
+ The migration is automatic - no code changes required. The new system provides better isolation and reliability.
@@ -92,7 +92,7 @@ MyMessage.unsubscribe(block_id)
92
92
 
93
93
  - Default handler compatibility
94
94
  - Block handler functionality
95
- - Proc parameter handler functionality
95
+ - Proc parameter handler functionality
96
96
  - Lambda handler functionality
97
97
  - Multiple handlers for same message type
98
98
  - Mixed handler types (method + proc)
@@ -114,7 +114,7 @@ MyMessage.unsubscribe(block_id)
114
114
  ### Test Results
115
115
 
116
116
  - **55 total tests** (10 new proc handler tests + existing tests)
117
- - **276 assertions**
117
+ - **276 assertions**
118
118
  - **All tests passing**
119
119
  - **Full backward compatibility** maintained
120
120
 
@@ -153,17 +153,17 @@ MyMessage.unsubscribe(block_id)
153
153
 
154
154
  ## Examples
155
155
 
156
- ### 1. New Working Example (`examples/05_proc_handlers.rb`)
156
+ ### 1. New Working Example (`examples/memory/07_proc_handlers_demo.rb`)
157
157
 
158
158
  Complete demonstration of all handler types:
159
159
  - Default handler (self.process)
160
- - Block handlers (inline logic)
160
+ - Block handlers (inline logic)
161
161
  - Proc handlers (reusable logic)
162
162
  - Lambda handlers (functional style)
163
163
  - Method handlers (service classes)
164
164
  - Handler management and unsubscription
165
165
 
166
- ### 2. Enhanced IoT Example (`examples/04_redis_smart_home_iot.rb`)
166
+ ### 2. Enhanced IoT Example (`examples/redis/01_smart_home_iot_demo.rb`)
167
167
 
168
168
  Production-ready Redis transport example showing real-world usage patterns.
169
169
 
@@ -234,6 +234,7 @@ Production-ready Redis transport example showing real-world usage patterns.
234
234
  ## Future Enhancements
235
235
 
236
236
  Potential areas for future development:
237
+
237
238
  - Handler priority/ordering
238
239
  - Conditional handler execution
239
240
  - Handler metrics and monitoring
@@ -244,4 +245,4 @@ Potential areas for future development:
244
245
 
245
246
  The enhanced subscription functionality provides SmartMessage users with powerful, flexible options for message processing while maintaining the simplicity and elegance of the original design. The implementation is production-ready, thoroughly tested, and fully documented.
246
247
 
247
- This enhancement positions SmartMessage as a more versatile and developer-friendly messaging framework suitable for both simple prototypes and complex enterprise applications.
248
+ This enhancement positions SmartMessage as a more versatile and developer-friendly messaging framework suitable for both simple prototypes and complex enterprise applications.
@@ -26,7 +26,7 @@ The default serializer that converts messages to/from JSON format.
26
26
 
27
27
  ```ruby
28
28
  # Basic usage
29
- serializer = SmartMessage::Serializer::JSON.new
29
+ serializer = SmartMessage::Serializer::Json.new
30
30
 
31
31
  # Configure in message class
32
32
  class UserMessage < SmartMessage::Base
@@ -35,7 +35,7 @@ class UserMessage < SmartMessage::Base
35
35
  property :preferences
36
36
 
37
37
  config do
38
- serializer SmartMessage::Serializer::JSON.new
38
+ serializer SmartMessage::Serializer::Json.new
39
39
  end
40
40
  end
41
41
 
@@ -569,7 +569,5 @@ end
569
569
 
570
570
  ## Next Steps
571
571
 
572
- - [Custom Serializers](custom-serializers.md) - Build your own serializer
573
572
  - [Transports](transports.md) - How serializers work with transports
574
- - [Message Headers](headers.md) - Understanding message metadata
575
- - [Examples](examples.md) - Real-world serialization patterns
573
+ - [Examples](../getting-started/examples.md) - Real-world serialization patterns