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,270 @@
1
+ #!/usr/bin/env ruby
2
+ # examples/multi_program_demo/emergency_dispatch_center.rb
3
+
4
+ require_relative '../../lib/smart_message'
5
+ require_relative 'messages/emergency_911_message'
6
+ require_relative 'messages/fire_emergency_message'
7
+ require_relative 'messages/silent_alarm_message'
8
+
9
+ require_relative 'common/health_monitor'
10
+ require_relative 'common/logger'
11
+
12
+ class EmergencyDispatchCenter
13
+ include Common::HealthMonitor
14
+ include Common::Logger
15
+
16
+ def initialize
17
+ @service_name = 'emergency-dispatch-center'
18
+
19
+ @status = 'healthy'
20
+ @start_time = Time.now
21
+ @call_counter = 0
22
+ @active_calls = {}
23
+ @dispatch_stats = Hash.new(0)
24
+
25
+ setup_messaging
26
+ setup_signal_handlers
27
+ setup_health_monitor
28
+ end
29
+
30
+
31
+ def setup_messaging
32
+ Messages::Emergency911Message.from(@service_name)
33
+ Messages::FireEmergencyMessage.from(@service_name)
34
+ Messages::SilentAlarmMessage.from(@service_name)
35
+
36
+ # Subscribe to 911 emergency calls
37
+ Messages::Emergency911Message.subscribe(to: '911') do |message|
38
+ handle_emergency_call(message)
39
+ end
40
+
41
+ puts '📞 Emergency Dispatch Center (911) operational'
42
+ puts ' Routing emergency calls to appropriate departments'
43
+ puts ' Monitoring: Fire, Police, Medical, Accidents, Hazmat'
44
+ puts ' Logging to: emergency_dispatch_center.log'
45
+ puts " Press Ctrl+C to stop\n\n"
46
+ logger.info('Emergency Dispatch Center ready for 911 calls')
47
+ end
48
+
49
+
50
+ def get_status_details
51
+ [@status, @details]
52
+ end
53
+
54
+ def setup_signal_handlers
55
+ %w[INT TERM].each do |signal|
56
+ Signal.trap(signal) do
57
+ puts "\n📞 Emergency Dispatch Center going offline..."
58
+ show_statistics
59
+ logger.info('Emergency Dispatch Center shutting down')
60
+ exit(0)
61
+ end
62
+ end
63
+ end
64
+
65
+
66
+ def run
67
+ puts '📞 Emergency Dispatch Center listening for 911 calls...'
68
+ loop do
69
+ sleep 1
70
+ @status = 'healthy'
71
+ end
72
+ rescue StandardError => e
73
+ puts "📞 Error in dispatch center: #{e.message}"
74
+ logger.error({alert:"Error in dispatch center", message: e.message, traceback: e.backtrace})
75
+ logger.error(e.backtrace.join("\n"))
76
+ end
77
+
78
+ private
79
+
80
+ def handle_emergency_call(call)
81
+ @call_counter += 1
82
+ call_id = "911-#{Time.now.strftime('%Y%m%d-%H%M%S')}-#{@call_counter.to_s.rjust(4, '0')}"
83
+
84
+ # Color code based on severity
85
+ severity_color = case call.severity
86
+ when 'critical' then "\e[91m" # Bright red
87
+ when 'high' then "\e[31m" # Red
88
+ when 'medium' then "\e[33m" # Yellow
89
+ else "\e[32m" # Green
90
+ end
91
+
92
+ puts "\n#{severity_color}📞 911 CALL RECEIVED\e[0m ##{call_id}"
93
+ puts " 📍 Location: #{call.caller_location}"
94
+ puts " 🚨 Type: #{call.emergency_type.upcase}"
95
+ puts " 📝 Description: #{call.description}"
96
+ puts " ⚠️ Severity: #{call.severity&.upcase || 'UNKNOWN'}"
97
+ puts " 👤 Caller: #{call.caller_name || 'Anonymous'} (#{call.caller_phone || 'No phone'})"
98
+
99
+ logger.warn("911 CALL #{call_id}: #{call.emergency_type} at #{call.caller_location} - #{call.description}")
100
+
101
+ @active_calls[call_id] = {
102
+ call: call,
103
+ received_at: Time.now,
104
+ dispatched_to: []
105
+ }
106
+
107
+ # Determine which departments to dispatch to
108
+ departments_to_dispatch = determine_dispatch_departments(call)
109
+
110
+ puts " 🚨 Dispatching to: #{departments_to_dispatch.join(', ')}"
111
+
112
+ # Route to appropriate departments
113
+ departments_to_dispatch.each do |dept|
114
+ route_to_department(call, dept, call_id)
115
+ @dispatch_stats[dept] += 1
116
+ end
117
+
118
+ # After a delay, consider the call handled
119
+ Thread.new do
120
+ sleep(rand(60..180)) # Simulate response time
121
+ if @active_calls[call_id]
122
+ puts "📞 Call #{call_id} marked as handled"
123
+ logger.info("Call #{call_id} handled after #{(Time.now - @active_calls[call_id][:received_at]).round} seconds")
124
+ @active_calls.delete(call_id)
125
+ end
126
+ end
127
+ rescue StandardError => e
128
+ puts "📞 Error handling 911 call: #{e.message} #{e.backtrace.join("\n")}"
129
+ logger.error({alert:"Error handling 911 call", message: e.message, traceback: e.backtrace})
130
+ end
131
+
132
+
133
+ def determine_dispatch_departments(call)
134
+ departments = []
135
+
136
+ # Fire department dispatch rules
137
+ if call.fire_involved ||
138
+ call.emergency_type == 'fire' ||
139
+ call.emergency_type == 'rescue' ||
140
+ (call.emergency_type == 'accident' && call.vehicles_involved && call.vehicles_involved > 2) ||
141
+ call.hazardous_materials
142
+ departments << 'fire_department'
143
+ end
144
+
145
+ # Police department dispatch rules
146
+ if call.emergency_type == 'crime' ||
147
+ call.weapons_involved ||
148
+ call.suspects_on_scene ||
149
+ call.emergency_type == 'accident' ||
150
+ (call.emergency_type == 'other' && call.description =~ /theft|robbery|assault|break.?in|suspicious/i)
151
+ departments << 'police_department'
152
+ end
153
+
154
+ # Medical (would go to EMS, but we'll send to fire for this demo)
155
+ if (call.emergency_type == 'medical' ||
156
+ call.injuries_reported ||
157
+ (call.number_of_victims && call.number_of_victims > 0)) && !departments.include?('fire_department')
158
+ departments << 'fire_department'
159
+ end
160
+
161
+ # Default to police if no specific department determined
162
+ departments << 'police_department' if departments.empty?
163
+
164
+ departments
165
+ end
166
+
167
+
168
+ def route_to_department(call, department, call_id)
169
+ case department
170
+ when 'fire_department'
171
+ # Convert to FireEmergencyMessage for fire department
172
+ if call.fire_involved || call.emergency_type == 'fire'
173
+ fire_msg = Messages::FireEmergencyMessage.new(
174
+ house_address: call.caller_location,
175
+ fire_type: determine_fire_type(call),
176
+ severity: call.severity || 'medium',
177
+ occupants_status: build_occupants_status(call),
178
+ spread_risk: call.hazardous_materials ? 'high' : 'medium',
179
+ timestamp: call._sm_header.published_at,
180
+ emergency_id: call_id
181
+ )
182
+ fire_msg._sm_header.from = '911-dispatch'
183
+ fire_msg._sm_header.to = 'fire_department'
184
+ fire_msg.publish
185
+ logger.info("Routed call #{call_id} to Fire Department as fire emergency")
186
+ else
187
+ # For rescue/medical, forward the 911 call directly
188
+ forward_call = call.dup
189
+ forward_call.call_id = call_id
190
+ forward_call._sm_header.from = '911-dispatch'
191
+ forward_call._sm_header.to = 'fire_department'
192
+ forward_call.publish
193
+ logger.info("Forwarded call #{call_id} to Fire Department for rescue/medical")
194
+ end
195
+
196
+ when 'police_department'
197
+ # Forward all police calls directly as Emergency911Message
198
+ forward_call = Messages::Emergency911Message.new(**call.to_h.merge(
199
+ call_id: call_id,
200
+ from: '911-dispatch',
201
+ to: 'police_department'
202
+ ))
203
+ forward_call._sm_header.from = '911-dispatch'
204
+ forward_call._sm_header.to = 'police_department'
205
+ forward_call.publish
206
+
207
+ if call.emergency_type == 'crime' || call.weapons_involved || call.suspects_on_scene
208
+ logger.info("Routed call #{call_id} to Police Department as crime report")
209
+ else
210
+ logger.info("Forwarded call #{call_id} to Police Department")
211
+ end
212
+ end
213
+
214
+ @active_calls[call_id][:dispatched_to] << department if @active_calls[call_id]
215
+ rescue StandardError => e
216
+ logger.error({alert:"Error routing to #{department}", message: e.message, trace: e.backtrace})
217
+ raise
218
+ end
219
+
220
+
221
+ def determine_fire_type(call)
222
+ return 'chemical' if call.hazardous_materials
223
+ return 'vehicle' if call.vehicles_involved && call.vehicles_involved > 0
224
+
225
+ desc = call.description.downcase
226
+ return 'electrical' if desc.include?('electrical') || desc.include?('wire')
227
+ return 'grease' if desc.include?('kitchen') || desc.include?('grease')
228
+ return 'chemical' if desc.include?('chemical') || desc.include?('gas')
229
+
230
+ 'general'
231
+ end
232
+
233
+
234
+ def determine_alarm_type(call)
235
+ return 'armed_robbery' if call.weapons_involved
236
+ return 'break_in' if call.description =~ /break.?in/i
237
+ return 'assault' if call.description =~ /assault|attack/i
238
+ return 'robbery' if call.description =~ /robbery|theft/i
239
+
240
+ 'suspicious_activity'
241
+ end
242
+
243
+
244
+ def build_occupants_status(call)
245
+ if call.injuries_reported
246
+ "#{call.number_of_victims || 'Unknown number of'} injured"
247
+ elsif call.number_of_victims && call.number_of_victims > 0
248
+ "#{call.number_of_victims} people involved"
249
+ else
250
+ 'Unknown'
251
+ end
252
+ end
253
+
254
+
255
+ def show_statistics
256
+ puts "\n📊 Dispatch Statistics:"
257
+ puts " Total 911 calls handled: #{@call_counter}"
258
+ puts " Active calls: #{@active_calls.size}"
259
+ puts ' Dispatches by department:'
260
+ @dispatch_stats.each do |dept, count|
261
+ puts " #{dept}: #{count}"
262
+ end
263
+ end
264
+ end
265
+
266
+ # Run the dispatch center
267
+ if __FILE__ == $0
268
+ dispatch = EmergencyDispatchCenter.new
269
+ dispatch.run
270
+ end