smart_message 0.0.13 → 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 +120 -0
- data/Gemfile.lock +3 -3
- data/README.md +71 -25
- data/docs/index.md +2 -0
- data/docs/reference/transports.md +46 -21
- data/docs/transports/memory-transport.md +2 -1
- data/docs/transports/multi-transport.md +484 -0
- 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 -30
- data/examples/memory/02_dead_letter_queue_demo.rb +9 -9
- data/examples/memory/03_point_to_point_orders.rb +3 -3
- data/examples/memory/04_publish_subscribe_events.rb +15 -15
- data/examples/memory/05_many_to_many_chat.rb +19 -19
- data/examples/memory/06_stdout_publish_only.rb +145 -0
- data/examples/memory/07_proc_handlers_demo.rb +13 -13
- data/examples/memory/08_custom_logger_demo.rb +136 -136
- data/examples/memory/09_error_handling_demo.rb +7 -7
- data/examples/memory/10_entity_addressing_basic.rb +25 -25
- data/examples/memory/11_entity_addressing_with_filtering.rb +32 -32
- data/examples/memory/12_regex_filtering_microservices.rb +10 -10
- data/examples/memory/14_global_configuration_demo.rb +12 -12
- data/examples/memory/README.md +34 -17
- 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 -20
- 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 +5 -7
- 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 +36 -6
- data/lib/smart_message/plugins.rb +46 -4
- 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/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/partitioned_files.rb +46 -0
- data/lib/smart_message/transport/stdout_transport.rb +50 -36
- data/lib/smart_message/transport/stdout_transport.rb.backup +88 -0
- data/lib/smart_message/version.rb +1 -1
- metadata +24 -10
- 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/wrapper.rb.bak +0 -132
- /data/examples/memory/{06_pretty_print_demo.rb → 16_pretty_print_demo.rb} +0 -0
@@ -0,0 +1,432 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Multi-Transport File Demo
|
6
|
+
#
|
7
|
+
# This example demonstrates advanced FileTransport usage including:
|
8
|
+
# - Combining FileTransport with other transports
|
9
|
+
# - Fan-out messaging to multiple files
|
10
|
+
# - Message routing based on content
|
11
|
+
# - Backup and archival strategies
|
12
|
+
|
13
|
+
require_relative '../../lib/smart_message'
|
14
|
+
require 'tempfile'
|
15
|
+
require 'fileutils'
|
16
|
+
|
17
|
+
# Define message classes
|
18
|
+
Dir.mkdir('messages') unless Dir.exist?('messages')
|
19
|
+
|
20
|
+
class AuditEvent < SmartMessage::Base
|
21
|
+
property :event_type, required: true
|
22
|
+
property :user_id, required: true
|
23
|
+
property :action, required: true
|
24
|
+
property :resource, required: true
|
25
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
26
|
+
property :severity, default: 'INFO', valid: %w[DEBUG INFO WARN ERROR CRITICAL]
|
27
|
+
property :details, default: {}
|
28
|
+
|
29
|
+
from 'multi_transport_file_demo'
|
30
|
+
end
|
31
|
+
|
32
|
+
class SystemMetric < SmartMessage::Base
|
33
|
+
property :metric_name, required: true
|
34
|
+
property :value, required: true
|
35
|
+
property :unit, required: true
|
36
|
+
property :host, required: true
|
37
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
38
|
+
property :tags, default: {}
|
39
|
+
|
40
|
+
from 'multi_transport_file_demo'
|
41
|
+
end
|
42
|
+
|
43
|
+
class AlertMessage < SmartMessage::Base
|
44
|
+
property :alert_id, required: true
|
45
|
+
property :severity, required: true, valid: %w[LOW MEDIUM HIGH CRITICAL]
|
46
|
+
property :message, required: true
|
47
|
+
property :source, required: true
|
48
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
49
|
+
property :metadata, default: {}
|
50
|
+
|
51
|
+
from 'multi_transport_file_demo'
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "=== SmartMessage Multi-Transport File Demo ==="
|
55
|
+
puts
|
56
|
+
|
57
|
+
demo_dir = Dir.mktmpdir('multi_transport_demo')
|
58
|
+
puts "Demo directory: #{demo_dir}"
|
59
|
+
|
60
|
+
begin
|
61
|
+
# Example 1: Fan-out to Multiple Files
|
62
|
+
puts "\n1. Fan-out to Multiple Files"
|
63
|
+
puts "=" * 35
|
64
|
+
|
65
|
+
# Create multiple file transports for different purposes
|
66
|
+
main_log = File.join(demo_dir, 'main.log')
|
67
|
+
audit_log = File.join(demo_dir, 'audit.log')
|
68
|
+
backup_log = File.join(demo_dir, 'backup.log')
|
69
|
+
|
70
|
+
main_transport = SmartMessage::Transport::FileTransport.new(
|
71
|
+
file_path: main_log,
|
72
|
+
format: :json
|
73
|
+
)
|
74
|
+
|
75
|
+
audit_transport = SmartMessage::Transport::FileTransport.new(
|
76
|
+
file_path: audit_log,
|
77
|
+
format: :yaml
|
78
|
+
)
|
79
|
+
|
80
|
+
backup_transport = SmartMessage::Transport::FileTransport.new(
|
81
|
+
file_path: backup_log,
|
82
|
+
format: :raw,
|
83
|
+
serializer: ->(msg) { "#{msg.timestamp} | #{msg.event_type} | #{msg.user_id} | #{msg.action}\n" }
|
84
|
+
)
|
85
|
+
|
86
|
+
# Configure AuditEvent to use multiple transports
|
87
|
+
AuditEvent.class_eval do
|
88
|
+
transport [main_transport, audit_transport, backup_transport]
|
89
|
+
end
|
90
|
+
|
91
|
+
puts "✓ Configured fan-out to 3 files:"
|
92
|
+
puts " - Main log (JSON): #{main_log}"
|
93
|
+
puts " - Audit log (YAML): #{audit_log}"
|
94
|
+
puts " - Backup log (Custom): #{backup_log}"
|
95
|
+
|
96
|
+
# Send audit events
|
97
|
+
events = [
|
98
|
+
{ event_type: 'USER_LOGIN', user_id: 'alice', action: 'authenticate', resource: 'web_app' },
|
99
|
+
{ event_type: 'DATA_ACCESS', user_id: 'bob', action: 'read', resource: 'customer_db', severity: 'WARN' },
|
100
|
+
{ event_type: 'ADMIN_ACTION', user_id: 'admin', action: 'delete_user', resource: 'user_mgmt', severity: 'CRITICAL' },
|
101
|
+
{ event_type: 'USER_LOGOUT', user_id: 'alice', action: 'logout', resource: 'web_app' }
|
102
|
+
]
|
103
|
+
|
104
|
+
events.each do |event_data|
|
105
|
+
AuditEvent.new(**event_data).publish
|
106
|
+
puts " → Sent: #{event_data[:event_type]} by #{event_data[:user_id]}"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Show results
|
110
|
+
puts "\nMain Log (JSON):"
|
111
|
+
puts File.read(main_log)
|
112
|
+
|
113
|
+
puts "\nAudit Log (YAML):"
|
114
|
+
puts File.read(audit_log)
|
115
|
+
|
116
|
+
puts "\nBackup Log (Custom):"
|
117
|
+
puts File.read(backup_log)
|
118
|
+
|
119
|
+
# Example 2: Conditional File Routing
|
120
|
+
puts "\n2. Conditional File Routing"
|
121
|
+
puts "=" * 35
|
122
|
+
|
123
|
+
# Create files for different severity levels
|
124
|
+
info_file = File.join(demo_dir, 'info.log')
|
125
|
+
warn_file = File.join(demo_dir, 'warnings.log')
|
126
|
+
error_file = File.join(demo_dir, 'errors.log')
|
127
|
+
|
128
|
+
# Create routing transports with filters
|
129
|
+
info_transport = SmartMessage::Transport::FileTransport.new(
|
130
|
+
file_path: info_file,
|
131
|
+
format: :json,
|
132
|
+
message_filter: ->(msg) { %w[DEBUG INFO].include?(msg.severity) }
|
133
|
+
)
|
134
|
+
|
135
|
+
warn_transport = SmartMessage::Transport::FileTransport.new(
|
136
|
+
file_path: warn_file,
|
137
|
+
format: :json,
|
138
|
+
message_filter: ->(msg) { msg.severity == 'WARN' }
|
139
|
+
)
|
140
|
+
|
141
|
+
error_transport = SmartMessage::Transport::FileTransport.new(
|
142
|
+
file_path: error_file,
|
143
|
+
format: :json,
|
144
|
+
message_filter: ->(msg) { %w[ERROR CRITICAL].include?(msg.severity) }
|
145
|
+
)
|
146
|
+
|
147
|
+
puts "✓ Configured conditional routing based on severity"
|
148
|
+
puts "Note: Using simplified approach - routing messages to appropriate transports"
|
149
|
+
|
150
|
+
# Create simple message classes for each severity level
|
151
|
+
class InfoAuditEvent < SmartMessage::Base
|
152
|
+
property :event_type, required: true
|
153
|
+
property :user_id, required: true
|
154
|
+
property :action, required: true
|
155
|
+
property :resource, required: true
|
156
|
+
property :severity, required: true
|
157
|
+
from 'multi_transport_file_demo'
|
158
|
+
end
|
159
|
+
|
160
|
+
class WarnAuditEvent < SmartMessage::Base
|
161
|
+
property :event_type, required: true
|
162
|
+
property :user_id, required: true
|
163
|
+
property :action, required: true
|
164
|
+
property :resource, required: true
|
165
|
+
property :severity, required: true
|
166
|
+
from 'multi_transport_file_demo'
|
167
|
+
end
|
168
|
+
|
169
|
+
class ErrorAuditEvent < SmartMessage::Base
|
170
|
+
property :event_type, required: true
|
171
|
+
property :user_id, required: true
|
172
|
+
property :action, required: true
|
173
|
+
property :resource, required: true
|
174
|
+
property :severity, required: true
|
175
|
+
from 'multi_transport_file_demo'
|
176
|
+
end
|
177
|
+
|
178
|
+
InfoAuditEvent.class_eval { transport info_transport }
|
179
|
+
WarnAuditEvent.class_eval { transport warn_transport }
|
180
|
+
ErrorAuditEvent.class_eval { transport error_transport }
|
181
|
+
|
182
|
+
# Send mixed severity events
|
183
|
+
mixed_events = [
|
184
|
+
{ event_type: 'DEBUG_INFO', user_id: 'dev', action: 'debug', resource: 'api', severity: 'DEBUG' },
|
185
|
+
{ event_type: 'USER_ACTION', user_id: 'user1', action: 'view', resource: 'page', severity: 'INFO' },
|
186
|
+
{ event_type: 'SLOW_QUERY', user_id: 'system', action: 'query', resource: 'database', severity: 'WARN' },
|
187
|
+
{ event_type: 'FAILED_LOGIN', user_id: 'attacker', action: 'login', resource: 'auth', severity: 'ERROR' },
|
188
|
+
{ event_type: 'SYSTEM_DOWN', user_id: 'system', action: 'crash', resource: 'server', severity: 'CRITICAL' }
|
189
|
+
]
|
190
|
+
|
191
|
+
mixed_events.each do |event_data|
|
192
|
+
case event_data[:severity]
|
193
|
+
when 'DEBUG', 'INFO'
|
194
|
+
InfoAuditEvent.new(**event_data).publish
|
195
|
+
when 'WARN'
|
196
|
+
WarnAuditEvent.new(**event_data).publish
|
197
|
+
when 'ERROR', 'CRITICAL'
|
198
|
+
ErrorAuditEvent.new(**event_data).publish
|
199
|
+
end
|
200
|
+
puts " → Routed #{event_data[:severity]} event to appropriate log"
|
201
|
+
end
|
202
|
+
|
203
|
+
# Show routing results
|
204
|
+
puts "\nInfo Log (DEBUG/INFO):"
|
205
|
+
puts File.read(info_file) if File.exist?(info_file) && File.size(info_file) > 0
|
206
|
+
|
207
|
+
puts "\nWarning Log (WARN):"
|
208
|
+
puts File.read(warn_file) if File.exist?(warn_file) && File.size(warn_file) > 0
|
209
|
+
|
210
|
+
puts "\nError Log (ERROR/CRITICAL):"
|
211
|
+
puts File.read(error_file) if File.exist?(error_file) && File.size(error_file) > 0
|
212
|
+
|
213
|
+
# Example 3: File + Memory + STDOUT Multi-Transport
|
214
|
+
puts "\n3. File + Memory + STDOUT Multi-Transport"
|
215
|
+
puts "=" * 45
|
216
|
+
|
217
|
+
metrics_file = File.join(demo_dir, 'metrics.log')
|
218
|
+
|
219
|
+
file_transport = SmartMessage::Transport::FileTransport.new(
|
220
|
+
file_path: metrics_file,
|
221
|
+
format: :json
|
222
|
+
)
|
223
|
+
|
224
|
+
memory_transport = SmartMessage::Transport::MemoryTransport.new(
|
225
|
+
auto_process: false
|
226
|
+
)
|
227
|
+
|
228
|
+
stdout_transport = SmartMessage::Transport::StdoutTransport.new(
|
229
|
+
format: :pretty
|
230
|
+
)
|
231
|
+
|
232
|
+
SystemMetric.class_eval do
|
233
|
+
transport [file_transport, memory_transport, stdout_transport]
|
234
|
+
end
|
235
|
+
|
236
|
+
puts "✓ Configured SystemMetric with 3 transports:"
|
237
|
+
puts " - File storage (persistent)"
|
238
|
+
puts " - Memory storage (fast access)"
|
239
|
+
puts " - STDOUT display (real-time monitoring)"
|
240
|
+
|
241
|
+
# Send system metrics
|
242
|
+
metrics = [
|
243
|
+
{ metric_name: 'cpu_usage', value: 45.2, unit: 'percent', host: 'web01' },
|
244
|
+
{ metric_name: 'memory_usage', value: 2048, unit: 'MB', host: 'web01' },
|
245
|
+
{ metric_name: 'disk_free', value: 15.8, unit: 'GB', host: 'web01' },
|
246
|
+
{ metric_name: 'response_time', value: 120, unit: 'ms', host: 'api01' }
|
247
|
+
]
|
248
|
+
|
249
|
+
metrics.each do |metric_data|
|
250
|
+
SystemMetric.new(**metric_data).publish
|
251
|
+
end
|
252
|
+
|
253
|
+
puts "\nFile storage contents:"
|
254
|
+
puts File.read(metrics_file)
|
255
|
+
|
256
|
+
puts "\nMemory storage contents:"
|
257
|
+
memory_transport.messages.each_with_index do |msg, i|
|
258
|
+
puts " #{i + 1}. #{msg[:metric_name]}: #{msg[:value]} #{msg[:unit]} (#{msg[:host]})"
|
259
|
+
end
|
260
|
+
|
261
|
+
# Example 4: Archive and Cleanup Strategy
|
262
|
+
puts "\n4. Archive and Cleanup Strategy"
|
263
|
+
puts "=" * 40
|
264
|
+
|
265
|
+
current_log = File.join(demo_dir, 'current.log')
|
266
|
+
archive_dir = File.join(demo_dir, 'archive')
|
267
|
+
Dir.mkdir(archive_dir)
|
268
|
+
|
269
|
+
# Simulated archival transport
|
270
|
+
class ArchivalTransport
|
271
|
+
def initialize(current_file, archive_dir, max_size: 1024)
|
272
|
+
@current_file = current_file
|
273
|
+
@archive_dir = archive_dir
|
274
|
+
@max_size = max_size
|
275
|
+
@file_transport = SmartMessage::Transport::FileTransport.new(
|
276
|
+
file_path: @current_file,
|
277
|
+
format: :json
|
278
|
+
)
|
279
|
+
end
|
280
|
+
|
281
|
+
def publish(message)
|
282
|
+
# Check if rotation is needed
|
283
|
+
if File.exist?(@current_file) && File.size(@current_file) > @max_size
|
284
|
+
rotate_file
|
285
|
+
end
|
286
|
+
|
287
|
+
@file_transport.publish(message)
|
288
|
+
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
def rotate_file
|
293
|
+
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
|
294
|
+
archive_file = File.join(@archive_dir, "archive_#{timestamp}.log")
|
295
|
+
|
296
|
+
FileUtils.mv(@current_file, archive_file)
|
297
|
+
puts " → Archived #{@current_file} to #{archive_file}"
|
298
|
+
|
299
|
+
# Recreate transport for new file
|
300
|
+
@file_transport = SmartMessage::Transport::FileTransport.new(
|
301
|
+
file_path: @current_file,
|
302
|
+
format: :json
|
303
|
+
)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
archival_transport = ArchivalTransport.new(current_log, archive_dir, max_size: 200) # Small for demo
|
308
|
+
|
309
|
+
class ArchivedAlert < SmartMessage::Base
|
310
|
+
property :alert_id, required: true
|
311
|
+
property :severity, required: true
|
312
|
+
property :message, required: true
|
313
|
+
property :source, required: true
|
314
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
315
|
+
|
316
|
+
from 'multi_transport_file_demo'
|
317
|
+
end
|
318
|
+
|
319
|
+
ArchivedAlert.class_eval do
|
320
|
+
transport archival_transport
|
321
|
+
end
|
322
|
+
|
323
|
+
puts "✓ Configured archival transport with 200-byte rotation"
|
324
|
+
|
325
|
+
# Send alerts to trigger rotation
|
326
|
+
15.times do |i|
|
327
|
+
ArchivedAlert.new(
|
328
|
+
alert_id: "ALERT_#{i + 1}",
|
329
|
+
severity: %w[LOW MEDIUM HIGH CRITICAL].sample,
|
330
|
+
message: "Alert message #{i + 1} with some details to make it longer",
|
331
|
+
source: 'monitoring_system'
|
332
|
+
).publish
|
333
|
+
end
|
334
|
+
|
335
|
+
puts "\nArchival results:"
|
336
|
+
puts "Current log size: #{File.exist?(current_log) ? File.size(current_log) : 0} bytes"
|
337
|
+
|
338
|
+
archive_files = Dir.glob(File.join(archive_dir, '*.log')).sort
|
339
|
+
puts "Archive files created: #{archive_files.length}"
|
340
|
+
archive_files.each do |file|
|
341
|
+
puts " - #{File.basename(file)} (#{File.size(file)} bytes)"
|
342
|
+
end
|
343
|
+
|
344
|
+
# Example 5: Performance Monitoring
|
345
|
+
puts "\n5. Performance Monitoring"
|
346
|
+
puts "=" * 30
|
347
|
+
|
348
|
+
perf_file = File.join(demo_dir, 'performance.log')
|
349
|
+
|
350
|
+
# Transport with performance metrics
|
351
|
+
class PerformanceFileTransport < SmartMessage::Transport::FileTransport
|
352
|
+
attr_reader :message_count, :total_write_time, :avg_write_time
|
353
|
+
|
354
|
+
def initialize(*args)
|
355
|
+
super
|
356
|
+
@message_count = 0
|
357
|
+
@total_write_time = 0.0
|
358
|
+
end
|
359
|
+
|
360
|
+
def publish(message)
|
361
|
+
start_time = Time.now
|
362
|
+
result = super
|
363
|
+
end_time = Time.now
|
364
|
+
|
365
|
+
@message_count += 1
|
366
|
+
@total_write_time += (end_time - start_time)
|
367
|
+
@avg_write_time = @total_write_time / @message_count
|
368
|
+
|
369
|
+
result
|
370
|
+
end
|
371
|
+
|
372
|
+
def stats
|
373
|
+
{
|
374
|
+
messages_sent: @message_count,
|
375
|
+
total_time: @total_write_time.round(4),
|
376
|
+
average_time: @avg_write_time.round(4),
|
377
|
+
messages_per_second: (@message_count / @total_write_time).round(2)
|
378
|
+
}
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
perf_transport = PerformanceFileTransport.new(
|
383
|
+
file_path: perf_file,
|
384
|
+
format: :json
|
385
|
+
)
|
386
|
+
|
387
|
+
class PerfTestMessage < SmartMessage::Base
|
388
|
+
property :id, required: true
|
389
|
+
property :data, required: true
|
390
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
391
|
+
|
392
|
+
from 'multi_transport_file_demo'
|
393
|
+
end
|
394
|
+
|
395
|
+
PerfTestMessage.class_eval do
|
396
|
+
transport perf_transport
|
397
|
+
end
|
398
|
+
|
399
|
+
puts "✓ Starting performance test..."
|
400
|
+
|
401
|
+
# Performance test
|
402
|
+
test_count = 100
|
403
|
+
start_time = Time.now
|
404
|
+
|
405
|
+
test_count.times do |i|
|
406
|
+
PerfTestMessage.new(
|
407
|
+
id: i + 1,
|
408
|
+
data: "Performance test message #{i + 1} with some payload data " * 5
|
409
|
+
).publish
|
410
|
+
end
|
411
|
+
|
412
|
+
end_time = Time.now
|
413
|
+
total_time = end_time - start_time
|
414
|
+
|
415
|
+
stats = perf_transport.stats
|
416
|
+
|
417
|
+
puts "Performance Results:"
|
418
|
+
puts " - Messages sent: #{stats[:messages_sent]}"
|
419
|
+
puts " - Total time: #{total_time.round(4)}s"
|
420
|
+
puts " - Average write time: #{stats[:average_time]}s"
|
421
|
+
puts " - Messages per second: #{stats[:messages_per_second]}"
|
422
|
+
puts " - File size: #{File.size(perf_file)} bytes"
|
423
|
+
|
424
|
+
rescue => e
|
425
|
+
puts "Error: #{e.message}"
|
426
|
+
puts e.backtrace.first(3)
|
427
|
+
ensure
|
428
|
+
# Cleanup
|
429
|
+
FileUtils.rm_rf(demo_dir) if Dir.exist?(demo_dir)
|
430
|
+
FileUtils.rm_rf('messages') if Dir.exist?('messages')
|
431
|
+
puts "\n✓ Multi-transport demo completed and cleaned up"
|
432
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# SmartMessage FileTransport Examples
|
2
|
+
|
3
|
+
This directory contains comprehensive examples demonstrating the capabilities of SmartMessage's FileTransport class. The FileTransport provides powerful file-based messaging with support for multiple formats, FIFO operations, file watching, and advanced routing patterns.
|
4
|
+
|
5
|
+
## Quick Start
|
6
|
+
|
7
|
+
Run all examples:
|
8
|
+
```bash
|
9
|
+
ruby 00_run_all_file_demos.rb all
|
10
|
+
```
|
11
|
+
|
12
|
+
Run interactively:
|
13
|
+
```bash
|
14
|
+
ruby 00_run_all_file_demos.rb
|
15
|
+
```
|
16
|
+
|
17
|
+
## Examples Overview
|
18
|
+
|
19
|
+
### 1. Basic File Transport Demo (`01_basic_file_transport_demo.rb`)
|
20
|
+
|
21
|
+
**What it demonstrates:**
|
22
|
+
- Core FileTransport functionality
|
23
|
+
- Multiple output formats (JSON, YAML, raw)
|
24
|
+
- Append vs overwrite modes
|
25
|
+
- Custom serialization for CSV output
|
26
|
+
- File rotation concepts
|
27
|
+
|
28
|
+
**Key concepts:**
|
29
|
+
- Message persistence to files
|
30
|
+
- Format flexibility
|
31
|
+
- Custom serializers
|
32
|
+
- Write mode configuration
|
33
|
+
|
34
|
+
**Sample output:**
|
35
|
+
```ruby
|
36
|
+
# JSON format
|
37
|
+
{"level":"INFO","message":"Application started","timestamp":"2024-01-15T10:00:00Z","component":"main"}
|
38
|
+
|
39
|
+
# Custom CSV format
|
40
|
+
timestamp,user_id,action,details
|
41
|
+
2024-01-15T10:00:00Z,12345,login,"{:ip=>\"192.168.1.1\"}"
|
42
|
+
```
|
43
|
+
|
44
|
+
### 2. FIFO Transport Demo (`02_fifo_transport_demo.rb`)
|
45
|
+
|
46
|
+
**What it demonstrates:**
|
47
|
+
- Named pipes (FIFO) for inter-process communication
|
48
|
+
- Real-time message streaming
|
49
|
+
- Multiple writer processes to single reader
|
50
|
+
- Non-blocking FIFO operations
|
51
|
+
- Message filtering with FIFOs
|
52
|
+
|
53
|
+
**Key concepts:**
|
54
|
+
- Process-to-process messaging
|
55
|
+
- Real-time communication
|
56
|
+
- Concurrent access patterns
|
57
|
+
- System-level integration
|
58
|
+
|
59
|
+
**Requirements:**
|
60
|
+
- Unix-like system with `mkfifo` support
|
61
|
+
- Will be skipped automatically on unsupported systems
|
62
|
+
|
63
|
+
**Sample usage:**
|
64
|
+
```ruby
|
65
|
+
# Create FIFO transport
|
66
|
+
fifo_transport = SmartMessage::Transport::FileTransport.new(
|
67
|
+
file_path: '/tmp/message_pipe.fifo',
|
68
|
+
file_type: :fifo,
|
69
|
+
format: :json
|
70
|
+
)
|
71
|
+
```
|
72
|
+
|
73
|
+
### 3. File Watching Demo (`03_file_watching_demo.rb`)
|
74
|
+
|
75
|
+
**What it demonstrates:**
|
76
|
+
- File change monitoring
|
77
|
+
- Configuration file watching
|
78
|
+
- Log rotation handling
|
79
|
+
- Multiple file monitoring
|
80
|
+
- Pattern-based content processing
|
81
|
+
|
82
|
+
**Key concepts:**
|
83
|
+
- Reactive file processing
|
84
|
+
- Configuration change detection
|
85
|
+
- Log aggregation patterns
|
86
|
+
- Real-time file monitoring
|
87
|
+
|
88
|
+
**Sample configuration:**
|
89
|
+
```ruby
|
90
|
+
# Watch for file changes
|
91
|
+
watching_transport = SmartMessage::Transport::FileTransport.new(
|
92
|
+
file_path: 'application.log',
|
93
|
+
enable_subscriptions: true,
|
94
|
+
subscription_mode: :poll_changes,
|
95
|
+
poll_interval: 0.5,
|
96
|
+
read_from: :end
|
97
|
+
)
|
98
|
+
```
|
99
|
+
|
100
|
+
### 4. Multi-Transport File Demo (`04_multi_transport_file_demo.rb`)
|
101
|
+
|
102
|
+
**What it demonstrates:**
|
103
|
+
- Fan-out messaging to multiple files
|
104
|
+
- Conditional routing based on message content
|
105
|
+
- Combining FileTransport with other transports
|
106
|
+
- Archive and cleanup strategies
|
107
|
+
- Performance monitoring
|
108
|
+
|
109
|
+
**Key concepts:**
|
110
|
+
- Message routing patterns
|
111
|
+
- Multi-destination publishing
|
112
|
+
- Archive management
|
113
|
+
- Performance optimization
|
114
|
+
|
115
|
+
**Advanced patterns:**
|
116
|
+
```ruby
|
117
|
+
# Fan-out to multiple destinations
|
118
|
+
AuditEvent.configure do |config|
|
119
|
+
config.transport = [
|
120
|
+
main_transport, # JSON format
|
121
|
+
audit_transport, # YAML format
|
122
|
+
backup_transport # Custom format
|
123
|
+
]
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
## Demo Runner (`00_run_all_file_demos.rb`)
|
128
|
+
|
129
|
+
The demo runner provides multiple ways to explore the examples:
|
130
|
+
|
131
|
+
### Interactive Mode
|
132
|
+
```bash
|
133
|
+
ruby 00_run_all_file_demos.rb
|
134
|
+
```
|
135
|
+
- Menu-driven interface
|
136
|
+
- Run individual demos or all demos
|
137
|
+
- System requirement checking
|
138
|
+
- Automatic FIFO support detection
|
139
|
+
|
140
|
+
### Command Line Mode
|
141
|
+
```bash
|
142
|
+
# Run all demos
|
143
|
+
ruby 00_run_all_file_demos.rb all
|
144
|
+
|
145
|
+
# List available demos
|
146
|
+
ruby 00_run_all_file_demos.rb list
|
147
|
+
|
148
|
+
# Run specific demo
|
149
|
+
ruby 00_run_all_file_demos.rb 1
|
150
|
+
```
|
151
|
+
|
152
|
+
## System Requirements
|
153
|
+
|
154
|
+
- **Ruby**: 2.7 or later
|
155
|
+
- **Platform**: Cross-platform (Windows, macOS, Linux)
|
156
|
+
- **FIFO Support**: Unix-like systems for FIFO demos
|
157
|
+
- **Dependencies**: SmartMessage gem
|
158
|
+
|
159
|
+
## Key FileTransport Features Demonstrated
|
160
|
+
|
161
|
+
### File Operations
|
162
|
+
- ✅ Writing to regular files
|
163
|
+
- ✅ Append and overwrite modes
|
164
|
+
- ✅ Multiple output formats
|
165
|
+
- ✅ Custom serialization
|
166
|
+
- ✅ File rotation handling
|
167
|
+
|
168
|
+
### FIFO Operations
|
169
|
+
- ✅ Named pipe creation and usage
|
170
|
+
- ✅ Inter-process communication
|
171
|
+
- ✅ Blocking and non-blocking modes
|
172
|
+
- ✅ Multiple writers, single reader
|
173
|
+
- ✅ Real-time message streaming
|
174
|
+
|
175
|
+
### File Watching
|
176
|
+
- ✅ Change detection and monitoring
|
177
|
+
- ✅ Configuration file watching
|
178
|
+
- ✅ Log rotation awareness
|
179
|
+
- ✅ Multiple file monitoring
|
180
|
+
- ✅ Pattern-based processing
|
181
|
+
|
182
|
+
### Advanced Features
|
183
|
+
- ✅ Multi-transport configurations
|
184
|
+
- ✅ Message routing and filtering
|
185
|
+
- ✅ Performance monitoring
|
186
|
+
- ✅ Archive strategies
|
187
|
+
- ✅ Error handling
|
188
|
+
|
189
|
+
## Best Practices Shown
|
190
|
+
|
191
|
+
1. **Message Class Organization**
|
192
|
+
- Store message classes in `messages/` directory
|
193
|
+
- Use clear, descriptive property definitions
|
194
|
+
- Include validation where appropriate
|
195
|
+
|
196
|
+
2. **Transport Configuration**
|
197
|
+
- Choose appropriate formats for use case
|
198
|
+
- Configure proper file modes
|
199
|
+
- Handle cleanup in ensure blocks
|
200
|
+
|
201
|
+
3. **Error Handling**
|
202
|
+
- Graceful degradation for unsupported features
|
203
|
+
- Proper resource cleanup
|
204
|
+
- Informative error messages
|
205
|
+
|
206
|
+
4. **Performance Considerations**
|
207
|
+
- Appropriate polling intervals
|
208
|
+
- Efficient serialization
|
209
|
+
- Resource management
|
210
|
+
|
211
|
+
## Troubleshooting
|
212
|
+
|
213
|
+
### FIFO Not Supported
|
214
|
+
If you see "FIFOs are not supported on this system":
|
215
|
+
- This is expected on Windows
|
216
|
+
- FIFO demos will be automatically skipped
|
217
|
+
- Other demos will still work normally
|
218
|
+
|
219
|
+
### Permission Errors
|
220
|
+
If you encounter permission errors:
|
221
|
+
- Ensure write access to the demo directory
|
222
|
+
- Check that temporary directories can be created
|
223
|
+
- Verify file system supports the operations
|
224
|
+
|
225
|
+
### Performance Issues
|
226
|
+
If file operations seem slow:
|
227
|
+
- Adjust polling intervals in file watching demos
|
228
|
+
- Consider using smaller message sizes
|
229
|
+
- Check available disk space
|
230
|
+
|
231
|
+
## Next Steps
|
232
|
+
|
233
|
+
After exploring these examples:
|
234
|
+
|
235
|
+
1. **Adapt for Your Use Case**
|
236
|
+
- Modify message classes for your domain
|
237
|
+
- Adjust file formats and paths
|
238
|
+
- Customize routing logic
|
239
|
+
|
240
|
+
2. **Integration Patterns**
|
241
|
+
- Combine with other SmartMessage transports
|
242
|
+
- Add to existing logging infrastructure
|
243
|
+
- Build monitoring dashboards
|
244
|
+
|
245
|
+
3. **Production Considerations**
|
246
|
+
- Add proper error handling
|
247
|
+
- Implement log rotation
|
248
|
+
- Monitor file system usage
|
249
|
+
- Add authentication/authorization
|
250
|
+
|
251
|
+
## Related Examples
|
252
|
+
|
253
|
+
- `../memory/` - Memory transport examples
|
254
|
+
- `../redis/` - Redis transport examples
|
255
|
+
- `../multi_transport_example.rb` - Cross-transport patterns
|
256
|
+
|
257
|
+
For more information, see the main SmartMessage documentation.
|