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,422 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/redis_queue/03_fluent_api.rb
|
3
|
+
# Demonstration of the Fluent API for Redis Queue Transport
|
4
|
+
|
5
|
+
require_relative '../../lib/smart_message'
|
6
|
+
require 'async'
|
7
|
+
|
8
|
+
puts "🎨 Redis Queue Transport - Fluent API Demo"
|
9
|
+
puts "=" * 50
|
10
|
+
|
11
|
+
#==============================================================================
|
12
|
+
# Transport Setup
|
13
|
+
#==============================================================================
|
14
|
+
|
15
|
+
transport = SmartMessage::Transport::RedisQueueTransport.new(
|
16
|
+
url: 'redis://localhost:6379',
|
17
|
+
db: 3, # Use database 3 for fluent API examples
|
18
|
+
queue_prefix: 'fluent_demo',
|
19
|
+
exchange_name: 'smart_message',
|
20
|
+
consumer_timeout: 1, # 1 second timeout
|
21
|
+
test_mode: false # Enable consumer tasks
|
22
|
+
)
|
23
|
+
|
24
|
+
#==============================================================================
|
25
|
+
# Message Classes
|
26
|
+
#==============================================================================
|
27
|
+
|
28
|
+
class TaskMessage < SmartMessage::Base
|
29
|
+
transport :redis_queue, {
|
30
|
+
url: 'redis://localhost:6379',
|
31
|
+
db: 3,
|
32
|
+
queue_prefix: 'fluent_demo',
|
33
|
+
exchange_name: 'smart_message',
|
34
|
+
test_mode: false
|
35
|
+
}
|
36
|
+
|
37
|
+
property :task_id, required: true
|
38
|
+
property :task_type, required: true
|
39
|
+
property :assigned_to
|
40
|
+
property :priority, default: 'medium'
|
41
|
+
property :estimated_hours, default: 1
|
42
|
+
|
43
|
+
def process
|
44
|
+
priority_icon = case priority
|
45
|
+
when 'critical' then '🔥'
|
46
|
+
when 'high' then '⚡'
|
47
|
+
when 'medium' then '⚖️'
|
48
|
+
when 'low' then '🐌'
|
49
|
+
else '📝'
|
50
|
+
end
|
51
|
+
|
52
|
+
puts "#{priority_icon} Task #{task_id} [#{task_type}] → #{assigned_to} (#{estimated_hours}h)"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class EventMessage < SmartMessage::Base
|
57
|
+
transport :redis_queue, {
|
58
|
+
url: 'redis://localhost:6379',
|
59
|
+
db: 3,
|
60
|
+
queue_prefix: 'fluent_demo',
|
61
|
+
exchange_name: 'smart_message',
|
62
|
+
test_mode: false
|
63
|
+
}
|
64
|
+
|
65
|
+
property :event_type, required: true
|
66
|
+
property :user_id
|
67
|
+
property :session_id
|
68
|
+
property :metadata, default: {}
|
69
|
+
property :timestamp, default: -> { Time.now }
|
70
|
+
|
71
|
+
def process
|
72
|
+
puts "📈 Event: #{event_type} | User: #{user_id} | Session: #{session_id}"
|
73
|
+
puts " Metadata: #{metadata.inspect}" if metadata.any?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class AlertMessage < SmartMessage::Base
|
78
|
+
transport :redis_queue, {
|
79
|
+
url: 'redis://localhost:6379',
|
80
|
+
db: 3,
|
81
|
+
queue_prefix: 'fluent_demo',
|
82
|
+
exchange_name: 'smart_message',
|
83
|
+
test_mode: false
|
84
|
+
}
|
85
|
+
|
86
|
+
property :alert_id, required: true
|
87
|
+
property :service, required: true
|
88
|
+
property :level, required: true
|
89
|
+
property :description, required: true
|
90
|
+
property :tags, default: []
|
91
|
+
|
92
|
+
def process
|
93
|
+
level_icon = case level
|
94
|
+
when 'critical' then '🚨'
|
95
|
+
when 'warning' then '⚠️'
|
96
|
+
when 'info' then 'ℹ️'
|
97
|
+
else '📢'
|
98
|
+
end
|
99
|
+
|
100
|
+
puts "#{level_icon} Alert #{alert_id}: #{service} - #{description}"
|
101
|
+
puts " Tags: #{tags.join(', ')}" if tags.any?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#==============================================================================
|
106
|
+
# Fluent API Subscription Examples
|
107
|
+
#==============================================================================
|
108
|
+
|
109
|
+
Async do
|
110
|
+
puts "\n🎭 Setting up Fluent API subscriptions:"
|
111
|
+
|
112
|
+
# Example 1: Simple FROM subscription
|
113
|
+
puts "1️⃣ Subscribe to messages FROM 'api_service'"
|
114
|
+
subscription1 = transport.where
|
115
|
+
.from('api_service')
|
116
|
+
.subscribe do |message_class, message_data|
|
117
|
+
data = JSON.parse(message_data)
|
118
|
+
puts "🔵 API Service Message: #{message_class} - #{data['task_id'] || data['event_type'] || data['alert_id']}"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Example 2: Simple TO subscription
|
122
|
+
puts "2️⃣ Subscribe to messages TO 'task_processor'"
|
123
|
+
subscription2 = transport.where
|
124
|
+
.to('task_processor')
|
125
|
+
.subscribe do |message_class, message_data|
|
126
|
+
data = JSON.parse(message_data)
|
127
|
+
puts "🟢 Task Processor: #{message_class} - #{data['task_id'] || data['task_type']}"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Example 3: Type-specific subscription
|
131
|
+
puts "3️⃣ Subscribe to TaskMessage types only"
|
132
|
+
subscription3 = transport.where
|
133
|
+
.type('TaskMessage')
|
134
|
+
.subscribe do |message_class, message_data|
|
135
|
+
data = JSON.parse(message_data)
|
136
|
+
puts "📋 Task Only: #{data['task_id']} - #{data['task_type']} [#{data['priority']}]"
|
137
|
+
end
|
138
|
+
|
139
|
+
# Example 4: Combined FROM and TO
|
140
|
+
puts "4️⃣ Subscribe FROM 'web_app' TO 'event_processor'"
|
141
|
+
subscription4 = transport.where
|
142
|
+
.from('web_app')
|
143
|
+
.to('event_processor')
|
144
|
+
.subscribe do |message_class, message_data|
|
145
|
+
data = JSON.parse(message_data)
|
146
|
+
puts "🌐➡️📊 Web→Events: #{message_class} - #{data['event_type']}"
|
147
|
+
end
|
148
|
+
|
149
|
+
# Example 5: Consumer group with load balancing
|
150
|
+
puts "5️⃣ Subscribe with consumer group 'alert_handlers'"
|
151
|
+
subscription5 = transport.where
|
152
|
+
.type('AlertMessage')
|
153
|
+
.consumer_group('alert_handlers')
|
154
|
+
.subscribe do |message_class, message_data|
|
155
|
+
data = JSON.parse(message_data)
|
156
|
+
fiber_id = Async::Task.current.object_id.to_s[-4..-1]
|
157
|
+
puts "⚡ Fiber-#{fiber_id}: Alert #{data['alert_id']} [#{data['level']}]"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Example 6: Complex multi-criteria subscription
|
161
|
+
puts "6️⃣ Subscribe FROM admin services TO monitoring with group"
|
162
|
+
subscription6 = transport.where
|
163
|
+
.from(/^admin_.*/) # Regex pattern for admin services
|
164
|
+
.to('monitoring_service')
|
165
|
+
.consumer_group('monitoring_workers')
|
166
|
+
.subscribe do |message_class, message_data|
|
167
|
+
data = JSON.parse(message_data)
|
168
|
+
puts "👑📊 Admin→Monitor: #{message_class}"
|
169
|
+
end
|
170
|
+
|
171
|
+
# Example 7: Type and destination combination
|
172
|
+
puts "7️⃣ Subscribe to EventMessage TO analytics services"
|
173
|
+
subscription7 = transport.where
|
174
|
+
.type('EventMessage')
|
175
|
+
.to(/.*analytics.*/) # Any service with 'analytics' in name
|
176
|
+
.subscribe do |message_class, message_data|
|
177
|
+
data = JSON.parse(message_data)
|
178
|
+
puts "📈🎯 Events→Analytics: #{data['event_type']} - User #{data['user_id']}"
|
179
|
+
end
|
180
|
+
|
181
|
+
# Wait for subscriptions to initialize
|
182
|
+
sleep 1
|
183
|
+
|
184
|
+
#============================================================================
|
185
|
+
# Pattern Building Demonstration
|
186
|
+
#============================================================================
|
187
|
+
|
188
|
+
puts "\n🏗️ Pattern Building Examples:"
|
189
|
+
|
190
|
+
# Show how different fluent combinations create patterns
|
191
|
+
builders = [
|
192
|
+
transport.where.from('api_service'),
|
193
|
+
transport.where.to('task_processor'),
|
194
|
+
transport.where.type('TaskMessage'),
|
195
|
+
transport.where.from('web_app').to('event_processor'),
|
196
|
+
transport.where.type('AlertMessage').from('monitoring'),
|
197
|
+
transport.where.to('analytics_service').type('EventMessage')
|
198
|
+
]
|
199
|
+
|
200
|
+
builders.each_with_index do |builder, i|
|
201
|
+
pattern = builder.build
|
202
|
+
puts "#{i + 1}. Pattern: '#{pattern}'"
|
203
|
+
end
|
204
|
+
|
205
|
+
#============================================================================
|
206
|
+
# Message Publishing Examples
|
207
|
+
#============================================================================
|
208
|
+
|
209
|
+
puts "\n📤 Publishing messages to demonstrate fluent subscriptions:"
|
210
|
+
|
211
|
+
# Messages FROM api_service (triggers subscription 1)
|
212
|
+
puts "\n🔸 Messages FROM api_service:"
|
213
|
+
TaskMessage.new(
|
214
|
+
task_id: 'TASK-001',
|
215
|
+
task_type: 'data_processing',
|
216
|
+
assigned_to: 'task_processor',
|
217
|
+
priority: 'high',
|
218
|
+
_sm_header: { from: 'api_service', to: 'task_processor' }
|
219
|
+
).publish
|
220
|
+
|
221
|
+
EventMessage.new(
|
222
|
+
event_type: 'api_call',
|
223
|
+
user_id: 'user123',
|
224
|
+
session_id: 'sess456',
|
225
|
+
metadata: { endpoint: '/api/tasks', method: 'POST' },
|
226
|
+
_sm_header: { from: 'api_service', to: 'analytics_service' }
|
227
|
+
).publish
|
228
|
+
|
229
|
+
# Messages TO task_processor (triggers subscription 2)
|
230
|
+
puts "\n🔸 Messages TO task_processor:"
|
231
|
+
TaskMessage.new(
|
232
|
+
task_id: 'TASK-002',
|
233
|
+
task_type: 'image_processing',
|
234
|
+
assigned_to: 'task_processor',
|
235
|
+
priority: 'medium',
|
236
|
+
estimated_hours: 3,
|
237
|
+
_sm_header: { from: 'upload_service', to: 'task_processor' }
|
238
|
+
).publish
|
239
|
+
|
240
|
+
TaskMessage.new(
|
241
|
+
task_id: 'TASK-003',
|
242
|
+
task_type: 'email_processing',
|
243
|
+
assigned_to: 'task_processor',
|
244
|
+
priority: 'low',
|
245
|
+
_sm_header: { from: 'mail_service', to: 'task_processor' }
|
246
|
+
).publish
|
247
|
+
|
248
|
+
# TaskMessage types (triggers subscription 3)
|
249
|
+
puts "\n🔸 Various TaskMessage types:"
|
250
|
+
TaskMessage.new(
|
251
|
+
task_id: 'TASK-004',
|
252
|
+
task_type: 'backup_database',
|
253
|
+
assigned_to: 'backup_service',
|
254
|
+
priority: 'critical',
|
255
|
+
estimated_hours: 2,
|
256
|
+
_sm_header: { from: 'scheduler', to: 'backup_service' }
|
257
|
+
).publish
|
258
|
+
|
259
|
+
# Web app to event processor (triggers subscription 4)
|
260
|
+
puts "\n🔸 Web app to event processor:"
|
261
|
+
EventMessage.new(
|
262
|
+
event_type: 'page_view',
|
263
|
+
user_id: 'user789',
|
264
|
+
session_id: 'sess123',
|
265
|
+
metadata: { page: '/dashboard', referrer: '/login' },
|
266
|
+
_sm_header: { from: 'web_app', to: 'event_processor' }
|
267
|
+
).publish
|
268
|
+
|
269
|
+
EventMessage.new(
|
270
|
+
event_type: 'button_click',
|
271
|
+
user_id: 'user789',
|
272
|
+
session_id: 'sess123',
|
273
|
+
metadata: { button_id: 'save_profile', page: '/settings' },
|
274
|
+
_sm_header: { from: 'web_app', to: 'event_processor' }
|
275
|
+
).publish
|
276
|
+
|
277
|
+
# Alert messages for consumer groups (triggers subscription 5)
|
278
|
+
puts "\n🔸 Alert messages for load balancing:"
|
279
|
+
3.times do |i|
|
280
|
+
AlertMessage.new(
|
281
|
+
alert_id: "ALERT-#{sprintf('%03d', i + 1)}",
|
282
|
+
service: ['database', 'cache', 'api'][i],
|
283
|
+
level: ['critical', 'warning', 'info'][i],
|
284
|
+
description: ["Database connection lost", "Cache hit rate below 80%", "API response time normal"][i],
|
285
|
+
tags: [['db', 'urgent'], ['cache', 'performance'], ['api', 'info']][i],
|
286
|
+
_sm_header: { from: 'monitoring_service', to: 'alert_handler' }
|
287
|
+
).publish
|
288
|
+
end
|
289
|
+
|
290
|
+
# Admin messages to monitoring (triggers subscription 6)
|
291
|
+
puts "\n🔸 Admin messages to monitoring:"
|
292
|
+
AlertMessage.new(
|
293
|
+
alert_id: 'ADMIN-001',
|
294
|
+
service: 'user_management',
|
295
|
+
level: 'info',
|
296
|
+
description: 'User privileges updated for admin user',
|
297
|
+
tags: ['admin', 'security'],
|
298
|
+
_sm_header: { from: 'admin_panel', to: 'monitoring_service' }
|
299
|
+
).publish
|
300
|
+
|
301
|
+
EventMessage.new(
|
302
|
+
event_type: 'admin_action',
|
303
|
+
user_id: 'admin123',
|
304
|
+
metadata: { action: 'user_created', target_user: 'newuser456' },
|
305
|
+
_sm_header: { from: 'admin_service', to: 'monitoring_service' }
|
306
|
+
).publish
|
307
|
+
|
308
|
+
# Event messages to analytics (triggers subscription 7)
|
309
|
+
puts "\n🔸 Event messages to analytics services:"
|
310
|
+
EventMessage.new(
|
311
|
+
event_type: 'purchase_completed',
|
312
|
+
user_id: 'customer123',
|
313
|
+
session_id: 'shop_session_789',
|
314
|
+
metadata: { order_id: 'ORD-789', amount: 149.99, items: 3 },
|
315
|
+
_sm_header: { from: 'checkout_service', to: 'user_analytics' }
|
316
|
+
).publish
|
317
|
+
|
318
|
+
EventMessage.new(
|
319
|
+
event_type: 'search_query',
|
320
|
+
user_id: 'customer456',
|
321
|
+
metadata: { query: 'wireless headphones', results: 24 },
|
322
|
+
_sm_header: { from: 'search_service', to: 'search_analytics' }
|
323
|
+
).publish
|
324
|
+
|
325
|
+
# Wait for message processing
|
326
|
+
puts "\n⏳ Processing all messages..."
|
327
|
+
sleep 5
|
328
|
+
|
329
|
+
#============================================================================
|
330
|
+
# Chained Fluent API Examples
|
331
|
+
#============================================================================
|
332
|
+
|
333
|
+
puts "\n🔗 Advanced Fluent API Chaining:"
|
334
|
+
|
335
|
+
# Example of building and modifying subscriptions
|
336
|
+
puts "\n8️⃣ Dynamic subscription building:"
|
337
|
+
base_subscription = transport.where.type('TaskMessage')
|
338
|
+
|
339
|
+
# Add criteria dynamically
|
340
|
+
urgent_tasks = base_subscription.from('urgent_processor')
|
341
|
+
pattern1 = urgent_tasks.build
|
342
|
+
puts "Dynamic pattern 1: #{pattern1}"
|
343
|
+
|
344
|
+
# Build different variations
|
345
|
+
analytics_tasks = base_subscription.to(/.*analytics.*/)
|
346
|
+
pattern2 = analytics_tasks.build
|
347
|
+
puts "Dynamic pattern 2: #{pattern2}"
|
348
|
+
|
349
|
+
# Complex chaining
|
350
|
+
complex_subscription = transport.where
|
351
|
+
.type('EventMessage')
|
352
|
+
.from(/^(web|mobile)_app$/) # From web or mobile app
|
353
|
+
.to(/.*analytics.*/) # To any analytics service
|
354
|
+
.consumer_group('analytics_processors')
|
355
|
+
|
356
|
+
pattern3 = complex_subscription.build
|
357
|
+
puts "Complex pattern: #{pattern3}"
|
358
|
+
|
359
|
+
# Subscribe with the complex pattern
|
360
|
+
complex_subscription.subscribe do |message_class, message_data|
|
361
|
+
data = JSON.parse(message_data)
|
362
|
+
puts "🎯 Complex Match: #{data['event_type']} from mobile/web → analytics"
|
363
|
+
end
|
364
|
+
|
365
|
+
# Test the complex subscription
|
366
|
+
EventMessage.new(
|
367
|
+
event_type: 'app_launch',
|
368
|
+
user_id: 'mobile_user123',
|
369
|
+
metadata: { platform: 'iOS', version: '2.1.0' },
|
370
|
+
_sm_header: { from: 'mobile_app', to: 'mobile_analytics' }
|
371
|
+
).publish
|
372
|
+
|
373
|
+
sleep 2
|
374
|
+
|
375
|
+
#============================================================================
|
376
|
+
# Subscription Management
|
377
|
+
#============================================================================
|
378
|
+
|
379
|
+
puts "\n📊 Fluent API Statistics:"
|
380
|
+
|
381
|
+
# Show routing table
|
382
|
+
routing_table = transport.routing_table
|
383
|
+
puts "\nRouting patterns created by fluent API:"
|
384
|
+
routing_table.each_with_index do |(pattern, queues), i|
|
385
|
+
puts "#{i + 1}. '#{pattern}' → #{queues.size} queue(s)"
|
386
|
+
end
|
387
|
+
|
388
|
+
# Show queue statistics
|
389
|
+
stats = transport.queue_stats
|
390
|
+
puts "\nQueue statistics:"
|
391
|
+
total_messages = 0
|
392
|
+
stats.each do |queue_name, info|
|
393
|
+
total_messages += info[:length]
|
394
|
+
puts " #{queue_name}: #{info[:length]} messages"
|
395
|
+
end
|
396
|
+
|
397
|
+
puts "\nTotal messages in all queues: #{total_messages}"
|
398
|
+
|
399
|
+
# Cleanup
|
400
|
+
transport.disconnect
|
401
|
+
end
|
402
|
+
|
403
|
+
puts "\n🎨 Fluent API demonstration completed!"
|
404
|
+
|
405
|
+
puts "\n💡 Fluent API Features Demonstrated:"
|
406
|
+
puts " ✓ .from() - Source-based filtering"
|
407
|
+
puts " ✓ .to() - Destination-based filtering"
|
408
|
+
puts " ✓ .type() - Message type filtering"
|
409
|
+
puts " ✓ .consumer_group() - Load balancing"
|
410
|
+
puts " ✓ Method chaining for complex criteria"
|
411
|
+
puts " ✓ Regex patterns in from/to filters"
|
412
|
+
puts " ✓ Dynamic subscription building"
|
413
|
+
puts " ✓ Pattern generation and inspection"
|
414
|
+
|
415
|
+
puts "\n🚀 Key Benefits:"
|
416
|
+
puts " • Readable, expressive subscription syntax"
|
417
|
+
puts " • Type-safe subscription building"
|
418
|
+
puts " • Flexible criteria combination"
|
419
|
+
puts " • Runtime pattern inspection"
|
420
|
+
puts " • Easy consumer group management with Async fibers"
|
421
|
+
puts " • Complex routing made simple"
|
422
|
+
puts " • Fiber-based concurrency for massive scalability"
|