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,735 @@
1
+ #!/usr/bin/env ruby
2
+ # examples/redis_queue/05_microservices.rb
3
+ # Microservices architecture with Redis Queue Transport
4
+
5
+ require_relative '../../lib/smart_message'
6
+
7
+ puts "🏗️ Redis Queue Transport - Microservices Architecture Demo"
8
+ puts "=" * 60
9
+
10
+ #==============================================================================
11
+ # Transport Configuration for Microservices
12
+ #==============================================================================
13
+
14
+ # Configure SmartMessage for microservices architecture
15
+ SmartMessage.configure do |config|
16
+ config.transport = :redis_queue
17
+ config.transport_options = {
18
+ url: 'redis://localhost:6379',
19
+ db: 5, # Use database 5 for microservices demo
20
+ queue_prefix: 'microservices',
21
+ consumer_group: 'service_workers'
22
+ }
23
+ end
24
+
25
+ #==============================================================================
26
+ # Service Request/Response Message Classes
27
+ #==============================================================================
28
+
29
+ class ServiceRequest < SmartMessage::Base
30
+ transport :redis_queue
31
+
32
+ property :request_id, required: true
33
+ property :service, required: true
34
+ property :operation, required: true
35
+ property :payload, default: {}
36
+ property :correlation_id
37
+ property :timestamp, default: -> { Time.now }
38
+
39
+ def process
40
+ puts "📥 Service Request: #{service}.#{operation} [#{request_id}]"
41
+ puts " Payload: #{payload.inspect}" if payload.any?
42
+ end
43
+ end
44
+
45
+ class ServiceResponse < SmartMessage::Base
46
+ transport :redis_queue
47
+
48
+ property :request_id, required: true
49
+ property :service, required: true
50
+ property :status, required: true # success, error, timeout
51
+ property :result, default: {}
52
+ property :error_message
53
+ property :processing_time_ms
54
+ property :timestamp, default: -> { Time.now }
55
+
56
+ def process
57
+ status_icon = case status
58
+ when 'success' then '✅'
59
+ when 'error' then '❌'
60
+ when 'timeout' then '⏰'
61
+ else '❓'
62
+ end
63
+
64
+ puts "#{status_icon} Service Response: #{service} [#{request_id}] - #{status}"
65
+ puts " Result: #{result.inspect}" if result.any?
66
+ puts " Error: #{error_message}" if error_message
67
+ puts " Processing time: #{processing_time_ms}ms" if processing_time_ms
68
+ end
69
+ end
70
+
71
+ class ServiceEvent < SmartMessage::Base
72
+ transport :redis_queue
73
+
74
+ property :event_id, required: true
75
+ property :event_type, required: true
76
+ property :service, required: true
77
+ property :entity_id
78
+ property :data, default: {}
79
+ property :timestamp, default: -> { Time.now }
80
+
81
+ def process
82
+ puts "📡 Service Event: #{service}.#{event_type} [#{event_id}]"
83
+ puts " Entity: #{entity_id}" if entity_id
84
+ puts " Data: #{data.inspect}" if data.any?
85
+ end
86
+ end
87
+
88
+ #==============================================================================
89
+ # Microservice Implementations
90
+ #==============================================================================
91
+
92
+ class ApiGatewayService
93
+ def initialize(transport)
94
+ @transport = transport
95
+ @request_counter = 0
96
+ setup_subscriptions
97
+ end
98
+
99
+ def setup_subscriptions
100
+ # Listen for responses from downstream services
101
+ @transport.where
102
+ .to('api_gateway')
103
+ .subscribe do |message_class, message_data|
104
+ data = JSON.parse(message_data)
105
+ puts "🌐 API Gateway received response from #{data['service']}: #{data['status']}"
106
+ end
107
+ end
108
+
109
+ def handle_user_request(operation, payload = {})
110
+ @request_counter += 1
111
+ request_id = "REQ-#{sprintf('%06d', @request_counter)}"
112
+
113
+ puts "\n🌐 API Gateway: Processing #{operation} request [#{request_id}]"
114
+
115
+ # Route to appropriate service based on operation
116
+ service = case operation
117
+ when 'create_user', 'get_user', 'update_user' then 'user_service'
118
+ when 'create_order', 'get_order', 'cancel_order' then 'order_service'
119
+ when 'process_payment', 'refund_payment' then 'payment_service'
120
+ when 'send_email', 'send_sms' then 'notification_service'
121
+ else 'unknown_service'
122
+ end
123
+
124
+ ServiceRequest.new(
125
+ request_id: request_id,
126
+ service: service,
127
+ operation: operation,
128
+ payload: payload,
129
+ correlation_id: SecureRandom.uuid,
130
+ _sm_header: {
131
+ from: 'api_gateway',
132
+ to: service
133
+ }
134
+ ).publish
135
+
136
+ request_id
137
+ end
138
+ end
139
+
140
+ class UserService
141
+ def initialize(transport)
142
+ @transport = transport
143
+ @users = {} # In-memory user store for demo
144
+ setup_subscriptions
145
+ end
146
+
147
+ def setup_subscriptions
148
+ @transport.where
149
+ .to('user_service')
150
+ .subscribe do |message_class, message_data|
151
+ handle_request(JSON.parse(message_data))
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def handle_request(data)
158
+ request_id = data['request_id']
159
+ operation = data['operation']
160
+ payload = data['payload'] || {}
161
+
162
+ puts "👤 User Service: Handling #{operation} [#{request_id}]"
163
+
164
+ start_time = Time.now
165
+ result, status, error = case operation
166
+ when 'create_user'
167
+ create_user(payload)
168
+ when 'get_user'
169
+ get_user(payload['user_id'])
170
+ when 'update_user'
171
+ update_user(payload['user_id'], payload)
172
+ else
173
+ [nil, 'error', 'Unknown operation']
174
+ end
175
+ end_time = Time.now
176
+
177
+ # Send response back to API Gateway
178
+ ServiceResponse.new(
179
+ request_id: request_id,
180
+ service: 'user_service',
181
+ status: status,
182
+ result: result || {},
183
+ error_message: error,
184
+ processing_time_ms: ((end_time - start_time) * 1000).round(2),
185
+ _sm_header: {
186
+ from: 'user_service',
187
+ to: 'api_gateway'
188
+ }
189
+ ).publish
190
+
191
+ # Emit event if successful
192
+ if status == 'success' && operation == 'create_user'
193
+ ServiceEvent.new(
194
+ event_id: SecureRandom.uuid,
195
+ event_type: 'user_created',
196
+ service: 'user_service',
197
+ entity_id: result[:user_id],
198
+ data: { name: result[:name], email: result[:email] },
199
+ _sm_header: {
200
+ from: 'user_service',
201
+ to: 'event_bus'
202
+ }
203
+ ).publish
204
+ end
205
+ end
206
+
207
+ def create_user(payload)
208
+ user_id = "user_#{SecureRandom.hex(4)}"
209
+ user_data = {
210
+ user_id: user_id,
211
+ name: payload['name'],
212
+ email: payload['email'],
213
+ created_at: Time.now.iso8601
214
+ }
215
+
216
+ @users[user_id] = user_data
217
+ [user_data, 'success', nil]
218
+ rescue => e
219
+ [nil, 'error', e.message]
220
+ end
221
+
222
+ def get_user(user_id)
223
+ if user_id && @users[user_id]
224
+ [@users[user_id], 'success', nil]
225
+ else
226
+ [nil, 'error', 'User not found']
227
+ end
228
+ end
229
+
230
+ def update_user(user_id, updates)
231
+ if user_id && @users[user_id]
232
+ @users[user_id].merge!(updates)
233
+ [@users[user_id], 'success', nil]
234
+ else
235
+ [nil, 'error', 'User not found']
236
+ end
237
+ end
238
+ end
239
+
240
+ class OrderService
241
+ def initialize(transport)
242
+ @transport = transport
243
+ @orders = {}
244
+ setup_subscriptions
245
+ end
246
+
247
+ def setup_subscriptions
248
+ @transport.where
249
+ .to('order_service')
250
+ .subscribe do |message_class, message_data|
251
+ handle_request(JSON.parse(message_data))
252
+ end
253
+ end
254
+
255
+ private
256
+
257
+ def handle_request(data)
258
+ request_id = data['request_id']
259
+ operation = data['operation']
260
+ payload = data['payload'] || {}
261
+
262
+ puts "📦 Order Service: Handling #{operation} [#{request_id}]"
263
+
264
+ start_time = Time.now
265
+ result, status, error = case operation
266
+ when 'create_order'
267
+ create_order(payload)
268
+ when 'get_order'
269
+ get_order(payload['order_id'])
270
+ when 'cancel_order'
271
+ cancel_order(payload['order_id'])
272
+ else
273
+ [nil, 'error', 'Unknown operation']
274
+ end
275
+ end_time = Time.now
276
+
277
+ # Send response back
278
+ ServiceResponse.new(
279
+ request_id: request_id,
280
+ service: 'order_service',
281
+ status: status,
282
+ result: result || {},
283
+ error_message: error,
284
+ processing_time_ms: ((end_time - start_time) * 1000).round(2),
285
+ _sm_header: {
286
+ from: 'order_service',
287
+ to: 'api_gateway'
288
+ }
289
+ ).publish
290
+
291
+ # Emit events for successful operations
292
+ if status == 'success'
293
+ emit_order_event(operation, result)
294
+ end
295
+ end
296
+
297
+ def create_order(payload)
298
+ order_id = "order_#{SecureRandom.hex(4)}"
299
+ order_data = {
300
+ order_id: order_id,
301
+ user_id: payload['user_id'],
302
+ items: payload['items'] || [],
303
+ total_amount: payload['total_amount'],
304
+ status: 'pending',
305
+ created_at: Time.now.iso8601
306
+ }
307
+
308
+ @orders[order_id] = order_data
309
+ [order_data, 'success', nil]
310
+ rescue => e
311
+ [nil, 'error', e.message]
312
+ end
313
+
314
+ def get_order(order_id)
315
+ if order_id && @orders[order_id]
316
+ [@orders[order_id], 'success', nil]
317
+ else
318
+ [nil, 'error', 'Order not found']
319
+ end
320
+ end
321
+
322
+ def cancel_order(order_id)
323
+ if order_id && @orders[order_id]
324
+ @orders[order_id][:status] = 'cancelled'
325
+ [@orders[order_id], 'success', nil]
326
+ else
327
+ [nil, 'error', 'Order not found']
328
+ end
329
+ end
330
+
331
+ def emit_order_event(operation, order_data)
332
+ event_type = case operation
333
+ when 'create_order' then 'order_created'
334
+ when 'cancel_order' then 'order_cancelled'
335
+ else "order_#{operation}"
336
+ end
337
+
338
+ ServiceEvent.new(
339
+ event_id: SecureRandom.uuid,
340
+ event_type: event_type,
341
+ service: 'order_service',
342
+ entity_id: order_data[:order_id],
343
+ data: order_data,
344
+ _sm_header: {
345
+ from: 'order_service',
346
+ to: 'event_bus'
347
+ }
348
+ ).publish
349
+ end
350
+ end
351
+
352
+ class PaymentService
353
+ def initialize(transport)
354
+ @transport = transport
355
+ @payments = {}
356
+ setup_subscriptions
357
+ end
358
+
359
+ def setup_subscriptions
360
+ @transport.where
361
+ .to('payment_service')
362
+ .subscribe do |message_class, message_data|
363
+ handle_request(JSON.parse(message_data))
364
+ end
365
+ end
366
+
367
+ private
368
+
369
+ def handle_request(data)
370
+ request_id = data['request_id']
371
+ operation = data['operation']
372
+ payload = data['payload'] || {}
373
+
374
+ puts "💳 Payment Service: Handling #{operation} [#{request_id}]"
375
+
376
+ start_time = Time.now
377
+ result, status, error = case operation
378
+ when 'process_payment'
379
+ process_payment(payload)
380
+ when 'refund_payment'
381
+ refund_payment(payload['payment_id'])
382
+ else
383
+ [nil, 'error', 'Unknown operation']
384
+ end
385
+ end_time = Time.now
386
+
387
+ ServiceResponse.new(
388
+ request_id: request_id,
389
+ service: 'payment_service',
390
+ status: status,
391
+ result: result || {},
392
+ error_message: error,
393
+ processing_time_ms: ((end_time - start_time) * 1000).round(2),
394
+ _sm_header: {
395
+ from: 'payment_service',
396
+ to: 'api_gateway'
397
+ }
398
+ ).publish
399
+
400
+ if status == 'success'
401
+ emit_payment_event(operation, result)
402
+ end
403
+ end
404
+
405
+ def process_payment(payload)
406
+ payment_id = "payment_#{SecureRandom.hex(4)}"
407
+
408
+ # Simulate payment processing
409
+ sleep(0.5) # Simulate external API call
410
+
411
+ # Random success/failure for demo
412
+ if rand < 0.9 # 90% success rate
413
+ payment_data = {
414
+ payment_id: payment_id,
415
+ order_id: payload['order_id'],
416
+ amount: payload['amount'],
417
+ currency: payload['currency'] || 'USD',
418
+ status: 'completed',
419
+ transaction_id: "txn_#{SecureRandom.hex(6)}",
420
+ processed_at: Time.now.iso8601
421
+ }
422
+
423
+ @payments[payment_id] = payment_data
424
+ [payment_data, 'success', nil]
425
+ else
426
+ [nil, 'error', 'Payment declined by bank']
427
+ end
428
+ rescue => e
429
+ [nil, 'error', e.message]
430
+ end
431
+
432
+ def refund_payment(payment_id)
433
+ if payment_id && @payments[payment_id]
434
+ @payments[payment_id][:status] = 'refunded'
435
+ @payments[payment_id][:refunded_at] = Time.now.iso8601
436
+ [@payments[payment_id], 'success', nil]
437
+ else
438
+ [nil, 'error', 'Payment not found']
439
+ end
440
+ end
441
+
442
+ def emit_payment_event(operation, payment_data)
443
+ event_type = case operation
444
+ when 'process_payment' then 'payment_processed'
445
+ when 'refund_payment' then 'payment_refunded'
446
+ else "payment_#{operation}"
447
+ end
448
+
449
+ ServiceEvent.new(
450
+ event_id: SecureRandom.uuid,
451
+ event_type: event_type,
452
+ service: 'payment_service',
453
+ entity_id: payment_data[:payment_id],
454
+ data: payment_data,
455
+ _sm_header: {
456
+ from: 'payment_service',
457
+ to: 'event_bus'
458
+ }
459
+ ).publish
460
+ end
461
+ end
462
+
463
+ class NotificationService
464
+ def initialize(transport)
465
+ @transport = transport
466
+ setup_subscriptions
467
+ end
468
+
469
+ def setup_subscriptions
470
+ # Subscribe to direct requests
471
+ @transport.where
472
+ .to('notification_service')
473
+ .subscribe do |message_class, message_data|
474
+ handle_request(JSON.parse(message_data))
475
+ end
476
+
477
+ # Subscribe to events for automatic notifications
478
+ @transport.where
479
+ .to('event_bus')
480
+ .subscribe do |message_class, message_data|
481
+ handle_event(JSON.parse(message_data)) if message_class == 'ServiceEvent'
482
+ end
483
+ end
484
+
485
+ private
486
+
487
+ def handle_request(data)
488
+ request_id = data['request_id']
489
+ operation = data['operation']
490
+ payload = data['payload'] || {}
491
+
492
+ puts "📧 Notification Service: Handling #{operation} [#{request_id}]"
493
+
494
+ result, status, error = case operation
495
+ when 'send_email'
496
+ send_email(payload)
497
+ when 'send_sms'
498
+ send_sms(payload)
499
+ else
500
+ [nil, 'error', 'Unknown operation']
501
+ end
502
+
503
+ ServiceResponse.new(
504
+ request_id: request_id,
505
+ service: 'notification_service',
506
+ status: status,
507
+ result: result || {},
508
+ error_message: error,
509
+ _sm_header: {
510
+ from: 'notification_service',
511
+ to: 'api_gateway'
512
+ }
513
+ ).publish
514
+ end
515
+
516
+ def handle_event(event_data)
517
+ event_type = event_data['event_type']
518
+
519
+ puts "📧 Notification Service: Handling event #{event_type}"
520
+
521
+ case event_type
522
+ when 'user_created'
523
+ send_welcome_email(event_data['data'])
524
+ when 'order_created'
525
+ send_order_confirmation(event_data['data'])
526
+ when 'payment_processed'
527
+ send_payment_confirmation(event_data['data'])
528
+ end
529
+ end
530
+
531
+ def send_email(payload)
532
+ puts " ✉️ Sending email to #{payload['to']}: #{payload['subject']}"
533
+ { message_id: SecureRandom.uuid, status: 'sent' }
534
+ rescue => e
535
+ [nil, 'error', e.message]
536
+ end
537
+
538
+ def send_sms(payload)
539
+ puts " 📱 Sending SMS to #{payload['phone']}: #{payload['message'][0..30]}..."
540
+ [{ message_id: SecureRandom.uuid, status: 'sent' }, 'success', nil]
541
+ rescue => e
542
+ [nil, 'error', e.message]
543
+ end
544
+
545
+ def send_welcome_email(user_data)
546
+ puts " 🎉 Sending welcome email to #{user_data['email']}"
547
+ end
548
+
549
+ def send_order_confirmation(order_data)
550
+ puts " 📦 Sending order confirmation for #{order_data['order_id']}"
551
+ end
552
+
553
+ def send_payment_confirmation(payment_data)
554
+ puts " 💳 Sending payment confirmation for #{payment_data['payment_id']}"
555
+ end
556
+ end
557
+
558
+ #==============================================================================
559
+ # Service Initialization
560
+ #==============================================================================
561
+
562
+ puts "\n🔧 Initializing microservices..."
563
+
564
+ transport = SmartMessage::Transport::RedisQueueTransport.new(
565
+ url: 'redis://localhost:6379',
566
+ db: 5,
567
+ queue_prefix: 'microservices',
568
+ consumer_group: 'service_workers',
569
+ block_time: 1000
570
+ )
571
+
572
+ # Initialize all services
573
+ api_gateway = ApiGatewayService.new(transport)
574
+ user_service = UserService.new(transport)
575
+ order_service = OrderService.new(transport)
576
+ payment_service = PaymentService.new(transport)
577
+ notification_service = NotificationService.new(transport)
578
+
579
+ # Wait for services to initialize
580
+ sleep 2
581
+
582
+ puts "✅ All microservices initialized and ready"
583
+
584
+ #==============================================================================
585
+ # End-to-End Workflow Demonstration
586
+ #==============================================================================
587
+
588
+ puts "\n🎭 Demonstrating end-to-end e-commerce workflow:"
589
+
590
+ # Workflow 1: User Registration and Welcome
591
+ puts "\n1️⃣ User Registration Workflow:"
592
+ user_req_id = api_gateway.handle_user_request('create_user', {
593
+ 'name' => 'Alice Johnson',
594
+ 'email' => 'alice@example.com'
595
+ })
596
+
597
+ sleep 2
598
+
599
+ # Workflow 2: Order Creation and Processing
600
+ puts "\n2️⃣ Order Creation Workflow:"
601
+ order_req_id = api_gateway.handle_user_request('create_order', {
602
+ 'user_id' => 'user_1234',
603
+ 'items' => [
604
+ { 'sku' => 'BOOK-001', 'name' => 'Ruby Programming', 'price' => 29.99 },
605
+ { 'sku' => 'BOOK-002', 'name' => 'Design Patterns', 'price' => 39.99 }
606
+ ],
607
+ 'total_amount' => 69.98
608
+ })
609
+
610
+ sleep 2
611
+
612
+ # Workflow 3: Payment Processing
613
+ puts "\n3️⃣ Payment Processing Workflow:"
614
+ payment_req_id = api_gateway.handle_user_request('process_payment', {
615
+ 'order_id' => 'order_5678',
616
+ 'amount' => 69.98,
617
+ 'currency' => 'USD',
618
+ 'payment_method' => 'credit_card'
619
+ })
620
+
621
+ sleep 3
622
+
623
+ # Workflow 4: Notification Sending
624
+ puts "\n4️⃣ Direct Notification Workflow:"
625
+ notification_req_id = api_gateway.handle_user_request('send_email', {
626
+ 'to' => 'customer@example.com',
627
+ 'subject' => 'Your order has been shipped!',
628
+ 'template' => 'shipping_notification'
629
+ })
630
+
631
+ sleep 2
632
+
633
+ #==============================================================================
634
+ # Complex Multi-Service Scenarios
635
+ #==============================================================================
636
+
637
+ puts "\n🔄 Complex multi-service scenarios:"
638
+
639
+ # Scenario 1: Parallel service calls
640
+ puts "\n📡 Scenario 1: Parallel service operations"
641
+ requests = [
642
+ api_gateway.handle_user_request('get_user', { 'user_id' => 'user_1234' }),
643
+ api_gateway.handle_user_request('get_order', { 'order_id' => 'order_5678' }),
644
+ api_gateway.handle_user_request('send_sms', { 'phone' => '+1234567890', 'message' => 'Your order is ready!' })
645
+ ]
646
+
647
+ puts " Parallel requests: #{requests.join(', ')}"
648
+
649
+ sleep 3
650
+
651
+ # Scenario 2: Service dependency chain
652
+ puts "\n🔗 Scenario 2: Service dependency chain"
653
+ puts " Creating user → Creating order → Processing payment → Sending confirmation"
654
+
655
+ # Step 1: Create user
656
+ user_req = api_gateway.handle_user_request('create_user', {
657
+ 'name' => 'Bob Smith',
658
+ 'email' => 'bob@example.com'
659
+ })
660
+
661
+ sleep 1
662
+
663
+ # Step 2: Create order for user
664
+ order_req = api_gateway.handle_user_request('create_order', {
665
+ 'user_id' => 'user_' + SecureRandom.hex(4),
666
+ 'items' => [{ 'sku' => 'GADGET-001', 'name' => 'Smart Watch', 'price' => 199.99 }],
667
+ 'total_amount' => 199.99
668
+ })
669
+
670
+ sleep 1
671
+
672
+ # Step 3: Process payment
673
+ payment_req = api_gateway.handle_user_request('process_payment', {
674
+ 'order_id' => 'order_' + SecureRandom.hex(4),
675
+ 'amount' => 199.99,
676
+ 'payment_method' => 'paypal'
677
+ })
678
+
679
+ sleep 2
680
+
681
+ # Scenario 3: Error handling and compensation
682
+ puts "\n⚠️ Scenario 3: Error handling demonstration"
683
+ error_req = api_gateway.handle_user_request('get_user', { 'user_id' => 'nonexistent_user' })
684
+
685
+ sleep 2
686
+
687
+ #==============================================================================
688
+ # Service Statistics and Monitoring
689
+ #==============================================================================
690
+
691
+ puts "\n📊 Microservices Architecture Statistics:"
692
+
693
+ # Show queue statistics
694
+ stats = transport.queue_stats
695
+ puts "\nService queue lengths:"
696
+ service_queues = stats.select { |name, _| name.include?('_service') }
697
+ service_queues.each do |queue_name, info|
698
+ service_name = queue_name.split('.').last.gsub('_', ' ').titleize
699
+ puts " #{service_name}: #{info[:length]} pending requests"
700
+ end
701
+
702
+ # Show routing patterns
703
+ routing_table = transport.routing_table
704
+ puts "\nActive service routing patterns:"
705
+ routing_table.each do |pattern, queues|
706
+ puts " Pattern: '#{pattern}' → #{queues.size} queue(s)"
707
+ end
708
+
709
+ puts "\nTotal active queues: #{stats.size}"
710
+ total_messages = stats.values.sum { |info| info[:length] }
711
+ puts "Total pending messages: #{total_messages}"
712
+
713
+ # Cleanup
714
+ transport.disconnect
715
+
716
+ puts "\n🏗️ Microservices architecture demonstration completed!"
717
+
718
+ puts "\n💡 Microservices Patterns Demonstrated:"
719
+ puts " ✓ Service-to-service communication"
720
+ puts " ✓ Request/response pattern"
721
+ puts " ✓ Event-driven architecture"
722
+ puts " ✓ Asynchronous message processing"
723
+ puts " ✓ Service isolation and independence"
724
+ puts " ✓ Centralized API Gateway pattern"
725
+ puts " ✓ Event bus for cross-service notifications"
726
+ puts " ✓ Error handling and fault tolerance"
727
+
728
+ puts "\n🚀 Key Architecture Benefits:"
729
+ puts " • Loose coupling between services"
730
+ puts " • High-performance async communication"
731
+ puts " • Scalable service-specific queues"
732
+ puts " • Event-driven reactive patterns"
733
+ puts " • Built-in message persistence"
734
+ puts " • Service discovery via routing patterns"
735
+ puts " • Comprehensive monitoring and observability"