smart_message 0.0.12 → 0.0.16
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/.gitignore +1 -0
- data/CHANGELOG.md +155 -1
- data/Gemfile.lock +6 -6
- data/README.md +71 -25
- data/docs/core-concepts/architecture.md +5 -10
- data/docs/getting-started/examples.md +0 -12
- data/docs/getting-started/quick-start.md +4 -9
- data/docs/index.md +6 -4
- data/docs/reference/serializers.md +160 -488
- data/docs/reference/transports.md +47 -146
- data/docs/transports/memory-transport.md +2 -1
- data/docs/transports/multi-transport.md +484 -0
- data/docs/transports/redis-transport-comparison.md +215 -350
- data/docs/transports/redis-transport.md +3 -22
- data/examples/README.md +6 -9
- data/examples/city_scenario/README.md +1 -1
- data/examples/city_scenario/messages/emergency_911_message.rb +0 -1
- data/examples/city_scenario/messages/emergency_resolved_message.rb +0 -1
- data/examples/city_scenario/messages/fire_dispatch_message.rb +0 -1
- data/examples/city_scenario/messages/fire_emergency_message.rb +0 -1
- data/examples/city_scenario/messages/health_check_message.rb +0 -1
- data/examples/city_scenario/messages/health_status_message.rb +0 -1
- data/examples/city_scenario/messages/police_dispatch_message.rb +0 -1
- data/examples/city_scenario/messages/silent_alarm_message.rb +0 -1
- data/examples/file/00_run_all_file_demos.rb +260 -0
- data/examples/file/01_basic_file_transport_demo.rb +237 -0
- data/examples/file/02_fifo_transport_demo.rb +289 -0
- data/examples/file/03_file_watching_demo.rb +332 -0
- data/examples/file/04_multi_transport_file_demo.rb +432 -0
- data/examples/file/README.md +257 -0
- data/examples/memory/00_run_all_demos.rb +317 -0
- data/examples/memory/01_message_deduplication_demo.rb +18 -32
- data/examples/memory/02_dead_letter_queue_demo.rb +9 -12
- data/examples/memory/03_point_to_point_orders.rb +3 -5
- data/examples/memory/04_publish_subscribe_events.rb +15 -16
- data/examples/memory/05_many_to_many_chat.rb +19 -22
- data/examples/memory/06_stdout_publish_only.rb +145 -0
- data/examples/memory/07_proc_handlers_demo.rb +13 -14
- data/examples/memory/08_custom_logger_demo.rb +136 -140
- data/examples/memory/09_error_handling_demo.rb +7 -10
- data/examples/memory/10_entity_addressing_basic.rb +25 -31
- data/examples/memory/11_entity_addressing_with_filtering.rb +32 -36
- data/examples/memory/12_regex_filtering_microservices.rb +10 -11
- data/examples/memory/13_header_block_configuration.rb +0 -5
- data/examples/memory/14_global_configuration_demo.rb +12 -14
- data/examples/memory/15_logger_demo.rb +0 -1
- data/examples/memory/README.md +37 -20
- data/examples/memory/log/demo_app.log.1 +100 -0
- data/examples/memory/log/demo_app.log.2 +100 -0
- data/examples/multi_transport_example.rb +114 -0
- data/examples/redis/01_smart_home_iot_demo.rb +20 -24
- data/examples/redis/README.md +0 -2
- data/examples/utilities/box_it.rb +12 -0
- data/examples/utilities/doing.rb +19 -0
- data/examples/utilities/temp.md +28 -0
- data/lib/smart_message/base.rb +24 -17
- data/lib/smart_message/configuration.rb +2 -23
- data/lib/smart_message/dead_letter_queue.rb +1 -1
- data/lib/smart_message/errors.rb +3 -0
- data/lib/smart_message/header.rb +1 -1
- data/lib/smart_message/logger/default.rb +1 -1
- data/lib/smart_message/messaging.rb +37 -66
- data/lib/smart_message/plugins.rb +42 -41
- data/lib/smart_message/serializer/base.rb +1 -1
- data/lib/smart_message/serializer.rb +3 -2
- data/lib/smart_message/subscription.rb +18 -20
- data/lib/smart_message/transport/async_publish_queue.rb +284 -0
- data/lib/smart_message/transport/base.rb +42 -8
- data/lib/smart_message/transport/fifo_operations.rb +264 -0
- data/lib/smart_message/transport/file_operations.rb +200 -0
- data/lib/smart_message/transport/file_transport.rb +149 -0
- data/lib/smart_message/transport/file_watching.rb +72 -0
- data/lib/smart_message/transport/memory_transport.rb +23 -4
- data/lib/smart_message/transport/partitioned_files.rb +46 -0
- data/lib/smart_message/transport/redis_transport.rb +11 -0
- data/lib/smart_message/transport/registry.rb +0 -1
- data/lib/smart_message/transport/stdout_transport.rb +73 -41
- data/lib/smart_message/transport/stdout_transport.rb.backup +88 -0
- data/lib/smart_message/transport.rb +0 -1
- data/lib/smart_message/version.rb +1 -1
- metadata +25 -37
- data/docs/guides/redis-queue-getting-started.md +0 -697
- data/docs/guides/redis-queue-patterns.md +0 -889
- data/docs/guides/redis-queue-production.md +0 -1091
- data/docs/transports/redis-enhanced-transport.md +0 -524
- data/docs/transports/redis-queue-transport.md +0 -1304
- data/examples/redis_enhanced/README.md +0 -319
- data/examples/redis_enhanced/enhanced_01_basic_patterns.rb +0 -233
- data/examples/redis_enhanced/enhanced_02_fluent_api.rb +0 -331
- data/examples/redis_enhanced/enhanced_03_dual_publishing.rb +0 -281
- data/examples/redis_enhanced/enhanced_04_advanced_routing.rb +0 -419
- data/examples/redis_queue/01_basic_messaging.rb +0 -221
- data/examples/redis_queue/01_comprehensive_examples.rb +0 -508
- data/examples/redis_queue/02_pattern_routing.rb +0 -405
- data/examples/redis_queue/03_fluent_api.rb +0 -422
- data/examples/redis_queue/04_load_balancing.rb +0 -486
- data/examples/redis_queue/05_microservices.rb +0 -735
- data/examples/redis_queue/06_emergency_alerts.rb +0 -777
- data/examples/redis_queue/07_queue_management.rb +0 -587
- data/examples/redis_queue/README.md +0 -366
- data/examples/redis_queue/enhanced_01_basic_patterns.rb +0 -233
- data/examples/redis_queue/enhanced_02_fluent_api.rb +0 -331
- data/examples/redis_queue/enhanced_03_dual_publishing.rb +0 -281
- data/examples/redis_queue/enhanced_04_advanced_routing.rb +0 -419
- data/examples/redis_queue/redis_queue_architecture.svg +0 -148
- data/ideas/README.md +0 -41
- data/ideas/agents.md +0 -1001
- data/ideas/database_transport.md +0 -980
- data/ideas/improvement.md +0 -359
- data/ideas/meshage.md +0 -1788
- data/ideas/message_discovery.md +0 -178
- data/ideas/message_schema.md +0 -1381
- data/lib/smart_message/transport/redis_enhanced_transport.rb +0 -399
- data/lib/smart_message/transport/redis_queue_transport.rb +0 -555
- data/lib/smart_message/wrapper.rb.bak +0 -132
- /data/examples/memory/{06_pretty_print_demo.rb → 16_pretty_print_demo.rb} +0 -0
@@ -0,0 +1,317 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/memory/00_run_all_demos.rb
|
3
|
+
#
|
4
|
+
# Master Demo Runner - Executes All SmartMessage Memory Transport Examples
|
5
|
+
#
|
6
|
+
# This script runs all the demo programs in the examples/memory directory
|
7
|
+
# in sequence, with clear banners to show which demo is currently running.
|
8
|
+
|
9
|
+
require 'fileutils'
|
10
|
+
require 'pathname'
|
11
|
+
|
12
|
+
class SmartMessageDemoRunner
|
13
|
+
DEMO_PROGRAMS = [
|
14
|
+
{
|
15
|
+
file: "01_message_deduplication_demo.rb",
|
16
|
+
title: "Message Deduplication with DDQ",
|
17
|
+
description: "Demonstrates message deduplication patterns and duplicate message prevention",
|
18
|
+
duration: "~10 seconds"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
file: "02_dead_letter_queue_demo.rb",
|
22
|
+
title: "Dead Letter Queue & Error Handling",
|
23
|
+
description: "Shows DLQ pattern implementation with circuit breakers and error recovery",
|
24
|
+
duration: "~15 seconds"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
file: "03_point_to_point_orders.rb",
|
28
|
+
title: "Point-to-Point Order Processing",
|
29
|
+
description: "Order processing system with 1:1 messaging between OrderService and PaymentService",
|
30
|
+
duration: "~8 seconds"
|
31
|
+
},
|
32
|
+
{
|
33
|
+
file: "04_publish_subscribe_events.rb",
|
34
|
+
title: "Publish-Subscribe Event Broadcasting",
|
35
|
+
description: "Event-driven architecture with multiple subscribers (Email, SMS, Audit)",
|
36
|
+
duration: "~10 seconds"
|
37
|
+
},
|
38
|
+
{
|
39
|
+
file: "05_many_to_many_chat.rb",
|
40
|
+
title: "Many-to-Many Chat System",
|
41
|
+
description: "Interactive chat system with rooms, bots, and human agents",
|
42
|
+
duration: "~12 seconds"
|
43
|
+
},
|
44
|
+
{
|
45
|
+
file: "06_stdout_publish_only.rb",
|
46
|
+
title: "STDOUT Transport (Publish-Only)",
|
47
|
+
description: "Demonstrates STDOUT transport for logging and external tool integration",
|
48
|
+
duration: "~5 seconds"
|
49
|
+
},
|
50
|
+
{
|
51
|
+
file: "07_proc_handlers_demo.rb",
|
52
|
+
title: "Proc-Based Message Handlers",
|
53
|
+
description: "Flexible message handlers using blocks, procs, lambdas, and methods",
|
54
|
+
duration: "~8 seconds"
|
55
|
+
},
|
56
|
+
{
|
57
|
+
file: "08_custom_logger_demo.rb",
|
58
|
+
title: "Custom Logging Implementations",
|
59
|
+
description: "Advanced logging with multiple loggers and custom formatting",
|
60
|
+
duration: "~12 seconds"
|
61
|
+
},
|
62
|
+
{
|
63
|
+
file: "09_error_handling_demo.rb",
|
64
|
+
title: "Comprehensive Error Handling",
|
65
|
+
description: "Error handling strategies, validation failures, and graceful degradation",
|
66
|
+
duration: "~10 seconds"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
file: "10_entity_addressing_basic.rb",
|
70
|
+
title: "Entity Addressing Basics",
|
71
|
+
description: "Message routing by entity addresses with FROM/TO/REPLY_TO patterns",
|
72
|
+
duration: "~8 seconds"
|
73
|
+
},
|
74
|
+
{
|
75
|
+
file: "11_entity_addressing_with_filtering.rb",
|
76
|
+
title: "Advanced Entity Addressing & Filtering",
|
77
|
+
description: "Complex filtering patterns with regex-based address matching",
|
78
|
+
duration: "~10 seconds"
|
79
|
+
},
|
80
|
+
{
|
81
|
+
file: "12_regex_filtering_microservices.rb",
|
82
|
+
title: "Microservices with Regex Filtering",
|
83
|
+
description: "Service-to-service communication with environment-based filtering",
|
84
|
+
duration: "~8 seconds"
|
85
|
+
},
|
86
|
+
{
|
87
|
+
file: "13_header_block_configuration.rb",
|
88
|
+
title: "Header Block Configuration",
|
89
|
+
description: "Dynamic header configuration with block-based modification",
|
90
|
+
duration: "~6 seconds"
|
91
|
+
},
|
92
|
+
{
|
93
|
+
file: "14_global_configuration_demo.rb",
|
94
|
+
title: "Global Configuration Management",
|
95
|
+
description: "Global transport settings and configuration inheritance",
|
96
|
+
duration: "~8 seconds"
|
97
|
+
},
|
98
|
+
{
|
99
|
+
file: "15_logger_demo.rb",
|
100
|
+
title: "Advanced Logger Configuration",
|
101
|
+
description: "Logger configuration, log levels, and SmartMessage lifecycle integration",
|
102
|
+
duration: "~10 seconds"
|
103
|
+
},
|
104
|
+
{
|
105
|
+
file: "16_pretty_print_demo.rb",
|
106
|
+
title: "Message Pretty-Printing",
|
107
|
+
description: "Message inspection and debugging with pretty-print formatting",
|
108
|
+
duration: "~5 seconds"
|
109
|
+
}
|
110
|
+
].freeze
|
111
|
+
|
112
|
+
def initialize
|
113
|
+
@base_dir = File.dirname(__FILE__)
|
114
|
+
@total_demos = DEMO_PROGRAMS.length
|
115
|
+
@start_time = Time.now
|
116
|
+
end
|
117
|
+
|
118
|
+
def run_all
|
119
|
+
print_main_banner
|
120
|
+
print_overview
|
121
|
+
|
122
|
+
DEMO_PROGRAMS.each_with_index do |demo, index|
|
123
|
+
run_demo(demo, index + 1)
|
124
|
+
end
|
125
|
+
|
126
|
+
print_completion_summary
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# Helper method to calculate visual width of string accounting for emoji
|
132
|
+
def visual_width(str)
|
133
|
+
# Remove ANSI escape sequences if any
|
134
|
+
clean_str = str.gsub(/\e\[[0-9;]*m/, '')
|
135
|
+
|
136
|
+
# Count emoji and other wide characters
|
137
|
+
emoji_count = clean_str.scan(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/).length
|
138
|
+
|
139
|
+
# Each emoji takes up 2 visual columns but counts as 1 character
|
140
|
+
# So we add the emoji_count to get the actual visual width
|
141
|
+
clean_str.length + emoji_count
|
142
|
+
end
|
143
|
+
|
144
|
+
# Helper method to pad string to exact visual width
|
145
|
+
def pad_to_width(str, target_width)
|
146
|
+
current_width = visual_width(str)
|
147
|
+
if current_width <= target_width
|
148
|
+
str + (" " * (target_width - current_width))
|
149
|
+
else
|
150
|
+
# Truncate if too long, being careful about emoji
|
151
|
+
str[0...(target_width - current_width)]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def print_main_banner
|
156
|
+
puts "\n"
|
157
|
+
puts "█" * 100
|
158
|
+
puts "█" + " " * 98 + "█"
|
159
|
+
puts "█" + pad_to_width(" 🚀 SMARTMESSAGE COMPREHENSIVE DEMO SUITE 🚀 ", 98) + "█"
|
160
|
+
puts "█" + " " * 98 + "█"
|
161
|
+
puts "█" + pad_to_width(" Running all #{@total_demos} demo programs to showcase SmartMessage capabilities ", 98) + "█"
|
162
|
+
puts "█" + " " * 98 + "█"
|
163
|
+
puts "█" * 100
|
164
|
+
puts "\n"
|
165
|
+
end
|
166
|
+
|
167
|
+
def print_overview
|
168
|
+
puts "📋 DEMO OVERVIEW:"
|
169
|
+
puts "=" * 80
|
170
|
+
|
171
|
+
DEMO_PROGRAMS.each_with_index do |demo, index|
|
172
|
+
printf " %2d. %-35s %s\n",
|
173
|
+
index + 1,
|
174
|
+
demo[:title],
|
175
|
+
"(#{demo[:duration]})"
|
176
|
+
end
|
177
|
+
|
178
|
+
total_time = DEMO_PROGRAMS.sum { |demo|
|
179
|
+
demo[:duration].scan(/\d+/).first.to_i
|
180
|
+
}
|
181
|
+
|
182
|
+
puts "=" * 80
|
183
|
+
puts "📊 Total estimated time: ~#{total_time} seconds (~#{(total_time/60.0).round(1)} minutes)"
|
184
|
+
puts "🎯 Each demo runs independently with clear separation"
|
185
|
+
puts "⏸️ Press Ctrl+C at any time to stop the demo suite"
|
186
|
+
puts "\n"
|
187
|
+
end
|
188
|
+
|
189
|
+
def run_demo(demo, demo_number)
|
190
|
+
file_path = File.join(@base_dir, demo[:file])
|
191
|
+
|
192
|
+
unless File.exist?(file_path)
|
193
|
+
print_error_banner(demo_number, demo[:title], "File not found: #{demo[:file]}")
|
194
|
+
return
|
195
|
+
end
|
196
|
+
|
197
|
+
print_demo_banner(demo_number, demo)
|
198
|
+
|
199
|
+
start_time = Time.now
|
200
|
+
begin
|
201
|
+
# Execute the demo program
|
202
|
+
success = system("cd #{@base_dir} && ruby #{demo[:file]}")
|
203
|
+
end_time = Time.now
|
204
|
+
|
205
|
+
if success
|
206
|
+
print_demo_completion(demo_number, demo[:title], end_time - start_time)
|
207
|
+
else
|
208
|
+
print_demo_error(demo_number, demo[:title], "Demo exited with error code")
|
209
|
+
end
|
210
|
+
|
211
|
+
rescue Interrupt
|
212
|
+
puts "\n"
|
213
|
+
puts "🛑 DEMO SUITE INTERRUPTED BY USER"
|
214
|
+
puts " Completed #{demo_number - 1} of #{@total_demos} demos"
|
215
|
+
exit(0)
|
216
|
+
rescue => e
|
217
|
+
print_demo_error(demo_number, demo[:title], e.message)
|
218
|
+
end
|
219
|
+
|
220
|
+
print_demo_separator
|
221
|
+
end
|
222
|
+
|
223
|
+
def print_demo_banner(demo_number, demo)
|
224
|
+
puts "┌" + "─" * 98 + "┐"
|
225
|
+
puts "│" + " " * 98 + "│"
|
226
|
+
puts "│" + pad_to_width("🔥 DEMO #{demo_number.to_s.rjust(2, '0')}/#{@total_demos.to_s.rjust(2, '0')}: #{demo[:title]}", 98) + "│"
|
227
|
+
puts "│" + " " * 98 + "│"
|
228
|
+
puts "│" + pad_to_width("📝 #{demo[:description]}", 98) + "│"
|
229
|
+
puts "│" + pad_to_width("⏱️ Expected duration: #{demo[:duration]}", 98) + "│"
|
230
|
+
puts "│" + pad_to_width("📁 File: #{demo[:file]}", 98) + "│"
|
231
|
+
puts "│" + " " * 98 + "│"
|
232
|
+
puts "└" + "─" * 98 + "┘"
|
233
|
+
puts "\n"
|
234
|
+
end
|
235
|
+
|
236
|
+
def print_demo_completion(demo_number, title, actual_time)
|
237
|
+
puts "\n"
|
238
|
+
puts "✅ DEMO #{demo_number.to_s.rjust(2, '0')} COMPLETED: #{title}"
|
239
|
+
puts " ⏱️ Actual execution time: #{actual_time.round(2)} seconds"
|
240
|
+
puts "\n"
|
241
|
+
end
|
242
|
+
|
243
|
+
def print_demo_error(demo_number, title, error_message)
|
244
|
+
puts "\n"
|
245
|
+
puts "❌ DEMO #{demo_number.to_s.rjust(2, '0')} FAILED: #{title}"
|
246
|
+
puts " 🚨 Error: #{error_message}"
|
247
|
+
puts " ⏭️ Continuing with next demo..."
|
248
|
+
puts "\n"
|
249
|
+
end
|
250
|
+
|
251
|
+
def print_error_banner(demo_number, title, error_message)
|
252
|
+
puts "┌" + "─" * 98 + "┐"
|
253
|
+
puts "│" + pad_to_width("❌ DEMO #{demo_number.to_s.rjust(2, '0')}/#{@total_demos.to_s.rjust(2, '0')} ERROR: #{title}", 98) + "│"
|
254
|
+
puts "│" + " " * 98 + "│"
|
255
|
+
puts "│" + pad_to_width("🚨 #{error_message}", 98) + "│"
|
256
|
+
puts "│" + " " * 98 + "│"
|
257
|
+
puts "└" + "─" * 98 + "┘"
|
258
|
+
puts "\n"
|
259
|
+
end
|
260
|
+
|
261
|
+
def print_demo_separator
|
262
|
+
puts "═" * 100
|
263
|
+
puts "\n"
|
264
|
+
sleep(1) # Brief pause between demos for readability
|
265
|
+
end
|
266
|
+
|
267
|
+
def print_completion_summary
|
268
|
+
total_time = Time.now - @start_time
|
269
|
+
|
270
|
+
puts "\n"
|
271
|
+
puts "🏁" * 50
|
272
|
+
puts "🏁" + " " * 96 + "🏁"
|
273
|
+
puts "🏁" + pad_to_width(" 🎉 ALL DEMOS COMPLETED SUCCESSFULLY! 🎉 ", 96) + "🏁"
|
274
|
+
puts "🏁" + " " * 96 + "🏁"
|
275
|
+
puts "🏁" + pad_to_width(" Total execution time: #{total_time.round(2)} seconds (#{(total_time/60.0).round(2)} minutes) ", 96) + "🏁"
|
276
|
+
puts "🏁" + pad_to_width(" Demos completed: #{@total_demos} ", 96) + "🏁"
|
277
|
+
puts "🏁" + " " * 96 + "🏁"
|
278
|
+
puts "🏁" * 50
|
279
|
+
puts "\n"
|
280
|
+
|
281
|
+
puts "📋 WHAT YOU'VE SEEN:"
|
282
|
+
puts "=" * 80
|
283
|
+
puts "✅ Message deduplication and Dead Letter Queue patterns"
|
284
|
+
puts "✅ Point-to-point, publish-subscribe, and many-to-many messaging"
|
285
|
+
puts "✅ STDOUT transport for debugging and external integration"
|
286
|
+
puts "✅ Advanced message handlers (procs, blocks, lambdas)"
|
287
|
+
puts "✅ Comprehensive logging and error handling strategies"
|
288
|
+
puts "✅ Entity addressing and advanced message filtering"
|
289
|
+
puts "✅ Microservices communication patterns"
|
290
|
+
puts "✅ Configuration management and message inspection"
|
291
|
+
puts "\n"
|
292
|
+
|
293
|
+
puts "🚀 NEXT STEPS:"
|
294
|
+
puts "=" * 80
|
295
|
+
puts "• Explore individual demos: ruby examples/memory/<demo_file>"
|
296
|
+
puts "• Check out Redis Queue examples: examples/redis_queue/"
|
297
|
+
puts "• View comprehensive documentation: docs/"
|
298
|
+
puts "• Start building with SmartMessage in your projects!"
|
299
|
+
puts "\n"
|
300
|
+
|
301
|
+
puts "💡 For more information:"
|
302
|
+
puts " 📖 README.md - Getting started guide"
|
303
|
+
puts " 🔧 examples/memory/README.md - Detailed example descriptions"
|
304
|
+
puts " 📚 https://github.com/MadBomber/smart_message - Full documentation"
|
305
|
+
puts "\n"
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# Allow running directly or requiring as a library
|
310
|
+
if __FILE__ == $0
|
311
|
+
puts "Starting SmartMessage Demo Suite..."
|
312
|
+
puts "Press Ctrl+C to interrupt at any time."
|
313
|
+
puts "\n"
|
314
|
+
|
315
|
+
runner = SmartMessageDemoRunner.new
|
316
|
+
runner.run_all
|
317
|
+
end
|
@@ -64,11 +64,9 @@ def demonstrate_deduplication
|
|
64
64
|
transport = SmartMessage::Transport::MemoryTransport.new
|
65
65
|
|
66
66
|
OrderMessage.transport(transport)
|
67
|
-
OrderMessage.serializer(SmartMessage::Serializer::Json.new)
|
68
67
|
OrderMessage.subscribe('OrderMessage.process')
|
69
68
|
|
70
69
|
NotificationMessage.transport(transport)
|
71
|
-
NotificationMessage.serializer(SmartMessage::Serializer::Json.new)
|
72
70
|
NotificationMessage.subscribe('NotificationMessage.process')
|
73
71
|
|
74
72
|
# Clear any previous state
|
@@ -91,21 +89,13 @@ def demonstrate_deduplication
|
|
91
89
|
# Test 1: OrderMessage with deduplication
|
92
90
|
puts "--- Test 1: OrderMessage (with deduplication) ---"
|
93
91
|
|
94
|
-
#
|
95
|
-
header = SmartMessage::Header.new(
|
96
|
-
uuid: uuid,
|
97
|
-
message_class: "OrderMessage",
|
98
|
-
published_at: Time.now,
|
99
|
-
publisher_pid: Process.pid,
|
100
|
-
version: 1,
|
101
|
-
from: "order-service"
|
102
|
-
)
|
103
|
-
|
104
|
-
# First message
|
92
|
+
# First message (create normally, then set UUID for testing)
|
105
93
|
order1 = OrderMessage.new(
|
106
|
-
|
107
|
-
|
94
|
+
order_id: "ORD-001",
|
95
|
+
amount: 99.99
|
108
96
|
)
|
97
|
+
# Override UUID for deduplication testing
|
98
|
+
order1._sm_header.uuid = uuid
|
109
99
|
|
110
100
|
puts "Publishing first order message..."
|
111
101
|
order1.publish
|
@@ -113,9 +103,11 @@ def demonstrate_deduplication
|
|
113
103
|
|
114
104
|
# Second message with SAME UUID (should be deduplicated)
|
115
105
|
order2 = OrderMessage.new(
|
116
|
-
|
117
|
-
|
106
|
+
order_id: "ORD-002",
|
107
|
+
amount: 149.99
|
118
108
|
)
|
109
|
+
# Use same UUID to test deduplication
|
110
|
+
order2._sm_header.uuid = uuid
|
119
111
|
|
120
112
|
puts "Publishing duplicate order message (same UUID)..."
|
121
113
|
order2.publish
|
@@ -129,21 +121,13 @@ def demonstrate_deduplication
|
|
129
121
|
# Test 2: NotificationMessage without deduplication
|
130
122
|
puts "--- Test 2: NotificationMessage (no deduplication) ---"
|
131
123
|
|
132
|
-
#
|
133
|
-
notification_header = SmartMessage::Header.new(
|
134
|
-
uuid: uuid, # Same UUID as orders!
|
135
|
-
message_class: "NotificationMessage",
|
136
|
-
published_at: Time.now,
|
137
|
-
publisher_pid: Process.pid,
|
138
|
-
version: 1,
|
139
|
-
from: "notification-service"
|
140
|
-
)
|
141
|
-
|
142
|
-
# First notification
|
124
|
+
# First notification (create normally, then set UUID)
|
143
125
|
notif1 = NotificationMessage.new(
|
144
|
-
|
145
|
-
|
126
|
+
message: "Order confirmed",
|
127
|
+
recipient: "customer@example.com"
|
146
128
|
)
|
129
|
+
# Use same UUID as orders to show deduplication is per-message-class
|
130
|
+
notif1._sm_header.uuid = uuid
|
147
131
|
|
148
132
|
puts "Publishing first notification..."
|
149
133
|
notif1.publish
|
@@ -151,9 +135,11 @@ def demonstrate_deduplication
|
|
151
135
|
|
152
136
|
# Second notification with same UUID (should NOT be deduplicated)
|
153
137
|
notif2 = NotificationMessage.new(
|
154
|
-
|
155
|
-
|
138
|
+
message: "Order shipped",
|
139
|
+
recipient: "customer@example.com"
|
156
140
|
)
|
141
|
+
# Use same UUID - NotificationMessage doesn't have deduplication enabled
|
142
|
+
notif2._sm_header.uuid = uuid
|
157
143
|
|
158
144
|
puts "Publishing duplicate notification (same UUID)..."
|
159
145
|
notif2.publish
|
@@ -45,12 +45,11 @@ class PaymentMessage < SmartMessage::Base
|
|
45
45
|
|
46
46
|
config do
|
47
47
|
transport SmartMessage::Transport.create(:memory)
|
48
|
-
serializer SmartMessage::Serializer::Json.new
|
49
48
|
end
|
50
49
|
|
51
|
-
def
|
52
|
-
header =
|
53
|
-
payload =
|
50
|
+
def process(message)
|
51
|
+
header = message._sm_header
|
52
|
+
payload = message
|
54
53
|
data = JSON.parse(payload, symbolize_names: true)
|
55
54
|
puts " 💳 Processing payment #{data[:payment_id]} for $#{data[:amount]}"
|
56
55
|
end
|
@@ -68,12 +67,11 @@ class OrderMessage < SmartMessage::Base
|
|
68
67
|
|
69
68
|
config do
|
70
69
|
transport SmartMessage::Transport.create(:memory)
|
71
|
-
serializer SmartMessage::Serializer::Json.new
|
72
70
|
end
|
73
71
|
|
74
|
-
def
|
75
|
-
header =
|
76
|
-
payload =
|
72
|
+
def process(message)
|
73
|
+
header = message._sm_header
|
74
|
+
payload = message
|
77
75
|
data = JSON.parse(payload, symbolize_names: true)
|
78
76
|
puts " 📦 Processing order #{data[:order_id]} with #{data[:items].size} items"
|
79
77
|
end
|
@@ -90,12 +88,11 @@ class NotificationMessage < SmartMessage::Base
|
|
90
88
|
|
91
89
|
config do
|
92
90
|
transport SmartMessage::Transport.create(:memory)
|
93
|
-
serializer SmartMessage::Serializer::Json.new
|
94
91
|
end
|
95
92
|
|
96
|
-
def
|
97
|
-
header =
|
98
|
-
payload =
|
93
|
+
def process(message)
|
94
|
+
header = message._sm_header
|
95
|
+
payload = message
|
99
96
|
data = JSON.parse(payload, symbolize_names: true)
|
100
97
|
puts " 📧 Sending #{data[:channel]} to user #{data[:user_id]}: #{data[:message]}"
|
101
98
|
end
|
@@ -35,8 +35,7 @@ class OrderMessage < SmartMessage::Base
|
|
35
35
|
|
36
36
|
# Configure to use memory transport for this example
|
37
37
|
config do
|
38
|
-
transport SmartMessage::Transport::
|
39
|
-
serializer SmartMessage::Serializer::Json.new
|
38
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
40
39
|
end
|
41
40
|
|
42
41
|
# Default processing - just logs the order
|
@@ -61,8 +60,7 @@ class PaymentResponseMessage < SmartMessage::Base
|
|
61
60
|
description: "ISO8601 timestamp when the payment was processed"
|
62
61
|
|
63
62
|
config do
|
64
|
-
transport SmartMessage::Transport::
|
65
|
-
serializer SmartMessage::Serializer::Json.new
|
63
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
66
64
|
end
|
67
65
|
|
68
66
|
def self.process(message)
|
@@ -208,7 +206,7 @@ class OrderProcessingDemo
|
|
208
206
|
puts "• Point-to-point messaging between OrderService and PaymentService"
|
209
207
|
puts "• Bidirectional communication with request/response pattern"
|
210
208
|
puts "• JSON serialization of complex message data"
|
211
|
-
puts "•
|
209
|
+
puts "• Memory transport for local demonstration"
|
212
210
|
end
|
213
211
|
end
|
214
212
|
|
@@ -31,13 +31,12 @@ class UserEventMessage < SmartMessage::Base
|
|
31
31
|
description: "Additional event-specific data (source, location, IP, etc.)"
|
32
32
|
|
33
33
|
config do
|
34
|
-
transport SmartMessage::Transport::
|
35
|
-
serializer SmartMessage::Serializer::Json.new
|
34
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
36
35
|
end
|
37
36
|
|
38
37
|
# Default processor - just logs the event
|
39
|
-
def
|
40
|
-
message_header, message_payload =
|
38
|
+
def process(message)
|
39
|
+
message_header, message_payload = message
|
41
40
|
event_data = JSON.parse(message_payload)
|
42
41
|
puts "📡 Event broadcasted: #{event_data['event_type']} for user #{event_data['user_id']}"
|
43
42
|
end
|
@@ -51,13 +50,13 @@ class EmailService
|
|
51
50
|
UserEventMessage.subscribe('EmailService.handle_user_event')
|
52
51
|
end
|
53
52
|
|
54
|
-
def
|
53
|
+
def handle_event(message)
|
55
54
|
service = new
|
56
|
-
service.process_event(
|
55
|
+
service.process_event(message)
|
57
56
|
end
|
58
57
|
|
59
|
-
def process_event(
|
60
|
-
message_header, message_payload =
|
58
|
+
def process_event(message)
|
59
|
+
message_header, message_payload = message
|
61
60
|
event_data = JSON.parse(message_payload)
|
62
61
|
|
63
62
|
case event_data['event_type']
|
@@ -107,13 +106,13 @@ class SMSService
|
|
107
106
|
UserEventMessage.subscribe('SMSService.handle_user_event')
|
108
107
|
end
|
109
108
|
|
110
|
-
def
|
109
|
+
def handle_event(message)
|
111
110
|
service = new
|
112
|
-
service.process_event(
|
111
|
+
service.process_event(message)
|
113
112
|
end
|
114
113
|
|
115
|
-
def process_event(
|
116
|
-
message_header, message_payload =
|
114
|
+
def process_event(message)
|
115
|
+
message_header, message_payload = message
|
117
116
|
event_data = JSON.parse(message_payload)
|
118
117
|
|
119
118
|
case event_data['event_type']
|
@@ -173,18 +172,18 @@ class AuditService
|
|
173
172
|
UserEventMessage.subscribe('AuditService.handle_user_event')
|
174
173
|
end
|
175
174
|
|
176
|
-
def
|
175
|
+
def handle_event(message)
|
177
176
|
# Use a singleton pattern for persistent audit log
|
178
177
|
@@instance ||= new
|
179
|
-
@@instance.process_event(
|
178
|
+
@@instance.process_event(message)
|
180
179
|
end
|
181
180
|
|
182
181
|
def self.get_summary
|
183
182
|
@@instance&.get_audit_summary || {}
|
184
183
|
end
|
185
184
|
|
186
|
-
def process_event(
|
187
|
-
message_header, message_payload =
|
185
|
+
def process_event(message)
|
186
|
+
message_header, message_payload = message
|
188
187
|
event_data = JSON.parse(message_payload)
|
189
188
|
|
190
189
|
audit_entry = {
|
@@ -36,12 +36,11 @@ class ChatMessage < SmartMessage::Base
|
|
36
36
|
description: "Additional message data (reactions, edit history, etc.)"
|
37
37
|
|
38
38
|
config do
|
39
|
-
transport SmartMessage::Transport::
|
40
|
-
serializer SmartMessage::Serializer::Json.new
|
39
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
41
40
|
end
|
42
41
|
|
43
|
-
def
|
44
|
-
message_header, message_payload =
|
42
|
+
def process(message)
|
43
|
+
message_header, message_payload = message
|
45
44
|
chat_data = JSON.parse(message_payload)
|
46
45
|
puts "💬 Chat message in #{chat_data['room_id']}: #{chat_data['content']}"
|
47
46
|
end
|
@@ -65,12 +64,11 @@ class BotCommandMessage < SmartMessage::Base
|
|
65
64
|
description: "ISO8601 timestamp when command was issued"
|
66
65
|
|
67
66
|
config do
|
68
|
-
transport SmartMessage::Transport::
|
69
|
-
serializer SmartMessage::Serializer::Json.new
|
67
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
70
68
|
end
|
71
69
|
|
72
|
-
def
|
73
|
-
message_header, message_payload =
|
70
|
+
def process(message)
|
71
|
+
message_header, message_payload = message
|
74
72
|
command_data = JSON.parse(message_payload)
|
75
73
|
puts "🤖 Bot command: #{command_data['command']} in #{command_data['room_id']}"
|
76
74
|
end
|
@@ -94,12 +92,11 @@ class SystemNotificationMessage < SmartMessage::Base
|
|
94
92
|
description: "Additional system event data and context"
|
95
93
|
|
96
94
|
config do
|
97
|
-
transport SmartMessage::Transport::
|
98
|
-
serializer SmartMessage::Serializer::Json.new
|
95
|
+
transport SmartMessage::Transport::MemoryTransport.new
|
99
96
|
end
|
100
97
|
|
101
|
-
def
|
102
|
-
message_header, message_payload =
|
98
|
+
def process(message)
|
99
|
+
message_header, message_payload = message
|
103
100
|
notif_data = JSON.parse(message_payload)
|
104
101
|
puts "🔔 System: #{notif_data['content']} in #{notif_data['room_id']}"
|
105
102
|
end
|
@@ -195,8 +192,8 @@ class HumanChatAgent
|
|
195
192
|
@@agents[agent.user_id] = agent
|
196
193
|
end
|
197
194
|
|
198
|
-
def
|
199
|
-
message_header, message_payload =
|
195
|
+
def handle_message(message)
|
196
|
+
message_header, message_payload = message
|
200
197
|
chat_data = JSON.parse(message_payload)
|
201
198
|
|
202
199
|
# Only process messages from rooms we're in and not our own messages
|
@@ -211,8 +208,8 @@ class HumanChatAgent
|
|
211
208
|
end
|
212
209
|
end
|
213
210
|
|
214
|
-
def handle_system_notification(
|
215
|
-
message_header, message_payload =
|
211
|
+
def handle_system_notification(message)
|
212
|
+
message_header, message_payload = message
|
216
213
|
notif_data = JSON.parse(message_payload)
|
217
214
|
|
218
215
|
# Only process notifications from rooms we're in
|
@@ -307,8 +304,8 @@ class BotAgent
|
|
307
304
|
)
|
308
305
|
end
|
309
306
|
|
310
|
-
def
|
311
|
-
message_header, message_payload =
|
307
|
+
def handle_command(message)
|
308
|
+
message_header, message_payload = message
|
312
309
|
command_data = JSON.parse(message_payload)
|
313
310
|
@@bots ||= []
|
314
311
|
|
@@ -321,8 +318,8 @@ class BotAgent
|
|
321
318
|
capable_bot&.process_command(command_data)
|
322
319
|
end
|
323
320
|
|
324
|
-
def
|
325
|
-
message_header, message_payload =
|
321
|
+
def handle_message(message)
|
322
|
+
message_header, message_payload = message
|
326
323
|
chat_data = JSON.parse(message_payload)
|
327
324
|
@@bots ||= []
|
328
325
|
|
@@ -498,8 +495,8 @@ class RoomManager
|
|
498
495
|
notification.publish
|
499
496
|
end
|
500
497
|
|
501
|
-
def
|
502
|
-
message_header, message_payload =
|
498
|
+
def handle_system_notification(message)
|
499
|
+
message_header, message_payload = message
|
503
500
|
@@instance ||= new
|
504
501
|
@@instance.process_system_notification(message_header, message_payload)
|
505
502
|
end
|