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
@@ -0,0 +1,1091 @@
1
+ # Redis Queue Transport - Production Guide
2
+
3
+ This guide covers deploying Redis Queue Transport in production environments, including configuration, monitoring, scaling, and operational best practices.
4
+
5
+ ## Production Architecture
6
+
7
+ ### Recommended Infrastructure
8
+
9
+ ```
10
+ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
11
+ │ Application │ │ Redis │ │ Monitoring │
12
+ │ Servers │◄──►│ Cluster │◄──►│ Stack │
13
+ │ │ │ │ │ │
14
+ │ • Rails Apps │ │ • Master/Replica │ │ • Prometheus │
15
+ │ • Workers │ │ • Sentinel │ │ • Grafana │
16
+ │ • Background │ │ • Persistence │ │ • AlertManager │
17
+ │ Jobs │ │ • Memory Opt │ │ • Logs │
18
+ └─────────────────┘ └──────────────────┘ └─────────────────┘
19
+ ```
20
+
21
+ ### Infrastructure Components
22
+
23
+ 1. **Application Layer**: Rails applications, worker processes
24
+ 2. **Redis Layer**: Clustered Redis with persistence and monitoring
25
+ 3. **Load Balancers**: HAProxy/nginx for application load balancing
26
+ 4. **Monitoring**: Comprehensive observability stack
27
+ 5. **Alerting**: Proactive issue detection and notification
28
+
29
+ ## Redis Configuration
30
+
31
+ ### Production Redis Settings
32
+
33
+ ```ruby
34
+ # config/redis.conf
35
+ # Memory and performance optimization
36
+ maxmemory 4gb
37
+ maxmemory-policy allkeys-lru
38
+ tcp-keepalive 60
39
+ timeout 0
40
+
41
+ # Persistence for queue durability
42
+ save 900 1 # Save if at least 1 change in 15 minutes
43
+ save 300 10 # Save if at least 10 changes in 5 minutes
44
+ save 60 10000 # Save if at least 10k changes in 1 minute
45
+
46
+ # AOF for maximum durability
47
+ appendonly yes
48
+ appendfsync everysec
49
+ auto-aof-rewrite-percentage 100
50
+ auto-aof-rewrite-min-size 64mb
51
+
52
+ # Network and connection settings
53
+ tcp-backlog 511
54
+ bind 0.0.0.0
55
+ port 6379
56
+ protected-mode yes
57
+ requirepass your_secure_password
58
+
59
+ # Logging
60
+ loglevel notice
61
+ logfile /var/log/redis/redis-server.log
62
+ syslog-enabled yes
63
+
64
+ # Performance tuning
65
+ hash-max-ziplist-entries 512
66
+ hash-max-ziplist-value 64
67
+ list-max-ziplist-size -2
68
+ list-compress-depth 0
69
+ ```
70
+
71
+ ### Redis Cluster Setup
72
+
73
+ ```yaml
74
+ # docker-compose.yml for Redis cluster
75
+ version: '3.8'
76
+ services:
77
+ redis-master:
78
+ image: redis:7-alpine
79
+ command: redis-server /etc/redis/redis.conf
80
+ volumes:
81
+ - ./redis-master.conf:/etc/redis/redis.conf
82
+ - redis-master-data:/data
83
+ ports:
84
+ - "6379:6379"
85
+ networks:
86
+ - redis-network
87
+
88
+ redis-replica-1:
89
+ image: redis:7-alpine
90
+ command: redis-server /etc/redis/redis.conf
91
+ volumes:
92
+ - ./redis-replica.conf:/etc/redis/redis.conf
93
+ - redis-replica-1-data:/data
94
+ depends_on:
95
+ - redis-master
96
+ networks:
97
+ - redis-network
98
+
99
+ redis-replica-2:
100
+ image: redis:7-alpine
101
+ command: redis-server /etc/redis/redis.conf
102
+ volumes:
103
+ - ./redis-replica.conf:/etc/redis/redis.conf
104
+ - redis-replica-2-data:/data
105
+ depends_on:
106
+ - redis-master
107
+ networks:
108
+ - redis-network
109
+
110
+ redis-sentinel-1:
111
+ image: redis:7-alpine
112
+ command: redis-sentinel /etc/redis/sentinel.conf
113
+ volumes:
114
+ - ./sentinel.conf:/etc/redis/sentinel.conf
115
+ depends_on:
116
+ - redis-master
117
+ networks:
118
+ - redis-network
119
+
120
+ volumes:
121
+ redis-master-data:
122
+ redis-replica-1-data:
123
+ redis-replica-2-data:
124
+
125
+ networks:
126
+ redis-network:
127
+ driver: bridge
128
+ ```
129
+
130
+ ## SmartMessage Configuration
131
+
132
+ ### Production Transport Configuration
133
+
134
+ ```ruby
135
+ # config/environments/production.rb
136
+ SmartMessage.configure do |config|
137
+ config.transport = :redis_queue
138
+ config.transport_options = {
139
+ # Connection settings
140
+ url: ENV.fetch('REDIS_URL', 'redis://redis.internal:6379'),
141
+ db: ENV.fetch('REDIS_DB', '0').to_i,
142
+ password: ENV['REDIS_PASSWORD'],
143
+
144
+ # Queue configuration
145
+ queue_prefix: "#{Rails.application.class.module_parent_name.downcase}.#{Rails.env}",
146
+ consumer_group: "#{Rails.application.class.module_parent_name.downcase}_workers",
147
+ consumer_id: "#{Socket.gethostname}_#{Process.pid}",
148
+
149
+ # Performance tuning
150
+ block_time: 5000, # 5 second blocking timeout
151
+ max_queue_length: 100000, # Large queue capacity
152
+ batch_size: 10, # Process in batches
153
+
154
+ # Reliability settings
155
+ max_retries: 5,
156
+ retry_delay: 30, # 30 seconds between retries
157
+ exponential_backoff: true,
158
+ dead_letter_queue: true,
159
+ dead_letter_prefix: 'dlq',
160
+
161
+ # Connection pooling
162
+ pool_size: ENV.fetch('REDIS_POOL_SIZE', '10').to_i,
163
+ pool_timeout: ENV.fetch('REDIS_POOL_TIMEOUT', '5').to_i,
164
+
165
+ # Circuit breaker
166
+ circuit_breaker: true,
167
+ failure_threshold: 10,
168
+ recovery_timeout: 120,
169
+
170
+ # Monitoring
171
+ enable_metrics: true,
172
+ metrics_interval: 60,
173
+
174
+ # Security
175
+ ssl_params: Rails.env.production? ? { verify_mode: OpenSSL::SSL::VERIFY_PEER } : nil
176
+ }
177
+ end
178
+ ```
179
+
180
+ ### Environment-Specific Settings
181
+
182
+ ```ruby
183
+ # config/smartmessage.rb
184
+ class SmartMessageConfig
185
+ ENVIRONMENT_CONFIGS = {
186
+ development: {
187
+ block_time: 1000, # Fast for development
188
+ max_queue_length: 1000, # Small queues
189
+ debug: true,
190
+ pool_size: 2
191
+ },
192
+
193
+ test: {
194
+ block_time: 100, # Very fast for tests
195
+ max_queue_length: 100, # Tiny queues
196
+ db: 15, # Test database
197
+ pool_size: 1
198
+ },
199
+
200
+ staging: {
201
+ block_time: 3000, # Medium performance
202
+ max_queue_length: 10000, # Medium queues
203
+ max_retries: 3,
204
+ pool_size: 5
205
+ },
206
+
207
+ production: {
208
+ block_time: 5000, # Optimized for throughput
209
+ max_queue_length: 100000,# Large queues
210
+ max_retries: 5,
211
+ pool_size: 20,
212
+ circuit_breaker: true,
213
+ dead_letter_queue: true
214
+ }
215
+ }.freeze
216
+
217
+ def self.configure_for_environment(env = Rails.env)
218
+ base_config = SmartMessage.configuration.transport_options || {}
219
+ env_config = ENVIRONMENT_CONFIGS[env.to_sym] || {}
220
+
221
+ SmartMessage.configure do |config|
222
+ config.transport_options = base_config.merge(env_config)
223
+ end
224
+ end
225
+ end
226
+
227
+ # Apply environment-specific configuration
228
+ SmartMessageConfig.configure_for_environment
229
+ ```
230
+
231
+ ## Scaling and Performance
232
+
233
+ ### Horizontal Scaling
234
+
235
+ ```ruby
236
+ # config/initializers/smart_message_workers.rb
237
+ class SmartMessageWorkers
238
+ def self.start_for_environment
239
+ worker_config = case Rails.env
240
+ when 'production'
241
+ production_workers
242
+ when 'staging'
243
+ staging_workers
244
+ else
245
+ development_workers
246
+ end
247
+
248
+ start_workers(worker_config)
249
+ end
250
+
251
+ private
252
+
253
+ def self.production_workers
254
+ {
255
+ # High-volume message processing
256
+ general_workers: {
257
+ count: ENV.fetch('GENERAL_WORKERS', '8').to_i,
258
+ consumer_group: 'general_workers',
259
+ patterns: ['#.*.general_service', '#.*.default']
260
+ },
261
+
262
+ # Critical business processes
263
+ order_workers: {
264
+ count: ENV.fetch('ORDER_WORKERS', '4').to_i,
265
+ consumer_group: 'order_workers',
266
+ patterns: ['order.#.*.*', '#.*.order_service']
267
+ },
268
+
269
+ # Payment processing
270
+ payment_workers: {
271
+ count: ENV.fetch('PAYMENT_WORKERS', '3').to_i,
272
+ consumer_group: 'payment_workers',
273
+ patterns: ['payment.#.*.*', '#.*.payment_service']
274
+ },
275
+
276
+ # Email and notifications
277
+ notification_workers: {
278
+ count: ENV.fetch('NOTIFICATION_WORKERS', '2').to_i,
279
+ consumer_group: 'notification_workers',
280
+ patterns: ['notification.#.*.*', '#.*.notification_service']
281
+ },
282
+
283
+ # Analytics and reporting
284
+ analytics_workers: {
285
+ count: ENV.fetch('ANALYTICS_WORKERS', '2').to_i,
286
+ consumer_group: 'analytics_workers',
287
+ patterns: ['analytics.#.*.*', '#.*.analytics_service']
288
+ }
289
+ }
290
+ end
291
+
292
+ def self.start_workers(worker_config)
293
+ worker_config.each do |worker_type, config|
294
+ Rails.logger.info "Starting #{config[:count]} #{worker_type} workers"
295
+
296
+ config[:count].times do |i|
297
+ Thread.new do
298
+ start_worker(worker_type, i + 1, config)
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ def self.start_worker(worker_type, worker_id, config)
305
+ transport = SmartMessage::Transport::RedisQueueTransport.new(
306
+ consumer_group: config[:consumer_group],
307
+ consumer_id: "#{worker_type}_#{worker_id}_#{Socket.gethostname}"
308
+ )
309
+
310
+ config[:patterns].each do |pattern|
311
+ transport.subscribe_pattern(pattern) do |message_class, message_data|
312
+ Rails.logger.info "[#{worker_type}_#{worker_id}] Processing: #{message_class}"
313
+
314
+ begin
315
+ # Process message with timeout
316
+ Timeout::timeout(30) do
317
+ process_message(message_class, message_data)
318
+ end
319
+ rescue Timeout::Error
320
+ Rails.logger.error "[#{worker_type}_#{worker_id}] Timeout processing: #{message_class}"
321
+ raise SmartMessage::Errors::RetryableError, 'Processing timeout'
322
+ rescue => e
323
+ Rails.logger.error "[#{worker_type}_#{worker_id}] Error: #{e.message}"
324
+ raise
325
+ end
326
+ end
327
+ end
328
+
329
+ Rails.logger.info "[#{worker_type}_#{worker_id}] Worker started"
330
+
331
+ # Keep worker alive
332
+ loop { sleep 1 }
333
+ rescue => e
334
+ Rails.logger.error "[#{worker_type}_#{worker_id}] Worker crashed: #{e.message}"
335
+ # Restart worker after delay
336
+ sleep 5
337
+ retry
338
+ end
339
+ end
340
+
341
+ # Auto-start workers in production
342
+ if Rails.env.production?
343
+ Thread.new { SmartMessageWorkers.start_for_environment }
344
+ end
345
+ ```
346
+
347
+ ### Vertical Scaling
348
+
349
+ ```ruby
350
+ # config/initializers/performance_optimization.rb
351
+ module SmartMessageOptimization
352
+ def self.optimize_for_production
353
+ # Optimize Redis connection pool
354
+ configure_connection_pool
355
+
356
+ # Set up message batching
357
+ configure_batching
358
+
359
+ # Enable compression for large messages
360
+ configure_compression
361
+
362
+ # Set up performance monitoring
363
+ configure_monitoring
364
+ end
365
+
366
+ private
367
+
368
+ def self.configure_connection_pool
369
+ SmartMessage.configure do |config|
370
+ config.transport_options.merge!({
371
+ pool_size: [ENV.fetch('MAX_THREADS', '20').to_i, 50].min,
372
+ pool_timeout: 10,
373
+ reconnect_attempts: 3,
374
+ reconnect_delay: 1
375
+ })
376
+ end
377
+ end
378
+
379
+ def self.configure_batching
380
+ # Process messages in batches for better throughput
381
+ SmartMessage::Transport::RedisQueueTransport.class_eval do
382
+ def process_message_batch(messages)
383
+ messages.each do |message_class, message_data|
384
+ begin
385
+ receive(message_class, message_data)
386
+ rescue => e
387
+ Rails.logger.error "Batch processing error: #{e.message}"
388
+ end
389
+ end
390
+ end
391
+ end
392
+ end
393
+
394
+ def self.configure_compression
395
+ # Enable compression for messages over 1KB
396
+ SmartMessage.configure do |config|
397
+ config.serializer_options = {
398
+ compress_threshold: 1024,
399
+ compression_method: :gzip
400
+ }
401
+ end
402
+ end
403
+
404
+ def self.configure_monitoring
405
+ # Set up performance metrics collection
406
+ ActiveSupport::Notifications.subscribe('smartmessage.message_processed') do |*args|
407
+ event = ActiveSupport::Notifications::Event.new(*args)
408
+
409
+ # Log processing time
410
+ Rails.logger.info "Message processed in #{event.duration}ms: #{event.payload[:message_class]}"
411
+
412
+ # Send to metrics collector
413
+ if defined?(Prometheus)
414
+ SmartMessageMetrics.record_processing_time(event.duration, event.payload[:message_class])
415
+ end
416
+ end
417
+ end
418
+ end
419
+
420
+ SmartMessageOptimization.optimize_for_production if Rails.env.production?
421
+ ```
422
+
423
+ ## Monitoring and Observability
424
+
425
+ ### Application Monitoring
426
+
427
+ ```ruby
428
+ # app/services/smart_message_monitor.rb
429
+ class SmartMessageMonitor
430
+ include Singleton
431
+
432
+ def initialize
433
+ @transport = SmartMessage::Transport::RedisQueueTransport.new
434
+ @metrics = {}
435
+ start_monitoring
436
+ end
437
+
438
+ def start_monitoring
439
+ Thread.new { monitor_queues }
440
+ Thread.new { monitor_workers }
441
+ Thread.new { monitor_performance }
442
+ end
443
+
444
+ private
445
+
446
+ def monitor_queues
447
+ loop do
448
+ stats = @transport.queue_stats
449
+
450
+ stats.each do |queue_name, info|
451
+ queue_length = info[:length]
452
+ consumer_count = info[:consumers] || 0
453
+
454
+ # Record metrics
455
+ @metrics["queue.#{queue_name}.length"] = queue_length
456
+ @metrics["queue.#{queue_name}.consumers"] = consumer_count
457
+
458
+ # Check for alerts
459
+ if queue_length > 1000
460
+ alert_high_queue_length(queue_name, queue_length)
461
+ end
462
+
463
+ if queue_length > 0 && consumer_count == 0
464
+ alert_no_consumers(queue_name, queue_length)
465
+ end
466
+
467
+ if consumer_count > 20
468
+ alert_high_consumer_count(queue_name, consumer_count)
469
+ end
470
+ end
471
+
472
+ # Update external metrics
473
+ update_external_metrics(@metrics)
474
+
475
+ sleep 30 # Check every 30 seconds
476
+ end
477
+ end
478
+
479
+ def monitor_workers
480
+ loop do
481
+ worker_stats = collect_worker_stats
482
+
483
+ worker_stats.each do |worker_type, stats|
484
+ @metrics["workers.#{worker_type}.active"] = stats[:active]
485
+ @metrics["workers.#{worker_type}.processing"] = stats[:processing]
486
+ @metrics["workers.#{worker_type}.errors"] = stats[:errors]
487
+ end
488
+
489
+ sleep 60 # Check every minute
490
+ end
491
+ end
492
+
493
+ def monitor_performance
494
+ start_time = Time.now
495
+ processed_messages = 0
496
+
497
+ loop do
498
+ current_processed = get_total_processed_messages
499
+ duration = Time.now - start_time
500
+
501
+ if duration >= 60 # Calculate rate every minute
502
+ rate = (current_processed - processed_messages) / duration
503
+ @metrics['performance.messages_per_second'] = rate
504
+
505
+ processed_messages = current_processed
506
+ start_time = Time.now
507
+ end
508
+
509
+ sleep 10
510
+ end
511
+ end
512
+
513
+ def alert_high_queue_length(queue_name, length)
514
+ Rails.logger.warn "HIGH QUEUE LENGTH: #{queue_name} has #{length} messages"
515
+
516
+ # Send to alerting system
517
+ if defined?(AlertManager)
518
+ AlertManager.alert(
519
+ severity: :warning,
520
+ message: "Queue #{queue_name} has #{length} messages",
521
+ tags: { queue: queue_name, type: :high_queue_length }
522
+ )
523
+ end
524
+ end
525
+
526
+ def alert_no_consumers(queue_name, length)
527
+ Rails.logger.error "NO CONSUMERS: #{queue_name} has #{length} messages but no consumers"
528
+
529
+ if defined?(AlertManager)
530
+ AlertManager.alert(
531
+ severity: :critical,
532
+ message: "Queue #{queue_name} has no consumers but #{length} pending messages",
533
+ tags: { queue: queue_name, type: :no_consumers }
534
+ )
535
+ end
536
+ end
537
+
538
+ def update_external_metrics(metrics)
539
+ # Send to Prometheus
540
+ if defined?(Prometheus::Client)
541
+ metrics.each do |metric_name, value|
542
+ Prometheus::Client.registry.get(metric_name.to_sym)&.set(value)
543
+ end
544
+ end
545
+
546
+ # Send to StatsD
547
+ if defined?(Statsd)
548
+ metrics.each do |metric_name, value|
549
+ $statsd&.gauge("smartmessage.#{metric_name}", value)
550
+ end
551
+ end
552
+
553
+ # Send to CloudWatch
554
+ if defined?(Aws::CloudWatch)
555
+ # Implementation for CloudWatch metrics
556
+ end
557
+ end
558
+ end
559
+
560
+ # Start monitoring in production
561
+ SmartMessageMonitor.instance if Rails.env.production?
562
+ ```
563
+
564
+ ### Prometheus Metrics
565
+
566
+ ```ruby
567
+ # lib/smart_message_metrics.rb
568
+ require 'prometheus/client'
569
+
570
+ module SmartMessageMetrics
571
+ def self.setup_metrics
572
+ registry = Prometheus::Client.registry
573
+
574
+ @message_processing_duration = registry.histogram(
575
+ :smartmessage_processing_duration_seconds,
576
+ docstring: 'Time spent processing messages',
577
+ labels: [:message_class, :worker_type]
578
+ )
579
+
580
+ @queue_length = registry.gauge(
581
+ :smartmessage_queue_length,
582
+ docstring: 'Current queue length',
583
+ labels: [:queue_name, :pattern]
584
+ )
585
+
586
+ @consumer_count = registry.gauge(
587
+ :smartmessage_consumer_count,
588
+ docstring: 'Number of active consumers',
589
+ labels: [:queue_name, :consumer_group]
590
+ )
591
+
592
+ @messages_processed_total = registry.counter(
593
+ :smartmessage_messages_processed_total,
594
+ docstring: 'Total number of messages processed',
595
+ labels: [:message_class, :status]
596
+ )
597
+
598
+ @connection_errors_total = registry.counter(
599
+ :smartmessage_connection_errors_total,
600
+ docstring: 'Total number of Redis connection errors',
601
+ labels: [:error_type]
602
+ )
603
+ end
604
+
605
+ def self.record_processing_time(duration_seconds, message_class, worker_type = 'unknown')
606
+ @message_processing_duration&.observe(duration_seconds, labels: {
607
+ message_class: message_class,
608
+ worker_type: worker_type
609
+ })
610
+ end
611
+
612
+ def self.update_queue_length(queue_name, length, pattern = '')
613
+ @queue_length&.set(length, labels: {
614
+ queue_name: queue_name,
615
+ pattern: pattern
616
+ })
617
+ end
618
+
619
+ def self.update_consumer_count(queue_name, count, consumer_group = '')
620
+ @consumer_count&.set(count, labels: {
621
+ queue_name: queue_name,
622
+ consumer_group: consumer_group
623
+ })
624
+ end
625
+
626
+ def self.increment_messages_processed(message_class, status = 'success')
627
+ @messages_processed_total&.increment(labels: {
628
+ message_class: message_class,
629
+ status: status
630
+ })
631
+ end
632
+
633
+ def self.increment_connection_errors(error_type)
634
+ @connection_errors_total&.increment(labels: {
635
+ error_type: error_type
636
+ })
637
+ end
638
+ end
639
+
640
+ # Initialize metrics
641
+ SmartMessageMetrics.setup_metrics if defined?(Prometheus::Client)
642
+ ```
643
+
644
+ ### Grafana Dashboard
645
+
646
+ ```json
647
+ {
648
+ "dashboard": {
649
+ "id": null,
650
+ "title": "SmartMessage Redis Queue Transport",
651
+ "tags": ["smartmessage", "redis", "queues"],
652
+ "timezone": "browser",
653
+ "panels": [
654
+ {
655
+ "title": "Queue Lengths",
656
+ "type": "graph",
657
+ "targets": [
658
+ {
659
+ "expr": "smartmessage_queue_length",
660
+ "legendFormat": "{{ queue_name }}"
661
+ }
662
+ ],
663
+ "yAxes": [
664
+ {
665
+ "label": "Messages",
666
+ "min": 0
667
+ }
668
+ ]
669
+ },
670
+ {
671
+ "title": "Messages Processed per Second",
672
+ "type": "graph",
673
+ "targets": [
674
+ {
675
+ "expr": "rate(smartmessage_messages_processed_total[1m])",
676
+ "legendFormat": "{{ message_class }} ({{ status }})"
677
+ }
678
+ ]
679
+ },
680
+ {
681
+ "title": "Processing Duration",
682
+ "type": "graph",
683
+ "targets": [
684
+ {
685
+ "expr": "histogram_quantile(0.95, smartmessage_processing_duration_seconds_bucket)",
686
+ "legendFormat": "95th percentile"
687
+ },
688
+ {
689
+ "expr": "histogram_quantile(0.50, smartmessage_processing_duration_seconds_bucket)",
690
+ "legendFormat": "50th percentile"
691
+ }
692
+ ]
693
+ },
694
+ {
695
+ "title": "Active Consumers",
696
+ "type": "stat",
697
+ "targets": [
698
+ {
699
+ "expr": "sum(smartmessage_consumer_count)",
700
+ "legendFormat": "Total Consumers"
701
+ }
702
+ ]
703
+ },
704
+ {
705
+ "title": "Connection Errors",
706
+ "type": "graph",
707
+ "targets": [
708
+ {
709
+ "expr": "rate(smartmessage_connection_errors_total[5m])",
710
+ "legendFormat": "{{ error_type }}"
711
+ }
712
+ ]
713
+ }
714
+ ]
715
+ }
716
+ }
717
+ ```
718
+
719
+ ## Security
720
+
721
+ ### Authentication and Authorization
722
+
723
+ ```ruby
724
+ # config/initializers/redis_security.rb
725
+ class RedisSecurityConfig
726
+ def self.configure_for_production
727
+ SmartMessage.configure do |config|
728
+ config.transport_options.merge!({
729
+ # Redis authentication
730
+ password: ENV.fetch('REDIS_PASSWORD'),
731
+
732
+ # SSL/TLS encryption
733
+ ssl: true,
734
+ ssl_params: {
735
+ verify_mode: OpenSSL::SSL::VERIFY_PEER,
736
+ ca_file: ENV['REDIS_CA_CERT_PATH'],
737
+ cert: OpenSSL::X509::Certificate.new(File.read(ENV['REDIS_CLIENT_CERT_PATH'])),
738
+ key: OpenSSL::PKey::RSA.new(File.read(ENV['REDIS_CLIENT_KEY_PATH']))
739
+ },
740
+
741
+ # Network security
742
+ bind: ENV.fetch('REDIS_BIND_ADDRESS', '127.0.0.1'),
743
+
744
+ # Message encryption
745
+ encrypt_messages: true,
746
+ encryption_key: ENV.fetch('MESSAGE_ENCRYPTION_KEY')
747
+ })
748
+ end
749
+ end
750
+ end
751
+
752
+ RedisSecurityConfig.configure_for_production if Rails.env.production?
753
+ ```
754
+
755
+ ### Message Encryption
756
+
757
+ ```ruby
758
+ # lib/smart_message_encryption.rb
759
+ module SmartMessageEncryption
760
+ def self.encrypt_message(message_data)
761
+ key = ENV.fetch('MESSAGE_ENCRYPTION_KEY')
762
+ cipher = OpenSSL::Cipher.new('AES-256-GCM')
763
+ cipher.encrypt
764
+ cipher.key = Base64.decode64(key)
765
+
766
+ iv = cipher.random_iv
767
+ encrypted_data = cipher.update(message_data) + cipher.final
768
+ auth_tag = cipher.auth_tag
769
+
770
+ Base64.encode64({
771
+ iv: Base64.encode64(iv),
772
+ data: Base64.encode64(encrypted_data),
773
+ tag: Base64.encode64(auth_tag)
774
+ }.to_json)
775
+ end
776
+
777
+ def self.decrypt_message(encrypted_message)
778
+ key = ENV.fetch('MESSAGE_ENCRYPTION_KEY')
779
+ parsed = JSON.parse(Base64.decode64(encrypted_message))
780
+
781
+ cipher = OpenSSL::Cipher.new('AES-256-GCM')
782
+ cipher.decrypt
783
+ cipher.key = Base64.decode64(key)
784
+ cipher.iv = Base64.decode64(parsed['iv'])
785
+ cipher.auth_tag = Base64.decode64(parsed['tag'])
786
+
787
+ cipher.update(Base64.decode64(parsed['data'])) + cipher.final
788
+ end
789
+ end
790
+ ```
791
+
792
+ ## Deployment
793
+
794
+ ### Docker Configuration
795
+
796
+ ```dockerfile
797
+ # Dockerfile
798
+ FROM ruby:3.2-slim
799
+
800
+ # Install system dependencies
801
+ RUN apt-get update && apt-get install -y \
802
+ build-essential \
803
+ libpq-dev \
804
+ nodejs \
805
+ && rm -rf /var/lib/apt/lists/*
806
+
807
+ WORKDIR /app
808
+
809
+ # Install Ruby dependencies
810
+ COPY Gemfile Gemfile.lock ./
811
+ RUN bundle config --global frozen 1 && \
812
+ bundle install --without development test
813
+
814
+ # Copy application code
815
+ COPY . .
816
+
817
+ # Create non-root user
818
+ RUN adduser --disabled-password --gecos '' appuser && \
819
+ chown -R appuser:appuser /app
820
+ USER appuser
821
+
822
+ # Health check
823
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
824
+ CMD curl -f http://localhost:3000/health || exit 1
825
+
826
+ EXPOSE 3000
827
+
828
+ CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
829
+ ```
830
+
831
+ ### Kubernetes Deployment
832
+
833
+ ```yaml
834
+ # k8s/smartmessage-app.yaml
835
+ apiVersion: apps/v1
836
+ kind: Deployment
837
+ metadata:
838
+ name: smartmessage-app
839
+ labels:
840
+ app: smartmessage-app
841
+ spec:
842
+ replicas: 3
843
+ selector:
844
+ matchLabels:
845
+ app: smartmessage-app
846
+ template:
847
+ metadata:
848
+ labels:
849
+ app: smartmessage-app
850
+ spec:
851
+ containers:
852
+ - name: app
853
+ image: smartmessage-app:latest
854
+ ports:
855
+ - containerPort: 3000
856
+ env:
857
+ - name: REDIS_URL
858
+ value: "redis://redis-service:6379"
859
+ - name: REDIS_PASSWORD
860
+ valueFrom:
861
+ secretKeyRef:
862
+ name: redis-secret
863
+ key: password
864
+ resources:
865
+ requests:
866
+ memory: "512Mi"
867
+ cpu: "250m"
868
+ limits:
869
+ memory: "1Gi"
870
+ cpu: "500m"
871
+ livenessProbe:
872
+ httpGet:
873
+ path: /health
874
+ port: 3000
875
+ initialDelaySeconds: 30
876
+ periodSeconds: 10
877
+ readinessProbe:
878
+ httpGet:
879
+ path: /ready
880
+ port: 3000
881
+ initialDelaySeconds: 5
882
+ periodSeconds: 5
883
+
884
+ ---
885
+ apiVersion: apps/v1
886
+ kind: Deployment
887
+ metadata:
888
+ name: smartmessage-workers
889
+ labels:
890
+ app: smartmessage-workers
891
+ spec:
892
+ replicas: 5
893
+ selector:
894
+ matchLabels:
895
+ app: smartmessage-workers
896
+ template:
897
+ metadata:
898
+ labels:
899
+ app: smartmessage-workers
900
+ spec:
901
+ containers:
902
+ - name: worker
903
+ image: smartmessage-app:latest
904
+ command: ["bundle", "exec", "ruby", "lib/workers/start_workers.rb"]
905
+ env:
906
+ - name: REDIS_URL
907
+ value: "redis://redis-service:6379"
908
+ - name: WORKER_TYPE
909
+ value: "all"
910
+ - name: GENERAL_WORKERS
911
+ value: "2"
912
+ - name: ORDER_WORKERS
913
+ value: "1"
914
+ resources:
915
+ requests:
916
+ memory: "256Mi"
917
+ cpu: "100m"
918
+ limits:
919
+ memory: "512Mi"
920
+ cpu: "200m"
921
+ ```
922
+
923
+ ### Helm Chart
924
+
925
+ ```yaml
926
+ # helm/smartmessage/values.yaml
927
+ replicaCount: 3
928
+
929
+ image:
930
+ repository: smartmessage
931
+ tag: latest
932
+ pullPolicy: IfNotPresent
933
+
934
+ redis:
935
+ host: redis-service
936
+ port: 6379
937
+ database: 0
938
+ auth:
939
+ enabled: true
940
+ password: "secure_password"
941
+
942
+ workers:
943
+ enabled: true
944
+ replicas: 5
945
+ types:
946
+ general: 2
947
+ order: 1
948
+ payment: 1
949
+ notification: 1
950
+
951
+ resources:
952
+ app:
953
+ requests:
954
+ memory: 512Mi
955
+ cpu: 250m
956
+ limits:
957
+ memory: 1Gi
958
+ cpu: 500m
959
+ workers:
960
+ requests:
961
+ memory: 256Mi
962
+ cpu: 100m
963
+ limits:
964
+ memory: 512Mi
965
+ cpu: 200m
966
+
967
+ autoscaling:
968
+ enabled: true
969
+ minReplicas: 3
970
+ maxReplicas: 10
971
+ targetCPUUtilizationPercentage: 70
972
+ targetMemoryUtilizationPercentage: 80
973
+
974
+ monitoring:
975
+ enabled: true
976
+ prometheus:
977
+ enabled: true
978
+ grafana:
979
+ enabled: true
980
+ alerting:
981
+ enabled: true
982
+
983
+ ingress:
984
+ enabled: true
985
+ className: nginx
986
+ annotations:
987
+ nginx.ingress.kubernetes.io/ssl-redirect: "true"
988
+ hosts:
989
+ - host: smartmessage.example.com
990
+ paths:
991
+ - path: /
992
+ pathType: Prefix
993
+ tls:
994
+ - secretName: smartmessage-tls
995
+ hosts:
996
+ - smartmessage.example.com
997
+ ```
998
+
999
+ ## High Availability
1000
+
1001
+ ### Redis Sentinel Configuration
1002
+
1003
+ ```ruby
1004
+ # config/redis_sentinel.rb
1005
+ class RedisSentinelConfig
1006
+ def self.configure_high_availability
1007
+ SmartMessage.configure do |config|
1008
+ config.transport_options = {
1009
+ # Sentinel configuration
1010
+ sentinels: [
1011
+ { host: 'sentinel-1.internal', port: 26379 },
1012
+ { host: 'sentinel-2.internal', port: 26379 },
1013
+ { host: 'sentinel-3.internal', port: 26379 }
1014
+ ],
1015
+ name: 'smartmessage-redis',
1016
+ password: ENV['REDIS_PASSWORD'],
1017
+
1018
+ # Failover settings
1019
+ sentinel_timeout: 5,
1020
+ connect_timeout: 5,
1021
+ read_timeout: 5,
1022
+ write_timeout: 5,
1023
+
1024
+ # Retry configuration
1025
+ reconnect_attempts: 5,
1026
+ reconnect_delay: 2,
1027
+
1028
+ # Connection pool for HA
1029
+ pool_size: 20,
1030
+ pool_timeout: 10
1031
+ }
1032
+ end
1033
+ end
1034
+ end
1035
+
1036
+ RedisSentinelConfig.configure_high_availability if Rails.env.production?
1037
+ ```
1038
+
1039
+ ### Disaster Recovery
1040
+
1041
+ ```ruby
1042
+ # lib/disaster_recovery.rb
1043
+ module DisasterRecovery
1044
+ class BackupManager
1045
+ def self.setup_automated_backups
1046
+ # Daily Redis backup
1047
+ whenever_schedule = <<~SCHEDULE
1048
+ # Redis backup every day at 2 AM
1049
+ 0 2 * * * cd #{Rails.root} && bundle exec ruby lib/disaster_recovery/backup_redis.rb
1050
+
1051
+ # Weekly full backup
1052
+ 0 1 * * 0 cd #{Rails.root} && bundle exec ruby lib/disaster_recovery/full_backup.rb
1053
+ SCHEDULE
1054
+
1055
+ File.write('config/schedule.rb', whenever_schedule)
1056
+ end
1057
+
1058
+ def self.backup_redis_data
1059
+ timestamp = Time.current.strftime('%Y%m%d_%H%M%S')
1060
+ backup_file = "backups/redis_backup_#{timestamp}.rdb"
1061
+
1062
+ system("redis-cli --rdb #{backup_file}")
1063
+
1064
+ # Upload to S3 or other backup storage
1065
+ if ENV['AWS_S3_BACKUP_BUCKET']
1066
+ upload_to_s3(backup_file)
1067
+ end
1068
+
1069
+ Rails.logger.info "Redis backup completed: #{backup_file}"
1070
+ end
1071
+
1072
+ def self.restore_from_backup(backup_file)
1073
+ Rails.logger.info "Starting Redis restore from: #{backup_file}"
1074
+
1075
+ # Stop Redis
1076
+ system('sudo systemctl stop redis')
1077
+
1078
+ # Replace RDB file
1079
+ system("sudo cp #{backup_file} /var/lib/redis/dump.rdb")
1080
+ system('sudo chown redis:redis /var/lib/redis/dump.rdb')
1081
+
1082
+ # Start Redis
1083
+ system('sudo systemctl start redis')
1084
+
1085
+ Rails.logger.info "Redis restore completed"
1086
+ end
1087
+ end
1088
+ end
1089
+ ```
1090
+
1091
+ This production guide provides the foundation for deploying Redis Queue Transport in enterprise environments. Adapt the configurations based on your specific infrastructure and requirements, always testing thoroughly in staging environments before production deployment.