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.
- checksums.yaml +4 -4
- data/.github/workflows/deploy-github-pages.yml +38 -0
- data/.gitignore +5 -0
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +35 -4
- data/README.md +169 -71
- data/Rakefile +29 -4
- data/docs/assets/images/ddq_architecture.svg +130 -0
- data/docs/assets/images/dlq_architecture.svg +115 -0
- data/docs/assets/images/enhanced-dual-publishing.svg +136 -0
- data/docs/assets/images/enhanced-fluent-api.svg +149 -0
- data/docs/assets/images/enhanced-microservices-routing.svg +115 -0
- data/docs/assets/images/enhanced-pattern-matching.svg +107 -0
- data/docs/assets/images/fluent-api-demo.svg +59 -0
- data/docs/assets/images/performance-comparison.svg +161 -0
- data/docs/assets/images/redis-basic-architecture.svg +53 -0
- data/docs/assets/images/redis-enhanced-architecture.svg +88 -0
- data/docs/assets/images/redis-queue-architecture.svg +101 -0
- data/docs/assets/images/smart_message.jpg +0 -0
- data/docs/assets/images/smart_message_walking.jpg +0 -0
- data/docs/assets/images/smartmessage_architecture_overview.svg +173 -0
- data/docs/assets/images/transport-comparison-matrix.svg +171 -0
- data/docs/assets/javascripts/mathjax.js +17 -0
- data/docs/assets/stylesheets/extra.css +51 -0
- data/docs/{addressing.md → core-concepts/addressing.md} +5 -7
- data/docs/{architecture.md → core-concepts/architecture.md} +78 -138
- data/docs/{dispatcher.md → core-concepts/dispatcher.md} +21 -21
- data/docs/{message_filtering.md → core-concepts/message-filtering.md} +2 -3
- data/docs/{message_processing.md → core-concepts/message-processing.md} +17 -17
- data/docs/{troubleshooting.md → development/troubleshooting.md} +7 -7
- data/docs/{examples.md → getting-started/examples.md} +115 -89
- data/docs/{getting-started.md → getting-started/quick-start.md} +47 -18
- data/docs/guides/redis-queue-getting-started.md +697 -0
- data/docs/guides/redis-queue-patterns.md +889 -0
- data/docs/guides/redis-queue-production.md +1091 -0
- data/docs/index.md +64 -0
- data/docs/{dead_letter_queue.md → reference/dead-letter-queue.md} +2 -3
- data/docs/{logging.md → reference/logging.md} +1 -1
- data/docs/{message_deduplication.md → reference/message-deduplication.md} +1 -0
- data/docs/{proc_handlers_summary.md → reference/proc-handlers.md} +7 -6
- data/docs/{serializers.md → reference/serializers.md} +3 -5
- data/docs/{transports.md → reference/transports.md} +133 -11
- data/docs/transports/memory-transport.md +374 -0
- data/docs/transports/redis-enhanced-transport.md +524 -0
- data/docs/transports/redis-queue-transport.md +1304 -0
- data/docs/transports/redis-transport-comparison.md +496 -0
- data/docs/transports/redis-transport.md +509 -0
- data/examples/README.md +98 -5
- data/examples/city_scenario/911_emergency_call_flow.svg +99 -0
- data/examples/city_scenario/README.md +515 -0
- data/examples/city_scenario/ai_visitor_intelligence_flow.svg +108 -0
- data/examples/city_scenario/citizen.rb +195 -0
- data/examples/city_scenario/city_diagram.svg +125 -0
- data/examples/city_scenario/common/health_monitor.rb +80 -0
- data/examples/city_scenario/common/logger.rb +30 -0
- data/examples/city_scenario/emergency_dispatch_center.rb +270 -0
- data/examples/city_scenario/fire_department.rb +446 -0
- data/examples/city_scenario/fire_emergency_flow.svg +95 -0
- data/examples/city_scenario/health_department.rb +100 -0
- data/examples/city_scenario/health_monitoring_system.svg +130 -0
- data/examples/city_scenario/house.rb +244 -0
- data/examples/city_scenario/local_bank.rb +217 -0
- data/examples/city_scenario/messages/emergency_911_message.rb +81 -0
- data/examples/city_scenario/messages/emergency_resolved_message.rb +43 -0
- data/examples/city_scenario/messages/fire_dispatch_message.rb +43 -0
- data/examples/city_scenario/messages/fire_emergency_message.rb +45 -0
- data/examples/city_scenario/messages/health_check_message.rb +22 -0
- data/examples/city_scenario/messages/health_status_message.rb +35 -0
- data/examples/city_scenario/messages/police_dispatch_message.rb +46 -0
- data/examples/city_scenario/messages/silent_alarm_message.rb +38 -0
- data/examples/city_scenario/police_department.rb +316 -0
- data/examples/city_scenario/redis_monitor.rb +129 -0
- data/examples/city_scenario/redis_stats.rb +743 -0
- data/examples/city_scenario/room_for_improvement.md +240 -0
- data/examples/city_scenario/security_emergency_flow.svg +95 -0
- data/examples/city_scenario/service_internal_architecture.svg +154 -0
- data/examples/city_scenario/smart_message_ai_agent.rb +364 -0
- data/examples/city_scenario/start_demo.sh +236 -0
- data/examples/city_scenario/stop_demo.sh +106 -0
- data/examples/city_scenario/visitor.rb +631 -0
- data/examples/{10_message_deduplication.rb → memory/01_message_deduplication_demo.rb} +1 -1
- data/examples/{09_dead_letter_queue_demo.rb → memory/02_dead_letter_queue_demo.rb} +13 -40
- data/examples/{01_point_to_point_orders.rb → memory/03_point_to_point_orders.rb} +1 -1
- data/examples/{02_publish_subscribe_events.rb → memory/04_publish_subscribe_events.rb} +2 -2
- data/examples/{03_many_to_many_chat.rb → memory/05_many_to_many_chat.rb} +4 -4
- data/examples/{show_me.rb → memory/06_pretty_print_demo.rb} +1 -1
- data/examples/{05_proc_handlers.rb → memory/07_proc_handlers_demo.rb} +2 -2
- data/examples/{06_custom_logger_example.rb → memory/08_custom_logger_demo.rb} +17 -14
- data/examples/{07_error_handling_scenarios.rb → memory/09_error_handling_demo.rb} +4 -4
- data/examples/{08_entity_addressing_basic.rb → memory/10_entity_addressing_basic.rb} +8 -8
- data/examples/{08_entity_addressing_with_filtering.rb → memory/11_entity_addressing_with_filtering.rb} +6 -6
- data/examples/{09_regex_filtering_microservices.rb → memory/12_regex_filtering_microservices.rb} +2 -2
- data/examples/{10_header_block_configuration.rb → memory/13_header_block_configuration.rb} +6 -6
- data/examples/{11_global_configuration_example.rb → memory/14_global_configuration_demo.rb} +19 -8
- data/examples/{show_logger.rb → memory/15_logger_demo.rb} +1 -1
- data/examples/memory/README.md +163 -0
- data/examples/memory/memory_transport_architecture.svg +90 -0
- data/examples/memory/point_to_point_pattern.svg +94 -0
- data/examples/memory/publish_subscribe_pattern.svg +125 -0
- data/examples/{04_redis_smart_home_iot.rb → redis/01_smart_home_iot_demo.rb} +5 -5
- data/examples/redis/README.md +230 -0
- data/examples/redis/alert_system_flow.svg +127 -0
- data/examples/redis/dashboard_status_flow.svg +107 -0
- data/examples/redis/device_command_flow.svg +113 -0
- data/examples/redis/redis_transport_architecture.svg +115 -0
- data/examples/{smart_home_iot_dataflow.md → redis/smart_home_iot_dataflow.md} +4 -116
- data/examples/redis/smart_home_system_architecture.svg +133 -0
- data/examples/redis_enhanced/README.md +319 -0
- data/examples/redis_enhanced/enhanced_01_basic_patterns.rb +233 -0
- data/examples/redis_enhanced/enhanced_02_fluent_api.rb +331 -0
- data/examples/redis_enhanced/enhanced_03_dual_publishing.rb +281 -0
- data/examples/redis_enhanced/enhanced_04_advanced_routing.rb +419 -0
- data/examples/redis_queue/01_basic_messaging.rb +221 -0
- data/examples/redis_queue/01_comprehensive_examples.rb +508 -0
- data/examples/redis_queue/02_pattern_routing.rb +405 -0
- data/examples/redis_queue/03_fluent_api.rb +422 -0
- data/examples/redis_queue/04_load_balancing.rb +486 -0
- data/examples/redis_queue/05_microservices.rb +735 -0
- data/examples/redis_queue/06_emergency_alerts.rb +777 -0
- data/examples/redis_queue/07_queue_management.rb +587 -0
- data/examples/redis_queue/README.md +366 -0
- data/examples/redis_queue/enhanced_01_basic_patterns.rb +233 -0
- data/examples/redis_queue/enhanced_02_fluent_api.rb +331 -0
- data/examples/redis_queue/enhanced_03_dual_publishing.rb +281 -0
- data/examples/redis_queue/enhanced_04_advanced_routing.rb +419 -0
- data/examples/redis_queue/redis_queue_architecture.svg +148 -0
- data/ideas/README.md +41 -0
- data/ideas/agents.md +1001 -0
- data/ideas/database_transport.md +980 -0
- data/ideas/improvement.md +359 -0
- data/ideas/meshage.md +1788 -0
- data/ideas/message_discovery.md +178 -0
- data/ideas/message_schema.md +1381 -0
- data/lib/smart_message/.idea/.gitignore +8 -0
- data/lib/smart_message/.idea/markdown.xml +6 -0
- data/lib/smart_message/.idea/misc.xml +4 -0
- data/lib/smart_message/.idea/modules.xml +8 -0
- data/lib/smart_message/.idea/smart_message.iml +16 -0
- data/lib/smart_message/.idea/vcs.xml +6 -0
- data/lib/smart_message/addressing.rb +15 -0
- data/lib/smart_message/base.rb +0 -2
- data/lib/smart_message/configuration.rb +1 -1
- data/lib/smart_message/logger.rb +15 -4
- data/lib/smart_message/plugins.rb +5 -2
- data/lib/smart_message/serializer.rb +14 -0
- data/lib/smart_message/transport/redis_enhanced_transport.rb +399 -0
- data/lib/smart_message/transport/redis_queue_transport.rb +555 -0
- data/lib/smart_message/transport/registry.rb +1 -0
- data/lib/smart_message/transport.rb +34 -1
- data/lib/smart_message/version.rb +1 -1
- data/lib/smart_message.rb +5 -52
- data/mkdocs.yml +184 -0
- data/p2p_plan.md +326 -0
- data/p2p_roadmap.md +287 -0
- data/smart_message.gemspec +2 -0
- data/smart_message.svg +51 -0
- metadata +170 -44
- data/docs/README.md +0 -57
- data/examples/dead_letters.jsonl +0 -12
- data/examples/temp.txt +0 -94
- data/examples/tmux_chat/README.md +0 -283
- data/examples/tmux_chat/bot_agent.rb +0 -278
- data/examples/tmux_chat/human_agent.rb +0 -199
- data/examples/tmux_chat/room_monitor.rb +0 -160
- data/examples/tmux_chat/shared_chat_system.rb +0 -328
- data/examples/tmux_chat/start_chat_demo.sh +0 -190
- data/examples/tmux_chat/stop_chat_demo.sh +0 -22
- /data/docs/{properties.md → core-concepts/properties.md} +0 -0
- /data/docs/{ideas_to_think_about.md → development/ideas.md} +0 -0
@@ -0,0 +1,419 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/redis_queue/enhanced_04_advanced_routing.rb
|
3
|
+
# Redis Enhanced Transport - Advanced Routing and Filtering Demo
|
4
|
+
|
5
|
+
require_relative '../../lib/smart_message'
|
6
|
+
require 'smart_message/transport/redis_enhanced_transport'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
puts "🚀 Redis Enhanced Transport - Advanced Routing Demo"
|
10
|
+
puts "=" * 53
|
11
|
+
|
12
|
+
# Create enhanced Redis transport
|
13
|
+
transport = SmartMessage::Transport::RedisEnhancedTransport.new(
|
14
|
+
url: 'redis://localhost:6379',
|
15
|
+
db: 5, # Use database 5 for advanced routing examples
|
16
|
+
auto_subscribe: true
|
17
|
+
)
|
18
|
+
|
19
|
+
#==============================================================================
|
20
|
+
# Define Complex Microservices Message Classes
|
21
|
+
#==============================================================================
|
22
|
+
|
23
|
+
class ApiRequestMessage < SmartMessage::Base
|
24
|
+
from 'api-gateway'
|
25
|
+
|
26
|
+
transport transport
|
27
|
+
serializer SmartMessage::Serializer::Json.new
|
28
|
+
|
29
|
+
property :request_id, required: true
|
30
|
+
property :endpoint, required: true
|
31
|
+
property :method, required: true
|
32
|
+
property :user_id
|
33
|
+
property :service_target, required: true
|
34
|
+
|
35
|
+
def self.process(wrapper)
|
36
|
+
header, payload = wrapper.split
|
37
|
+
data = JSON.parse(payload)
|
38
|
+
|
39
|
+
puts "🌐 [API GATEWAY] #{data['method']} #{data['endpoint']}"
|
40
|
+
puts " Request ID: #{data['request_id']}"
|
41
|
+
puts " Target: #{data['service_target']}"
|
42
|
+
puts " User: #{data['user_id'] || 'anonymous'}"
|
43
|
+
puts " Route: #{header.from} → #{header.to}"
|
44
|
+
puts
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class DatabaseQueryMessage < SmartMessage::Base
|
49
|
+
from 'orm-layer'
|
50
|
+
to 'database-service'
|
51
|
+
|
52
|
+
transport transport
|
53
|
+
serializer SmartMessage::Serializer::Json.new
|
54
|
+
|
55
|
+
property :query_id, required: true
|
56
|
+
property :query_type, required: true # SELECT, INSERT, UPDATE, DELETE
|
57
|
+
property :table, required: true
|
58
|
+
property :execution_time_ms
|
59
|
+
|
60
|
+
def self.process(wrapper)
|
61
|
+
header, payload = wrapper.split
|
62
|
+
data = JSON.parse(payload)
|
63
|
+
|
64
|
+
puts "🗄️ [DATABASE] #{data['query_type']} on #{data['table']}"
|
65
|
+
puts " Query ID: #{data['query_id']}"
|
66
|
+
puts " Execution: #{data['execution_time_ms']}ms"
|
67
|
+
puts " Route: #{header.from} → #{header.to}"
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class LogMessage < SmartMessage::Base
|
73
|
+
from 'various-services'
|
74
|
+
to 'log-aggregator'
|
75
|
+
|
76
|
+
transport transport
|
77
|
+
serializer SmartMessage::Serializer::Json.new
|
78
|
+
|
79
|
+
property :log_id, required: true
|
80
|
+
property :level, required: true # DEBUG, INFO, WARN, ERROR, FATAL
|
81
|
+
property :service, required: true
|
82
|
+
property :message, required: true
|
83
|
+
property :context, default: {}
|
84
|
+
|
85
|
+
def self.process(wrapper)
|
86
|
+
header, payload = wrapper.split
|
87
|
+
data = JSON.parse(payload)
|
88
|
+
|
89
|
+
level_emoji = {
|
90
|
+
'DEBUG' => '🔍',
|
91
|
+
'INFO' => 'ℹ️',
|
92
|
+
'WARN' => '⚠️',
|
93
|
+
'ERROR' => '❌',
|
94
|
+
'FATAL' => '💀'
|
95
|
+
}[data['level']] || '📝'
|
96
|
+
|
97
|
+
puts "#{level_emoji} [LOG AGGREGATOR] #{data['level']} from #{data['service']}"
|
98
|
+
puts " #{data['message']}"
|
99
|
+
puts " Context: #{data['context']}" unless data['context'].empty?
|
100
|
+
puts " Route: #{header.from} → #{header.to}"
|
101
|
+
puts
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class MetricsMessage < SmartMessage::Base
|
106
|
+
from 'monitoring-agents'
|
107
|
+
to 'metrics-collector'
|
108
|
+
|
109
|
+
transport transport
|
110
|
+
serializer SmartMessage::Serializer::Json.new
|
111
|
+
|
112
|
+
property :metric_id, required: true
|
113
|
+
property :metric_name, required: true
|
114
|
+
property :value, required: true
|
115
|
+
property :tags, default: {}
|
116
|
+
property :timestamp, default: -> { Time.now.to_f }
|
117
|
+
|
118
|
+
def self.process(wrapper)
|
119
|
+
header, payload = wrapper.split
|
120
|
+
data = JSON.parse(payload)
|
121
|
+
|
122
|
+
puts "📊 [METRICS] #{data['metric_name']}: #{data['value']}"
|
123
|
+
puts " Tags: #{data['tags']}"
|
124
|
+
puts " From: #{header.from}"
|
125
|
+
puts
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#==============================================================================
|
130
|
+
# Advanced Routing Demonstration Functions
|
131
|
+
#==============================================================================
|
132
|
+
|
133
|
+
def setup_service_specific_routing(transport)
|
134
|
+
puts "🎯 Setting up service-specific routing patterns..."
|
135
|
+
puts
|
136
|
+
|
137
|
+
# Route API requests to specific services
|
138
|
+
transport.where.from('api-gateway').to('user-service').subscribe
|
139
|
+
transport.where.from('api-gateway').to('order-service').subscribe
|
140
|
+
transport.where.from('api-gateway').to('payment-service').subscribe
|
141
|
+
|
142
|
+
puts "✅ API Gateway routing configured for:"
|
143
|
+
puts " • user-service"
|
144
|
+
puts " • order-service"
|
145
|
+
puts " • payment-service"
|
146
|
+
puts
|
147
|
+
|
148
|
+
# Database queries from different ORM layers
|
149
|
+
transport.where.from('user-orm').type('DatabaseQueryMessage').subscribe
|
150
|
+
transport.where.from('order-orm').type('DatabaseQueryMessage').subscribe
|
151
|
+
transport.where.from('analytics-orm').type('DatabaseQueryMessage').subscribe
|
152
|
+
|
153
|
+
puts "✅ Database query routing configured for:"
|
154
|
+
puts " • user-orm queries"
|
155
|
+
puts " • order-orm queries"
|
156
|
+
puts " • analytics-orm queries"
|
157
|
+
puts
|
158
|
+
end
|
159
|
+
|
160
|
+
def setup_log_level_filtering(transport)
|
161
|
+
puts "📋 Setting up log level filtering patterns..."
|
162
|
+
puts
|
163
|
+
|
164
|
+
# Different log processing based on level and service
|
165
|
+
transport.subscribe_pattern("logmessage.user_service.log_aggregator")
|
166
|
+
transport.subscribe_pattern("logmessage.payment_service.log_aggregator")
|
167
|
+
transport.subscribe_pattern("logmessage.critical_service.log_aggregator")
|
168
|
+
|
169
|
+
puts "✅ Log filtering configured for:"
|
170
|
+
puts " • user-service logs"
|
171
|
+
puts " • payment-service logs"
|
172
|
+
puts " • critical-service logs"
|
173
|
+
puts
|
174
|
+
end
|
175
|
+
|
176
|
+
def setup_metrics_collection_routing(transport)
|
177
|
+
puts "📈 Setting up metrics collection routing..."
|
178
|
+
puts
|
179
|
+
|
180
|
+
# Collect metrics from different monitoring agents
|
181
|
+
transport.where.type('MetricsMessage').from('cpu-monitor').subscribe
|
182
|
+
transport.where.type('MetricsMessage').from('memory-monitor').subscribe
|
183
|
+
transport.where.type('MetricsMessage').from('disk-monitor').subscribe
|
184
|
+
transport.where.type('MetricsMessage').from('network-monitor').subscribe
|
185
|
+
|
186
|
+
puts "✅ Metrics collection configured for:"
|
187
|
+
puts " • CPU monitoring"
|
188
|
+
puts " • Memory monitoring"
|
189
|
+
puts " • Disk monitoring"
|
190
|
+
puts " • Network monitoring"
|
191
|
+
puts
|
192
|
+
end
|
193
|
+
|
194
|
+
def demonstrate_dynamic_routing
|
195
|
+
puts "🔄 Demonstrating dynamic routing scenarios..."
|
196
|
+
puts
|
197
|
+
|
198
|
+
# Scenario 1: API Gateway routes to different services
|
199
|
+
api_requests = [
|
200
|
+
{ service: 'user-service', endpoint: '/users/profile', method: 'GET' },
|
201
|
+
{ service: 'order-service', endpoint: '/orders/create', method: 'POST' },
|
202
|
+
{ service: 'payment-service', endpoint: '/payments/process', method: 'POST' }
|
203
|
+
]
|
204
|
+
|
205
|
+
api_requests.each_with_index do |req, i|
|
206
|
+
message = ApiRequestMessage.new(
|
207
|
+
request_id: "REQ-#{Time.now.to_i}-#{i}",
|
208
|
+
endpoint: req[:endpoint],
|
209
|
+
method: req[:method],
|
210
|
+
service_target: req[:service],
|
211
|
+
user_id: "user_#{100 + i}"
|
212
|
+
)
|
213
|
+
message.to(req[:service]) # Dynamic routing
|
214
|
+
message.publish
|
215
|
+
|
216
|
+
sleep 0.1
|
217
|
+
end
|
218
|
+
|
219
|
+
puts "✅ Published 3 API requests with dynamic routing"
|
220
|
+
puts
|
221
|
+
end
|
222
|
+
|
223
|
+
def demonstrate_database_query_routing
|
224
|
+
puts "🗄️ Demonstrating database query routing..."
|
225
|
+
puts
|
226
|
+
|
227
|
+
queries = [
|
228
|
+
{ orm: 'user-orm', type: 'SELECT', table: 'users', time: 15 },
|
229
|
+
{ orm: 'order-orm', type: 'INSERT', table: 'orders', time: 8 },
|
230
|
+
{ orm: 'analytics-orm', type: 'UPDATE', table: 'metrics', time: 45 }
|
231
|
+
]
|
232
|
+
|
233
|
+
queries.each_with_index do |query, i|
|
234
|
+
message = DatabaseQueryMessage.new(
|
235
|
+
query_id: "QRY-#{Time.now.to_i}-#{i}",
|
236
|
+
query_type: query[:type],
|
237
|
+
table: query[:table],
|
238
|
+
execution_time_ms: query[:time]
|
239
|
+
)
|
240
|
+
message.from(query[:orm]) # Dynamic sender
|
241
|
+
message.publish
|
242
|
+
|
243
|
+
sleep 0.1
|
244
|
+
end
|
245
|
+
|
246
|
+
puts "✅ Published 3 database queries from different ORM layers"
|
247
|
+
puts
|
248
|
+
end
|
249
|
+
|
250
|
+
def demonstrate_log_aggregation_routing
|
251
|
+
puts "📋 Demonstrating log aggregation routing..."
|
252
|
+
puts
|
253
|
+
|
254
|
+
log_entries = [
|
255
|
+
{ service: 'user-service', level: 'INFO', msg: 'User authentication successful' },
|
256
|
+
{ service: 'payment-service', level: 'ERROR', msg: 'Credit card validation failed' },
|
257
|
+
{ service: 'critical-service', level: 'FATAL', msg: 'Database connection lost' },
|
258
|
+
{ service: 'user-service', level: 'DEBUG', msg: 'Cache miss for user profile' }
|
259
|
+
]
|
260
|
+
|
261
|
+
log_entries.each_with_index do |log, i|
|
262
|
+
message = LogMessage.new(
|
263
|
+
log_id: "LOG-#{Time.now.to_i}-#{i}",
|
264
|
+
level: log[:level],
|
265
|
+
service: log[:service],
|
266
|
+
message: log[:msg],
|
267
|
+
context: {
|
268
|
+
thread_id: "thread_#{i}",
|
269
|
+
request_id: "req_#{100 + i}"
|
270
|
+
}
|
271
|
+
)
|
272
|
+
message.from(log[:service])
|
273
|
+
message.publish
|
274
|
+
|
275
|
+
sleep 0.1
|
276
|
+
end
|
277
|
+
|
278
|
+
puts "✅ Published 4 log entries from different services"
|
279
|
+
puts
|
280
|
+
end
|
281
|
+
|
282
|
+
def demonstrate_metrics_collection
|
283
|
+
puts "📊 Demonstrating metrics collection..."
|
284
|
+
puts
|
285
|
+
|
286
|
+
metrics = [
|
287
|
+
{ agent: 'cpu-monitor', name: 'cpu.usage.percent', value: 78.5, tags: { host: 'web-01' } },
|
288
|
+
{ agent: 'memory-monitor', name: 'memory.used.bytes', value: 2147483648, tags: { host: 'web-01' } },
|
289
|
+
{ agent: 'disk-monitor', name: 'disk.free.percent', value: 45.2, tags: { mount: '/data' } },
|
290
|
+
{ agent: 'network-monitor', name: 'network.bytes.sent', value: 1048576, tags: { interface: 'eth0' } }
|
291
|
+
]
|
292
|
+
|
293
|
+
metrics.each_with_index do |metric, i|
|
294
|
+
message = MetricsMessage.new(
|
295
|
+
metric_id: "MET-#{Time.now.to_i}-#{i}",
|
296
|
+
metric_name: metric[:name],
|
297
|
+
value: metric[:value],
|
298
|
+
tags: metric[:tags]
|
299
|
+
)
|
300
|
+
message.from(metric[:agent])
|
301
|
+
message.publish
|
302
|
+
|
303
|
+
sleep 0.1
|
304
|
+
end
|
305
|
+
|
306
|
+
puts "✅ Published 4 metrics from different monitoring agents"
|
307
|
+
puts
|
308
|
+
end
|
309
|
+
|
310
|
+
def show_routing_patterns_summary
|
311
|
+
puts "📋 Active Routing Patterns Summary:"
|
312
|
+
puts "=" * 40
|
313
|
+
puts
|
314
|
+
|
315
|
+
puts "🎯 Service-to-Service Routing:"
|
316
|
+
puts " • api-gateway → user-service"
|
317
|
+
puts " • api-gateway → order-service"
|
318
|
+
puts " • api-gateway → payment-service"
|
319
|
+
puts
|
320
|
+
|
321
|
+
puts "🗄️ Database Query Routing:"
|
322
|
+
puts " • user-orm → database-service"
|
323
|
+
puts " • order-orm → database-service"
|
324
|
+
puts " • analytics-orm → database-service"
|
325
|
+
puts
|
326
|
+
|
327
|
+
puts "📋 Log Aggregation Routing:"
|
328
|
+
puts " • user-service → log-aggregator"
|
329
|
+
puts " • payment-service → log-aggregator"
|
330
|
+
puts " • critical-service → log-aggregator"
|
331
|
+
puts
|
332
|
+
|
333
|
+
puts "📊 Metrics Collection Routing:"
|
334
|
+
puts " • cpu-monitor → metrics-collector"
|
335
|
+
puts " • memory-monitor → metrics-collector"
|
336
|
+
puts " • disk-monitor → metrics-collector"
|
337
|
+
puts " • network-monitor → metrics-collector"
|
338
|
+
puts
|
339
|
+
end
|
340
|
+
|
341
|
+
#==============================================================================
|
342
|
+
# Main Demonstration
|
343
|
+
#==============================================================================
|
344
|
+
|
345
|
+
begin
|
346
|
+
puts "🔧 Checking Redis connection..."
|
347
|
+
unless transport.connected?
|
348
|
+
puts "❌ Redis not available. Please start Redis server:"
|
349
|
+
puts " brew services start redis # macOS"
|
350
|
+
puts " sudo service redis start # Linux"
|
351
|
+
exit 1
|
352
|
+
end
|
353
|
+
puts "✅ Connected to Redis"
|
354
|
+
puts
|
355
|
+
|
356
|
+
# Set up advanced routing patterns
|
357
|
+
setup_service_specific_routing(transport)
|
358
|
+
setup_log_level_filtering(transport)
|
359
|
+
setup_metrics_collection_routing(transport)
|
360
|
+
|
361
|
+
# Subscribe message classes
|
362
|
+
ApiRequestMessage.subscribe
|
363
|
+
DatabaseQueryMessage.subscribe
|
364
|
+
LogMessage.subscribe
|
365
|
+
MetricsMessage.subscribe
|
366
|
+
|
367
|
+
puts "⏳ Waiting for subscriptions to be established..."
|
368
|
+
sleep 1
|
369
|
+
|
370
|
+
# Demonstrate different routing scenarios
|
371
|
+
demonstrate_dynamic_routing
|
372
|
+
sleep 0.5
|
373
|
+
|
374
|
+
demonstrate_database_query_routing
|
375
|
+
sleep 0.5
|
376
|
+
|
377
|
+
demonstrate_log_aggregation_routing
|
378
|
+
sleep 0.5
|
379
|
+
|
380
|
+
demonstrate_metrics_collection
|
381
|
+
sleep 1
|
382
|
+
|
383
|
+
puts "⏳ Processing messages (waiting 3 seconds)..."
|
384
|
+
sleep 3
|
385
|
+
|
386
|
+
# Show summary
|
387
|
+
show_routing_patterns_summary
|
388
|
+
|
389
|
+
# Show active pattern subscriptions
|
390
|
+
puts "🔍 Active Pattern Subscriptions:"
|
391
|
+
pattern_subscriptions = transport.instance_variable_get(:@pattern_subscriptions)
|
392
|
+
if pattern_subscriptions && pattern_subscriptions.any?
|
393
|
+
pattern_subscriptions.each_with_index do |pattern, i|
|
394
|
+
puts " #{i + 1}. #{pattern}"
|
395
|
+
end
|
396
|
+
else
|
397
|
+
puts " No pattern subscriptions found"
|
398
|
+
end
|
399
|
+
puts
|
400
|
+
|
401
|
+
puts "🎉 Advanced Routing Demo completed!"
|
402
|
+
puts
|
403
|
+
puts "💡 Advanced Routing Benefits:"
|
404
|
+
puts " • Precise message targeting with multiple conditions"
|
405
|
+
puts " • Dynamic routing based on message content"
|
406
|
+
puts " • Service-specific pattern matching"
|
407
|
+
puts " • Complex microservices communication patterns"
|
408
|
+
puts " • Flexible subscription management"
|
409
|
+
|
410
|
+
rescue Interrupt
|
411
|
+
puts "\n👋 Demo interrupted by user"
|
412
|
+
rescue => e
|
413
|
+
puts "💥 Error: #{e.message}"
|
414
|
+
puts e.backtrace[0..3]
|
415
|
+
ensure
|
416
|
+
puts "\n🧹 Cleaning up..."
|
417
|
+
transport&.disconnect
|
418
|
+
puts "✅ Disconnected from Redis"
|
419
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/redis_queue/01_basic_messaging.rb
|
3
|
+
# Basic Redis Queue Transport messaging demonstration
|
4
|
+
|
5
|
+
require_relative '../../lib/smart_message'
|
6
|
+
require 'async'
|
7
|
+
|
8
|
+
puts "🚀 Redis Queue Transport - Basic Messaging Demo"
|
9
|
+
puts "=" * 50
|
10
|
+
|
11
|
+
# Configure SmartMessage to use Redis Queue transport
|
12
|
+
SmartMessage.configure do |config|
|
13
|
+
config.transport = :redis_queue
|
14
|
+
config.transport_options = {
|
15
|
+
url: 'redis://localhost:6379',
|
16
|
+
db: 1, # Use database 1 for examples
|
17
|
+
queue_prefix: 'demo_queue',
|
18
|
+
exchange_name: 'smart_message',
|
19
|
+
test_mode: false # Enable consumer tasks for real processing
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
#==============================================================================
|
24
|
+
# Define Message Classes
|
25
|
+
#==============================================================================
|
26
|
+
|
27
|
+
class WelcomeMessage < SmartMessage::Base
|
28
|
+
transport :redis_queue
|
29
|
+
|
30
|
+
property :user_name, required: true
|
31
|
+
property :email
|
32
|
+
property :signup_date, default: -> { Time.now.strftime('%Y-%m-%d %H:%M:%S') }
|
33
|
+
|
34
|
+
def process
|
35
|
+
puts "👋 Welcome #{user_name}! (#{email}) - Signed up: #{signup_date}"
|
36
|
+
puts " Message processed at: #{Time.now.strftime('%H:%M:%S.%L')}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class OrderNotification < SmartMessage::Base
|
41
|
+
transport :redis_queue
|
42
|
+
|
43
|
+
property :order_id, required: true
|
44
|
+
property :customer_name, required: true
|
45
|
+
property :total_amount, required: true
|
46
|
+
property :status, default: 'pending'
|
47
|
+
|
48
|
+
def process
|
49
|
+
puts "📦 Order #{order_id}: $#{total_amount} for #{customer_name} [#{status}]"
|
50
|
+
puts " Order processed at: #{Time.now.strftime('%H:%M:%S.%L')}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class SystemAlert < SmartMessage::Base
|
55
|
+
transport :redis_queue
|
56
|
+
|
57
|
+
property :alert_type, required: true
|
58
|
+
property :message, required: true
|
59
|
+
property :severity, default: 'info'
|
60
|
+
property :timestamp, default: -> { Time.now }
|
61
|
+
|
62
|
+
def process
|
63
|
+
icon = case severity
|
64
|
+
when 'critical' then '🚨'
|
65
|
+
when 'warning' then '⚠️'
|
66
|
+
when 'info' then 'ℹ️'
|
67
|
+
else '📢'
|
68
|
+
end
|
69
|
+
|
70
|
+
puts "#{icon} [#{alert_type.upcase}] #{message}"
|
71
|
+
puts " Severity: #{severity} - Time: #{timestamp.strftime('%H:%M:%S')}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#==============================================================================
|
76
|
+
# Basic Publishing and Subscription Demo
|
77
|
+
#==============================================================================
|
78
|
+
|
79
|
+
Async do
|
80
|
+
puts "\n📤 Publishing Messages..."
|
81
|
+
|
82
|
+
# Subscribe to all message types
|
83
|
+
puts "Setting up subscribers..."
|
84
|
+
WelcomeMessage.subscribe
|
85
|
+
OrderNotification.subscribe
|
86
|
+
SystemAlert.subscribe
|
87
|
+
|
88
|
+
# Wait for subscribers to initialize
|
89
|
+
sleep 0.5
|
90
|
+
|
91
|
+
# Publish welcome messages
|
92
|
+
puts "\n1️⃣ Publishing Welcome Messages:"
|
93
|
+
welcome1 = WelcomeMessage.new(
|
94
|
+
user_name: 'Alice Johnson',
|
95
|
+
email: 'alice@example.com'
|
96
|
+
)
|
97
|
+
welcome1.publish
|
98
|
+
|
99
|
+
welcome2 = WelcomeMessage.new(
|
100
|
+
user_name: 'Bob Smith',
|
101
|
+
email: 'bob@example.com'
|
102
|
+
)
|
103
|
+
welcome2.publish
|
104
|
+
|
105
|
+
# Publish order notifications
|
106
|
+
puts "\n2️⃣ Publishing Order Notifications:"
|
107
|
+
order1 = OrderNotification.new(
|
108
|
+
order_id: 'ORD-001',
|
109
|
+
customer_name: 'Alice Johnson',
|
110
|
+
total_amount: 149.99,
|
111
|
+
status: 'confirmed'
|
112
|
+
)
|
113
|
+
order1.publish
|
114
|
+
|
115
|
+
order2 = OrderNotification.new(
|
116
|
+
order_id: 'ORD-002',
|
117
|
+
customer_name: 'Bob Smith',
|
118
|
+
total_amount: 89.50,
|
119
|
+
status: 'processing'
|
120
|
+
)
|
121
|
+
order2.publish
|
122
|
+
|
123
|
+
# Publish system alerts
|
124
|
+
puts "\n3️⃣ Publishing System Alerts:"
|
125
|
+
alert1 = SystemAlert.new(
|
126
|
+
alert_type: 'database',
|
127
|
+
message: 'Database connection restored after brief outage',
|
128
|
+
severity: 'info'
|
129
|
+
)
|
130
|
+
alert1.publish
|
131
|
+
|
132
|
+
alert2 = SystemAlert.new(
|
133
|
+
alert_type: 'security',
|
134
|
+
message: 'Multiple failed login attempts detected',
|
135
|
+
severity: 'warning'
|
136
|
+
)
|
137
|
+
alert2.publish
|
138
|
+
|
139
|
+
alert3 = SystemAlert.new(
|
140
|
+
alert_type: 'system',
|
141
|
+
message: 'Critical: Disk usage above 95%',
|
142
|
+
severity: 'critical'
|
143
|
+
)
|
144
|
+
alert3.publish
|
145
|
+
|
146
|
+
# Wait for message processing
|
147
|
+
puts "\n⏳ Processing messages..."
|
148
|
+
sleep 3
|
149
|
+
|
150
|
+
#============================================================================
|
151
|
+
# Message Statistics
|
152
|
+
#============================================================================
|
153
|
+
|
154
|
+
puts "\n📊 Message Statistics:"
|
155
|
+
|
156
|
+
# Get transport instance for statistics
|
157
|
+
transport = SmartMessage::Transport::RedisQueueTransport.new(
|
158
|
+
url: 'redis://localhost:6379',
|
159
|
+
db: 1,
|
160
|
+
queue_prefix: 'demo_queue',
|
161
|
+
exchange_name: 'smart_message',
|
162
|
+
test_mode: true # Statistics only, no consumers
|
163
|
+
)
|
164
|
+
|
165
|
+
# Show queue statistics
|
166
|
+
stats = transport.queue_stats
|
167
|
+
if stats.any?
|
168
|
+
stats.each do |queue_name, info|
|
169
|
+
puts " Queue: #{queue_name}"
|
170
|
+
puts " Length: #{info[:length]} messages"
|
171
|
+
puts " Pattern: #{info[:pattern] || 'N/A'}"
|
172
|
+
puts " Consumers: #{info[:consumers] || 0}"
|
173
|
+
puts ""
|
174
|
+
end
|
175
|
+
else
|
176
|
+
puts " No queues found (all messages processed successfully)"
|
177
|
+
end
|
178
|
+
|
179
|
+
transport.disconnect
|
180
|
+
|
181
|
+
#============================================================================
|
182
|
+
# Performance Demonstration
|
183
|
+
#============================================================================
|
184
|
+
|
185
|
+
puts "\n🏃♀️ Performance Test - Publishing 100 messages rapidly:"
|
186
|
+
|
187
|
+
start_time = Time.now
|
188
|
+
|
189
|
+
100.times do |i|
|
190
|
+
message = SystemAlert.new(
|
191
|
+
alert_type: 'performance_test',
|
192
|
+
message: "Performance test message ##{i + 1}",
|
193
|
+
severity: 'info'
|
194
|
+
)
|
195
|
+
message.publish
|
196
|
+
end
|
197
|
+
|
198
|
+
end_time = Time.now
|
199
|
+
duration = end_time - start_time
|
200
|
+
|
201
|
+
puts "✅ Published 100 messages in #{duration.round(3)} seconds"
|
202
|
+
puts " Rate: #{(100 / duration).round(1)} messages/second"
|
203
|
+
|
204
|
+
# Wait for processing
|
205
|
+
sleep 2
|
206
|
+
end
|
207
|
+
|
208
|
+
puts "\n🎯 Basic messaging demonstration completed!"
|
209
|
+
puts " ✓ Published welcome messages"
|
210
|
+
puts " ✓ Published order notifications"
|
211
|
+
puts " ✓ Published system alerts"
|
212
|
+
puts " ✓ Demonstrated high-throughput publishing"
|
213
|
+
puts " ✓ All messages processed via Redis Queue transport"
|
214
|
+
|
215
|
+
puts "\n💡 Key Features Demonstrated:"
|
216
|
+
puts " • Simple pub/sub messaging with Async framework"
|
217
|
+
puts " • Automatic message serialization"
|
218
|
+
puts " • Queue-based reliable delivery"
|
219
|
+
puts " • Multiple message types"
|
220
|
+
puts " • High-performance publishing"
|
221
|
+
puts " • Fiber-based concurrency for scalable processing"
|