smart_message 0.0.1

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +3 -0
  3. data/.gitignore +8 -0
  4. data/.travis.yml +7 -0
  5. data/CHANGELOG.md +100 -0
  6. data/COMMITS.md +196 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +71 -0
  9. data/README.md +303 -0
  10. data/Rakefile +10 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/docs/README.md +52 -0
  14. data/docs/architecture.md +370 -0
  15. data/docs/dispatcher.md +593 -0
  16. data/docs/examples.md +808 -0
  17. data/docs/getting-started.md +235 -0
  18. data/docs/ideas_to_think_about.md +329 -0
  19. data/docs/serializers.md +575 -0
  20. data/docs/transports.md +501 -0
  21. data/docs/troubleshooting.md +582 -0
  22. data/examples/01_point_to_point_orders.rb +200 -0
  23. data/examples/02_publish_subscribe_events.rb +364 -0
  24. data/examples/03_many_to_many_chat.rb +608 -0
  25. data/examples/README.md +335 -0
  26. data/examples/tmux_chat/README.md +283 -0
  27. data/examples/tmux_chat/bot_agent.rb +272 -0
  28. data/examples/tmux_chat/human_agent.rb +197 -0
  29. data/examples/tmux_chat/room_monitor.rb +158 -0
  30. data/examples/tmux_chat/shared_chat_system.rb +295 -0
  31. data/examples/tmux_chat/start_chat_demo.sh +190 -0
  32. data/examples/tmux_chat/stop_chat_demo.sh +22 -0
  33. data/lib/simple_stats.rb +57 -0
  34. data/lib/smart_message/base.rb +284 -0
  35. data/lib/smart_message/dispatcher/.keep +0 -0
  36. data/lib/smart_message/dispatcher.rb +146 -0
  37. data/lib/smart_message/errors.rb +29 -0
  38. data/lib/smart_message/header.rb +20 -0
  39. data/lib/smart_message/logger/base.rb +8 -0
  40. data/lib/smart_message/logger.rb +7 -0
  41. data/lib/smart_message/serializer/base.rb +23 -0
  42. data/lib/smart_message/serializer/json.rb +22 -0
  43. data/lib/smart_message/serializer.rb +10 -0
  44. data/lib/smart_message/transport/base.rb +85 -0
  45. data/lib/smart_message/transport/memory_transport.rb +69 -0
  46. data/lib/smart_message/transport/registry.rb +59 -0
  47. data/lib/smart_message/transport/stdout_transport.rb +62 -0
  48. data/lib/smart_message/transport.rb +41 -0
  49. data/lib/smart_message/version.rb +7 -0
  50. data/lib/smart_message/wrapper.rb +43 -0
  51. data/lib/smart_message.rb +54 -0
  52. data/smart_message.gemspec +53 -0
  53. metadata +252 -0
@@ -0,0 +1,582 @@
1
+ # Troubleshooting Guide
2
+
3
+ This guide helps you diagnose and solve common issues when working with SmartMessage.
4
+
5
+ ## Common Issues
6
+
7
+ ### 1. Messages Not Being Processed
8
+
9
+ **Symptoms:**
10
+ - Messages are published but process methods are never called
11
+ - No errors are thrown
12
+ - Statistics show messages published but not routed
13
+
14
+ **Possible Causes & Solutions:**
15
+
16
+ #### Missing Subscription
17
+ ```ruby
18
+ # Problem: Forgot to subscribe
19
+ class MyMessage < SmartMessage::Base
20
+ property :data
21
+
22
+ def self.process(header, payload)
23
+ puts "Processing message"
24
+ end
25
+ end
26
+
27
+ MyMessage.new(data: "test").publish # Nothing happens
28
+
29
+ # Solution: Add subscription
30
+ MyMessage.subscribe
31
+ MyMessage.new(data: "test").publish # Now it works
32
+ ```
33
+
34
+ #### Transport Not Configured for Loopback
35
+ ```ruby
36
+ # Problem: Using STDOUT without loopback
37
+ class MyMessage < SmartMessage::Base
38
+ property :data
39
+
40
+ config do
41
+ transport SmartMessage::Transport.create(:stdout) # No loopback
42
+ serializer SmartMessage::Serializer::JSON.new
43
+ end
44
+ end
45
+
46
+ # Solution: Enable loopback for local testing
47
+ class MyMessage < SmartMessage::Base
48
+ config do
49
+ transport SmartMessage::Transport.create(:stdout, loopback: true)
50
+ serializer SmartMessage::Serializer::JSON.new
51
+ end
52
+ end
53
+ ```
54
+
55
+ #### Auto-process Disabled
56
+ ```ruby
57
+ # Problem: Memory transport with auto_process disabled
58
+ class MyMessage < SmartMessage::Base
59
+ config do
60
+ transport SmartMessage::Transport.create(:memory, auto_process: false)
61
+ end
62
+ end
63
+
64
+ # Messages are stored but not processed
65
+ transport = MyMessage.transport
66
+ puts transport.message_count # Shows stored messages
67
+
68
+ # Solution: Enable auto_process or manually process
69
+ MyMessage.config do
70
+ transport SmartMessage::Transport.create(:memory, auto_process: true)
71
+ end
72
+
73
+ # Or manually trigger processing
74
+ transport.process_all
75
+ ```
76
+
77
+ ### 2. Serialization Errors
78
+
79
+ **Symptoms:**
80
+ - `SmartMessage::Errors::SerializerNotConfigured` exceptions
81
+ - Encoding/decoding failures
82
+ - Malformed message data
83
+
84
+ **Solutions:**
85
+
86
+ #### Missing Serializer Configuration
87
+ ```ruby
88
+ # Problem: No serializer configured
89
+ class MyMessage < SmartMessage::Base
90
+ property :data
91
+
92
+ config do
93
+ transport SmartMessage::Transport.create(:memory)
94
+ # Missing serializer!
95
+ end
96
+ end
97
+
98
+ # Throws: SmartMessage::Errors::SerializerNotConfigured
99
+ MyMessage.new(data: "test").publish
100
+
101
+ # Solution: Add serializer
102
+ class MyMessage < SmartMessage::Base
103
+ config do
104
+ transport SmartMessage::Transport.create(:memory)
105
+ serializer SmartMessage::Serializer::JSON.new
106
+ end
107
+ end
108
+ ```
109
+
110
+ #### JSON Encoding Issues
111
+ ```ruby
112
+ # Problem: Objects that can't be serialized to JSON
113
+ class ProblematicMessage < SmartMessage::Base
114
+ property :data
115
+
116
+ config do
117
+ serializer SmartMessage::Serializer::JSON.new
118
+ end
119
+ end
120
+
121
+ # This will fail
122
+ message = ProblematicMessage.new(data: Object.new)
123
+ message.publish # JSON::GeneratorError
124
+
125
+ # Solution: Ensure data is JSON-serializable
126
+ message = ProblematicMessage.new(data: { key: "value" })
127
+ message.publish # Works fine
128
+
129
+ # Or implement custom serialization
130
+ class SafeMessage < SmartMessage::Base
131
+ property :data
132
+
133
+ def to_h
134
+ hash = super
135
+ hash[:data] = hash[:data].to_s if hash[:data]
136
+ hash
137
+ end
138
+ end
139
+ ```
140
+
141
+ ### 3. Transport Configuration Issues
142
+
143
+ **Symptoms:**
144
+ - `SmartMessage::Errors::TransportNotConfigured` exceptions
145
+ - Connection failures
146
+ - Messages not being sent
147
+
148
+ **Solutions:**
149
+
150
+ #### Missing Transport Configuration
151
+ ```ruby
152
+ # Problem: No transport configured
153
+ class MyMessage < SmartMessage::Base
154
+ property :data
155
+
156
+ config do
157
+ serializer SmartMessage::Serializer::JSON.new
158
+ # Missing transport!
159
+ end
160
+ end
161
+
162
+ MyMessage.new(data: "test").publish # Throws TransportNotConfigured
163
+
164
+ # Solution: Add transport
165
+ class MyMessage < SmartMessage::Base
166
+ config do
167
+ transport SmartMessage::Transport.create(:memory)
168
+ serializer SmartMessage::Serializer::JSON.new
169
+ end
170
+ end
171
+ ```
172
+
173
+ #### Transport Connection Issues
174
+ ```ruby
175
+ # For custom transports that might fail to connect
176
+ class MyMessage < SmartMessage::Base
177
+ config do
178
+ transport CustomTransport.new(host: "unreachable-host")
179
+ end
180
+ end
181
+
182
+ # Check transport status
183
+ transport = MyMessage.transport
184
+ puts "Connected: #{transport.connected?}"
185
+
186
+ # Solution: Verify connection settings
187
+ class MyMessage < SmartMessage::Base
188
+ config do
189
+ transport CustomTransport.new(
190
+ host: "localhost",
191
+ port: 5672,
192
+ retry_attempts: 3
193
+ )
194
+ end
195
+ end
196
+ ```
197
+
198
+ ### 4. Thread Pool Issues
199
+
200
+ **Symptoms:**
201
+ - Messages processed very slowly
202
+ - Application hangs on exit
203
+ - High memory usage
204
+
205
+ **Debugging Thread Pool:**
206
+
207
+ ```ruby
208
+ dispatcher = SmartMessage::Dispatcher.new
209
+
210
+ # Check thread pool status
211
+ status = dispatcher.status
212
+ puts "Running: #{status[:running]}"
213
+ puts "Queue length: #{status[:queue_length]}"
214
+ puts "Scheduled tasks: #{status[:scheduled_task_count]}"
215
+ puts "Completed tasks: #{status[:completed_task_count]}"
216
+ puts "Pool size: #{status[:length]}"
217
+
218
+ # If queue is growing, messages are being created faster than processed
219
+ if status[:queue_length] > 100
220
+ puts "⚠️ Large queue detected - consider optimizing message processing"
221
+ end
222
+
223
+ # If pool is not running
224
+ unless status[:running]
225
+ puts "❌ Thread pool is not running - check for shutdown issues"
226
+ end
227
+ ```
228
+
229
+ **Solutions:**
230
+
231
+ #### Slow Message Processing
232
+ ```ruby
233
+ # Problem: Slow process method blocking thread pool
234
+ class SlowMessage < SmartMessage::Base
235
+ def self.process(header, payload)
236
+ sleep(10) # Very slow operation
237
+ # Processing logic
238
+ end
239
+ end
240
+
241
+ # Solution: Optimize or use background jobs
242
+ class OptimizedMessage < SmartMessage::Base
243
+ def self.process(header, payload)
244
+ # Quick validation
245
+ data = JSON.parse(payload)
246
+
247
+ # Delegate heavy work to background job
248
+ BackgroundJob.perform_async(data)
249
+ end
250
+ end
251
+ ```
252
+
253
+ #### Application Hanging on Exit
254
+ ```ruby
255
+ # Problem: Threads not shutting down gracefully
256
+ # The dispatcher handles this automatically, but if you create custom threads:
257
+
258
+ class CustomMessage < SmartMessage::Base
259
+ def self.process(header, payload)
260
+ # Problem: Creating non-daemon threads
261
+ Thread.new do
262
+ loop do
263
+ # Long-running work
264
+ sleep(1)
265
+ end
266
+ end
267
+ end
268
+ end
269
+
270
+ # Solution: Use daemon threads or proper cleanup
271
+ class BetterMessage < SmartMessage::Base
272
+ def self.process(header, payload)
273
+ thread = Thread.new do
274
+ loop do
275
+ break if Thread.current[:stop_requested]
276
+ # Work with interruption points
277
+ sleep(1)
278
+ end
279
+ end
280
+
281
+ # Register cleanup
282
+ at_exit do
283
+ thread[:stop_requested] = true
284
+ thread.join(5) # Wait up to 5 seconds
285
+ end
286
+ end
287
+ end
288
+ ```
289
+
290
+ ### 5. Memory Issues
291
+
292
+ **Symptoms:**
293
+ - Increasing memory usage over time
294
+ - Out of memory errors
295
+ - Slow performance
296
+
297
+ **Debugging Memory Usage:**
298
+
299
+ ```ruby
300
+ # Check message storage in memory transport
301
+ transport = SmartMessage::Transport.create(:memory)
302
+ puts "Stored messages: #{transport.message_count}"
303
+ puts "Max messages: #{transport.instance_variable_get(:@options)[:max_messages]}"
304
+
305
+ # Check statistics storage
306
+ puts "Statistics entries: #{SS.stat.keys.length}"
307
+
308
+ # Monitor object creation
309
+ class MemoryMonitorMessage < SmartMessage::Base
310
+ def self.process(header, payload)
311
+ puts "Objects before: #{ObjectSpace.count_objects[:TOTAL]}"
312
+
313
+ # Your processing logic
314
+ data = JSON.parse(payload)
315
+
316
+ puts "Objects after: #{ObjectSpace.count_objects[:TOTAL]}"
317
+ end
318
+ end
319
+ ```
320
+
321
+ **Solutions:**
322
+
323
+ #### Memory Transport Overflow
324
+ ```ruby
325
+ # Problem: Memory transport storing too many messages
326
+ transport = SmartMessage::Transport.create(:memory, max_messages: 10000)
327
+
328
+ # Monitor and clean up
329
+ def cleanup_memory_transport(transport)
330
+ if transport.message_count > 5000
331
+ puts "Cleaning up old messages..."
332
+ transport.clear_messages
333
+ end
334
+ end
335
+
336
+ # Or use smaller limits
337
+ transport = SmartMessage::Transport.create(:memory, max_messages: 100)
338
+ ```
339
+
340
+ #### Statistics Memory Growth
341
+ ```ruby
342
+ # Problem: Statistics growing without bounds
343
+ # Check current statistics size
344
+ puts "Statistics size: #{SS.stat.size}"
345
+
346
+ # Solution: Periodic cleanup
347
+ def cleanup_statistics
348
+ # Keep only recent statistics
349
+ current_stats = SS.stat
350
+ important_stats = current_stats.select do |key, value|
351
+ # Keep publish counts and recent routing stats
352
+ key.include?('publish') || value > 0
353
+ end
354
+
355
+ SS.reset
356
+ important_stats.each { |key, value| SS.add(*key.split('+'), how_many: value) }
357
+ end
358
+
359
+ # Run cleanup periodically
360
+ Thread.new do
361
+ loop do
362
+ sleep(3600) # Every hour
363
+ cleanup_statistics
364
+ end
365
+ end
366
+ ```
367
+
368
+ ### 6. Debugging Message Flow
369
+
370
+ **Enable Debug Logging:**
371
+
372
+ ```ruby
373
+ # Add debug output to your message classes
374
+ class DebugMessage < SmartMessage::Base
375
+ property :data
376
+
377
+ def publish
378
+ puts "🚀 Publishing #{self.class.name}: #{self.to_h}"
379
+ super
380
+ end
381
+
382
+ def self.process(header, payload)
383
+ puts "📥 Processing #{header.message_class}: #{payload}"
384
+
385
+ # Your processing logic
386
+ data = JSON.parse(payload)
387
+ message = new(data)
388
+
389
+ puts "✅ Processed #{header.message_class}: #{message.data}"
390
+ end
391
+ end
392
+ ```
393
+
394
+ **Trace Message Path:**
395
+
396
+ ```ruby
397
+ # Add correlation IDs for tracing
398
+ class TrackedMessage < SmartMessage::Base
399
+ property :data
400
+ property :correlation_id, default: -> { SecureRandom.uuid }
401
+
402
+ def publish
403
+ puts "[#{correlation_id}] Publishing message"
404
+ super
405
+ end
406
+
407
+ def self.process(header, payload)
408
+ data = JSON.parse(payload)
409
+ message = new(data)
410
+
411
+ puts "[#{message.correlation_id}] Processing message"
412
+
413
+ # Your logic here
414
+
415
+ puts "[#{message.correlation_id}] Processing complete"
416
+ end
417
+ end
418
+ ```
419
+
420
+ **Check Statistics:**
421
+
422
+ ```ruby
423
+ # Monitor message flow with statistics
424
+ def print_message_stats(message_class)
425
+ class_name = message_class.to_s
426
+ published = SS.get(class_name, 'publish')
427
+ routed = SS.get(class_name, "#{class_name}.process", 'routed')
428
+
429
+ puts "#{class_name} Statistics:"
430
+ puts " Published: #{published}"
431
+ puts " Routed: #{routed}"
432
+ puts " Success rate: #{routed.to_f / published * 100}%" if published > 0
433
+ end
434
+
435
+ # Usage
436
+ print_message_stats(MyMessage)
437
+ ```
438
+
439
+ ### 7. Configuration Issues
440
+
441
+ **Debug Configuration:**
442
+
443
+ ```ruby
444
+ # Check current configuration
445
+ def debug_message_config(message_class)
446
+ puts "#{message_class} Configuration:"
447
+ puts " Transport: #{message_class.transport.class.name}"
448
+ puts " Transport configured: #{message_class.transport_configured?}"
449
+ puts " Serializer: #{message_class.serializer.class.name}"
450
+ puts " Serializer configured: #{message_class.serializer_configured?}"
451
+
452
+ # Check instance-level overrides
453
+ instance = message_class.new
454
+ puts " Instance transport: #{instance.transport.class.name}"
455
+ puts " Instance serializer: #{instance.serializer.class.name}"
456
+ end
457
+
458
+ debug_message_config(MyMessage)
459
+ ```
460
+
461
+ **Reset Configuration:**
462
+
463
+ ```ruby
464
+ # If configuration gets corrupted, reset it
465
+ class MyMessage < SmartMessage::Base
466
+ # Reset all configuration
467
+ reset_transport
468
+ reset_serializer
469
+ reset_logger
470
+
471
+ # Reconfigure
472
+ config do
473
+ transport SmartMessage::Transport.create(:memory)
474
+ serializer SmartMessage::Serializer::JSON.new
475
+ end
476
+ end
477
+ ```
478
+
479
+ ## Performance Troubleshooting
480
+
481
+ ### Slow Message Processing
482
+
483
+ ```ruby
484
+ # Benchmark message processing
485
+ require 'benchmark'
486
+
487
+ def benchmark_message_processing(message_class, count = 100)
488
+ time = Benchmark.measure do
489
+ count.times do |i|
490
+ message_class.new(data: "test #{i}").publish
491
+ end
492
+
493
+ # Wait for processing to complete
494
+ sleep(1)
495
+ end
496
+
497
+ puts "Processed #{count} messages in #{time.real.round(2)} seconds"
498
+ puts "Rate: #{(count / time.real).round(2)} messages/second"
499
+ end
500
+
501
+ benchmark_message_processing(MyMessage, 1000)
502
+ ```
503
+
504
+ ### High Memory Usage
505
+
506
+ ```ruby
507
+ # Monitor memory during message processing
508
+ def monitor_memory_usage
509
+ require 'objspace'
510
+
511
+ initial_memory = ObjectSpace.count_objects[:TOTAL]
512
+
513
+ # Process some messages
514
+ 100.times { |i| MyMessage.new(data: "test #{i}").publish }
515
+
516
+ # Force garbage collection
517
+ GC.start
518
+
519
+ final_memory = ObjectSpace.count_objects[:TOTAL]
520
+
521
+ puts "Memory usage:"
522
+ puts " Initial: #{initial_memory} objects"
523
+ puts " Final: #{final_memory} objects"
524
+ puts " Difference: #{final_memory - initial_memory} objects"
525
+ end
526
+
527
+ monitor_memory_usage
528
+ ```
529
+
530
+ ## Getting Help
531
+
532
+ ### Collect Debug Information
533
+
534
+ ```ruby
535
+ def collect_debug_info
536
+ puts "SmartMessage Debug Information"
537
+ puts "=============================="
538
+ puts "Version: #{SmartMessage::VERSION}"
539
+ puts "Ruby version: #{RUBY_VERSION}"
540
+ puts "Platform: #{RUBY_PLATFORM}"
541
+ puts ""
542
+
543
+ # Available transports
544
+ puts "Available transports: #{SmartMessage::Transport.available.join(', ')}"
545
+ puts ""
546
+
547
+ # Current statistics
548
+ puts "Current statistics:"
549
+ SS.stat.each { |key, value| puts " #{key}: #{value}" }
550
+ puts ""
551
+
552
+ # Thread pool status if dispatcher exists
553
+ begin
554
+ dispatcher = SmartMessage::Dispatcher.new
555
+ status = dispatcher.status
556
+ puts "Dispatcher status:"
557
+ status.each { |key, value| puts " #{key}: #{value}" }
558
+ rescue => e
559
+ puts "Dispatcher error: #{e.message}"
560
+ end
561
+ end
562
+
563
+ collect_debug_info
564
+ ```
565
+
566
+ ### Enable Verbose Logging
567
+
568
+ ```ruby
569
+ # Enable debug output in test.log
570
+ require 'debug_me'
571
+ include DebugMe
572
+
573
+ # This will log to test.log with detailed information
574
+ debug_me { "Message published: #{message.to_h}" }
575
+ ```
576
+
577
+ If you're still experiencing issues after trying these troubleshooting steps, please open an issue on the [GitHub repository](https://github.com/MadBomber/smart_message) with:
578
+
579
+ 1. Your debug information (use `collect_debug_info` above)
580
+ 2. A minimal code example that reproduces the issue
581
+ 3. The full error message and stack trace
582
+ 4. Your system environment details