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,260 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Run All File Transport Demos
|
6
|
+
#
|
7
|
+
# This script runs all the FileTransport demonstration programs
|
8
|
+
# and provides a summary of each demo's capabilities.
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
|
12
|
+
puts "š SmartMessage FileTransport Demo Suite"
|
13
|
+
puts "=" * 50
|
14
|
+
puts
|
15
|
+
|
16
|
+
demos = [
|
17
|
+
{
|
18
|
+
file: '01_basic_file_transport_demo.rb',
|
19
|
+
title: 'Basic File Transport Demo',
|
20
|
+
description: 'Core FileTransport functionality including writing, formats, and modes'
|
21
|
+
},
|
22
|
+
{
|
23
|
+
file: '02_fifo_transport_demo.rb',
|
24
|
+
title: 'FIFO Transport Demo',
|
25
|
+
description: 'Named pipes (FIFO) for real-time inter-process communication'
|
26
|
+
},
|
27
|
+
{
|
28
|
+
file: '03_file_watching_demo.rb',
|
29
|
+
title: 'File Watching Demo',
|
30
|
+
description: 'Monitoring files for changes and processing new content'
|
31
|
+
},
|
32
|
+
{
|
33
|
+
file: '04_multi_transport_file_demo.rb',
|
34
|
+
title: 'Multi-Transport File Demo',
|
35
|
+
description: 'Advanced patterns with multiple transports and routing'
|
36
|
+
}
|
37
|
+
]
|
38
|
+
|
39
|
+
def run_demo(demo_file, title)
|
40
|
+
puts "š§ Running: #{title}"
|
41
|
+
puts "-" * 60
|
42
|
+
|
43
|
+
start_time = Time.now
|
44
|
+
|
45
|
+
begin
|
46
|
+
# Run the demo in a separate process to isolate any issues
|
47
|
+
output = `ruby #{demo_file} 2>&1`
|
48
|
+
exit_status = $?.exitstatus
|
49
|
+
|
50
|
+
end_time = Time.now
|
51
|
+
duration = (end_time - start_time).round(2)
|
52
|
+
|
53
|
+
if exit_status == 0
|
54
|
+
puts output
|
55
|
+
puts "ā
SUCCESS - Completed in #{duration}s"
|
56
|
+
else
|
57
|
+
puts "ā FAILED - Exit status: #{exit_status}"
|
58
|
+
puts "Output:"
|
59
|
+
puts output
|
60
|
+
end
|
61
|
+
|
62
|
+
return exit_status == 0
|
63
|
+
|
64
|
+
rescue => e
|
65
|
+
puts "ā ERROR - #{e.message}"
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_system_requirements
|
71
|
+
puts "š Checking System Requirements"
|
72
|
+
puts "-" * 40
|
73
|
+
|
74
|
+
requirements = {
|
75
|
+
'Ruby version' => RUBY_VERSION,
|
76
|
+
'Platform' => RUBY_PLATFORM,
|
77
|
+
'SmartMessage available' => File.exist?('../../lib/smart_message.rb')
|
78
|
+
}
|
79
|
+
|
80
|
+
requirements.each do |req, status|
|
81
|
+
puts " #{req}: #{status}"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Check for FIFO support
|
85
|
+
fifo_supported = false
|
86
|
+
begin
|
87
|
+
test_dir = Dir.mktmpdir('fifo_check')
|
88
|
+
test_fifo = File.join(test_dir, 'test.fifo')
|
89
|
+
fifo_supported = system("mkfifo #{test_fifo} 2>/dev/null") && File.exist?(test_fifo)
|
90
|
+
FileUtils.rm_rf(test_dir)
|
91
|
+
rescue
|
92
|
+
fifo_supported = false
|
93
|
+
end
|
94
|
+
|
95
|
+
puts " FIFO support: #{fifo_supported ? 'ā
Available' : 'ā Not available'}"
|
96
|
+
|
97
|
+
unless fifo_supported
|
98
|
+
puts " ā ļø Note: FIFO demos will be skipped on this system"
|
99
|
+
end
|
100
|
+
|
101
|
+
puts
|
102
|
+
return fifo_supported
|
103
|
+
end
|
104
|
+
|
105
|
+
def show_demo_menu(demos)
|
106
|
+
puts "š Available Demos:"
|
107
|
+
puts "-" * 20
|
108
|
+
|
109
|
+
demos.each_with_index do |demo, index|
|
110
|
+
puts " #{index + 1}. #{demo[:title]}"
|
111
|
+
puts " #{demo[:description]}"
|
112
|
+
puts
|
113
|
+
end
|
114
|
+
|
115
|
+
puts " 0. Run all demos"
|
116
|
+
puts " q. Quit"
|
117
|
+
puts
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_user_choice(max_choice)
|
121
|
+
loop do
|
122
|
+
print "Enter your choice (0-#{max_choice}, q): "
|
123
|
+
input = gets.chomp.downcase
|
124
|
+
|
125
|
+
return :quit if input == 'q'
|
126
|
+
return 0 if input == '0'
|
127
|
+
|
128
|
+
choice = input.to_i
|
129
|
+
if choice >= 1 && choice <= max_choice
|
130
|
+
return choice
|
131
|
+
end
|
132
|
+
|
133
|
+
puts "Invalid choice. Please try again."
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Change to the examples/file directory
|
138
|
+
script_dir = File.dirname(__FILE__)
|
139
|
+
Dir.chdir(script_dir)
|
140
|
+
|
141
|
+
# Check system requirements
|
142
|
+
fifo_supported = check_system_requirements
|
143
|
+
|
144
|
+
# Interactive mode
|
145
|
+
if ARGV.empty?
|
146
|
+
loop do
|
147
|
+
show_demo_menu(demos)
|
148
|
+
choice = get_user_choice(demos.length)
|
149
|
+
|
150
|
+
break if choice == :quit
|
151
|
+
|
152
|
+
puts
|
153
|
+
|
154
|
+
if choice == 0
|
155
|
+
# Run all demos
|
156
|
+
puts "š Running All Demos"
|
157
|
+
puts "=" * 30
|
158
|
+
puts
|
159
|
+
|
160
|
+
success_count = 0
|
161
|
+
total_start = Time.now
|
162
|
+
|
163
|
+
demos.each_with_index do |demo, index|
|
164
|
+
# Skip FIFO demo if not supported
|
165
|
+
if demo[:file].include?('fifo') && !fifo_supported
|
166
|
+
puts "āļø Skipping #{demo[:title]} (FIFO not supported)"
|
167
|
+
puts
|
168
|
+
next
|
169
|
+
end
|
170
|
+
|
171
|
+
if run_demo(demo[:file], demo[:title])
|
172
|
+
success_count += 1
|
173
|
+
end
|
174
|
+
puts
|
175
|
+
end
|
176
|
+
|
177
|
+
total_time = (Time.now - total_start).round(2)
|
178
|
+
|
179
|
+
puts "š Summary"
|
180
|
+
puts "=" * 20
|
181
|
+
puts "Successful demos: #{success_count}/#{demos.length}"
|
182
|
+
puts "Total time: #{total_time}s"
|
183
|
+
puts
|
184
|
+
|
185
|
+
else
|
186
|
+
# Run specific demo
|
187
|
+
demo = demos[choice - 1]
|
188
|
+
|
189
|
+
# Check if FIFO demo on unsupported system
|
190
|
+
if demo[:file].include?('fifo') && !fifo_supported
|
191
|
+
puts "ā Cannot run #{demo[:title]} - FIFO not supported on this system"
|
192
|
+
puts
|
193
|
+
next
|
194
|
+
end
|
195
|
+
|
196
|
+
run_demo(demo[:file], demo[:title])
|
197
|
+
puts
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
puts "š Thanks for exploring SmartMessage FileTransport!"
|
202
|
+
|
203
|
+
else
|
204
|
+
# Command line mode
|
205
|
+
case ARGV[0]
|
206
|
+
when 'all'
|
207
|
+
puts "š Running All Demos (Non-Interactive Mode)"
|
208
|
+
puts "=" * 45
|
209
|
+
puts
|
210
|
+
|
211
|
+
success_count = 0
|
212
|
+
|
213
|
+
demos.each do |demo|
|
214
|
+
# Skip FIFO demo if not supported
|
215
|
+
if demo[:file].include?('fifo') && !fifo_supported
|
216
|
+
puts "āļø Skipping #{demo[:title]} (FIFO not supported)"
|
217
|
+
puts
|
218
|
+
next
|
219
|
+
end
|
220
|
+
|
221
|
+
if run_demo(demo[:file], demo[:title])
|
222
|
+
success_count += 1
|
223
|
+
end
|
224
|
+
puts
|
225
|
+
end
|
226
|
+
|
227
|
+
puts "š Final Summary: #{success_count}/#{demos.length} demos successful"
|
228
|
+
|
229
|
+
when 'list'
|
230
|
+
puts "š Available FileTransport Demos:"
|
231
|
+
demos.each_with_index do |demo, index|
|
232
|
+
puts " #{index + 1}. #{demo[:file]} - #{demo[:title]}"
|
233
|
+
end
|
234
|
+
|
235
|
+
when /^\d+$/
|
236
|
+
choice = ARGV[0].to_i
|
237
|
+
if choice >= 1 && choice <= demos.length
|
238
|
+
demo = demos[choice - 1]
|
239
|
+
|
240
|
+
if demo[:file].include?('fifo') && !fifo_supported
|
241
|
+
puts "ā Cannot run #{demo[:title]} - FIFO not supported on this system"
|
242
|
+
exit 1
|
243
|
+
end
|
244
|
+
|
245
|
+
success = run_demo(demo[:file], demo[:title])
|
246
|
+
exit(success ? 0 : 1)
|
247
|
+
else
|
248
|
+
puts "ā Invalid demo number. Use 'list' to see available demos."
|
249
|
+
exit 1
|
250
|
+
end
|
251
|
+
|
252
|
+
else
|
253
|
+
puts "Usage:"
|
254
|
+
puts " #{$0} # Interactive mode"
|
255
|
+
puts " #{$0} all # Run all demos"
|
256
|
+
puts " #{$0} list # List available demos"
|
257
|
+
puts " #{$0} N # Run demo number N"
|
258
|
+
exit 1
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Basic File Transport Demo
|
6
|
+
#
|
7
|
+
# This example demonstrates the core functionality of SmartMessage's FileTransport.
|
8
|
+
# It shows how to publish messages to files and read them back.
|
9
|
+
|
10
|
+
require_relative '../../lib/smart_message'
|
11
|
+
require 'tempfile'
|
12
|
+
require 'fileutils'
|
13
|
+
|
14
|
+
# Define message classes that will be saved in the messages directory
|
15
|
+
Dir.mkdir('messages') unless Dir.exist?('messages')
|
16
|
+
|
17
|
+
class LogMessage < SmartMessage::Base
|
18
|
+
property :level, required: true, valid: %w[DEBUG INFO WARN ERROR FATAL]
|
19
|
+
property :message, required: true
|
20
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
21
|
+
property :component, default: 'system'
|
22
|
+
|
23
|
+
from 'file_transport_demo'
|
24
|
+
|
25
|
+
# Transport will be set dynamically in examples
|
26
|
+
end
|
27
|
+
|
28
|
+
class UserAction < SmartMessage::Base
|
29
|
+
property :user_id, required: true
|
30
|
+
property :action, required: true
|
31
|
+
property :details, default: {}
|
32
|
+
property :timestamp, default: -> { Time.now.iso8601 }
|
33
|
+
|
34
|
+
from 'file_transport_demo'
|
35
|
+
|
36
|
+
# Transport will be set dynamically in examples
|
37
|
+
end
|
38
|
+
|
39
|
+
puts "=== SmartMessage FileTransport Basic Demo ==="
|
40
|
+
puts
|
41
|
+
|
42
|
+
# Create a temporary directory for our demo
|
43
|
+
demo_dir = Dir.mktmpdir('file_transport_demo')
|
44
|
+
puts "Demo directory: #{demo_dir}"
|
45
|
+
|
46
|
+
begin
|
47
|
+
# Example 1: Basic file writing
|
48
|
+
puts "\n1. Basic File Writing"
|
49
|
+
puts "=" * 30
|
50
|
+
|
51
|
+
log_file = File.join(demo_dir, 'application.log')
|
52
|
+
|
53
|
+
# Configure a simple file transport
|
54
|
+
file_transport = SmartMessage::Transport::FileTransport.new(
|
55
|
+
file_path: log_file,
|
56
|
+
format: :json
|
57
|
+
)
|
58
|
+
|
59
|
+
# Configure LogMessage to use the file transport
|
60
|
+
LogMessage.class_eval do
|
61
|
+
transport file_transport
|
62
|
+
end
|
63
|
+
|
64
|
+
# Publish some log messages
|
65
|
+
LogMessage.new(level: 'INFO', message: 'Application started', component: 'main').publish
|
66
|
+
LogMessage.new(level: 'DEBUG', message: 'Loading configuration', component: 'config').publish
|
67
|
+
LogMessage.new(level: 'WARN', message: 'Deprecated feature used', component: 'legacy').publish
|
68
|
+
LogMessage.new(level: 'ERROR', message: 'Database connection failed', component: 'db').publish
|
69
|
+
|
70
|
+
puts "ā Messages written to: #{log_file}"
|
71
|
+
puts "File contents:"
|
72
|
+
puts File.read(log_file)
|
73
|
+
|
74
|
+
# Example 2: Different output formats
|
75
|
+
puts "\n2. Different Output Formats"
|
76
|
+
puts "=" * 30
|
77
|
+
|
78
|
+
formats = [:json, :yaml, :raw]
|
79
|
+
|
80
|
+
formats.each do |format|
|
81
|
+
format_file = File.join(demo_dir, "messages_#{format}.log")
|
82
|
+
|
83
|
+
format_transport = SmartMessage::Transport::FileTransport.new(
|
84
|
+
file_path: format_file,
|
85
|
+
format: format
|
86
|
+
)
|
87
|
+
|
88
|
+
# Create a temporary message class for this format
|
89
|
+
temp_message = Class.new(SmartMessage::Base) do
|
90
|
+
property :content, required: true
|
91
|
+
property :format_type, required: true
|
92
|
+
from 'file_transport_demo'
|
93
|
+
end
|
94
|
+
|
95
|
+
temp_message.class_eval do
|
96
|
+
transport format_transport
|
97
|
+
end
|
98
|
+
|
99
|
+
temp_message.new(
|
100
|
+
content: "This message is in #{format} format",
|
101
|
+
format_type: format.to_s
|
102
|
+
).publish
|
103
|
+
|
104
|
+
puts "\n#{format.upcase} format (#{format_file}):"
|
105
|
+
puts File.read(format_file)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Example 3: Append vs Overwrite modes
|
109
|
+
puts "\n3. Append vs Overwrite Modes"
|
110
|
+
puts "=" * 30
|
111
|
+
|
112
|
+
append_file = File.join(demo_dir, 'append_demo.log')
|
113
|
+
overwrite_file = File.join(demo_dir, 'overwrite_demo.log')
|
114
|
+
|
115
|
+
# Append mode (default)
|
116
|
+
append_transport = SmartMessage::Transport::FileTransport.new(
|
117
|
+
file_path: append_file,
|
118
|
+
write_mode: :append,
|
119
|
+
format: :raw
|
120
|
+
)
|
121
|
+
|
122
|
+
# Overwrite mode
|
123
|
+
overwrite_transport = SmartMessage::Transport::FileTransport.new(
|
124
|
+
file_path: overwrite_file,
|
125
|
+
write_mode: :overwrite,
|
126
|
+
format: :raw
|
127
|
+
)
|
128
|
+
|
129
|
+
# Create messages for demonstration
|
130
|
+
3.times do |i|
|
131
|
+
# Append mode - messages accumulate
|
132
|
+
temp_append = Class.new(SmartMessage::Base) do
|
133
|
+
property :content, required: true
|
134
|
+
from 'file_transport_demo'
|
135
|
+
end
|
136
|
+
temp_append.class_eval do
|
137
|
+
transport append_transport
|
138
|
+
end
|
139
|
+
temp_append.new(content: "Append message #{i + 1}").publish
|
140
|
+
|
141
|
+
# Overwrite mode - only the last message remains
|
142
|
+
temp_overwrite = Class.new(SmartMessage::Base) do
|
143
|
+
property :content, required: true
|
144
|
+
from 'file_transport_demo'
|
145
|
+
end
|
146
|
+
temp_overwrite.class_eval do
|
147
|
+
transport overwrite_transport
|
148
|
+
end
|
149
|
+
temp_overwrite.new(content: "Overwrite message #{i + 1}").publish
|
150
|
+
end
|
151
|
+
|
152
|
+
puts "\nAppend mode result (#{append_file}):"
|
153
|
+
puts File.read(append_file)
|
154
|
+
|
155
|
+
puts "\nOverwrite mode result (#{overwrite_file}):"
|
156
|
+
puts File.read(overwrite_file)
|
157
|
+
|
158
|
+
# Example 4: Custom serialization
|
159
|
+
puts "\n4. Custom Serialization"
|
160
|
+
puts "=" * 30
|
161
|
+
|
162
|
+
csv_file = File.join(demo_dir, 'user_actions.csv')
|
163
|
+
|
164
|
+
# Create a CSV-style transport with custom serializer
|
165
|
+
csv_transport = SmartMessage::Transport::FileTransport.new(
|
166
|
+
file_path: csv_file,
|
167
|
+
format: :custom,
|
168
|
+
serializer: ->(message) {
|
169
|
+
# Custom CSV serialization
|
170
|
+
"#{message.timestamp},#{message.user_id},#{message.action},\"#{message.details}\"\n"
|
171
|
+
}
|
172
|
+
)
|
173
|
+
|
174
|
+
UserAction.class_eval do
|
175
|
+
transport csv_transport
|
176
|
+
end
|
177
|
+
|
178
|
+
# Write CSV header manually
|
179
|
+
File.write(csv_file, "timestamp,user_id,action,details\n")
|
180
|
+
|
181
|
+
# Publish user action messages
|
182
|
+
UserAction.new(user_id: '12345', action: 'login', details: {ip: '192.168.1.1'}).publish
|
183
|
+
UserAction.new(user_id: '12345', action: 'view_profile', details: {page: 'settings'}).publish
|
184
|
+
UserAction.new(user_id: '67890', action: 'purchase', details: {item_id: 'ABC123', amount: 29.99}).publish
|
185
|
+
UserAction.new(user_id: '12345', action: 'logout', details: {}).publish
|
186
|
+
|
187
|
+
puts "CSV file contents (#{csv_file}):"
|
188
|
+
puts File.read(csv_file)
|
189
|
+
|
190
|
+
# Example 5: File rotation
|
191
|
+
puts "\n5. File Rotation"
|
192
|
+
puts "=" * 30
|
193
|
+
|
194
|
+
# Note: This demonstrates the concept - actual rotation would require external tools
|
195
|
+
base_file = File.join(demo_dir, 'rotated.log')
|
196
|
+
|
197
|
+
rotation_transport = SmartMessage::Transport::FileTransport.new(
|
198
|
+
file_path: base_file,
|
199
|
+
format: :json
|
200
|
+
)
|
201
|
+
|
202
|
+
temp_rotated = Class.new(SmartMessage::Base) do
|
203
|
+
property :sequence, required: true
|
204
|
+
property :data, required: true
|
205
|
+
from 'file_transport_demo'
|
206
|
+
end
|
207
|
+
temp_rotated.class_eval do
|
208
|
+
transport rotation_transport
|
209
|
+
end
|
210
|
+
|
211
|
+
# Simulate rotation by publishing messages and manually rotating
|
212
|
+
5.times do |i|
|
213
|
+
temp_rotated.new(sequence: i + 1, data: "Message #{i + 1}").publish
|
214
|
+
|
215
|
+
# Simulate rotation after every 2 messages
|
216
|
+
if (i + 1) % 2 == 0
|
217
|
+
rotated_file = "#{base_file}.#{(i + 1) / 2}"
|
218
|
+
FileUtils.mv(base_file, rotated_file) if File.exist?(base_file)
|
219
|
+
puts "ā Rotated to: #{rotated_file}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Show rotated files
|
224
|
+
Dir.glob("#{base_file}*").sort.each do |file|
|
225
|
+
puts "\n#{file}:"
|
226
|
+
puts File.read(file) if File.exist?(file) && File.size(file) > 0
|
227
|
+
end
|
228
|
+
|
229
|
+
rescue => e
|
230
|
+
puts "Error: #{e.message}"
|
231
|
+
puts e.backtrace.first(3)
|
232
|
+
ensure
|
233
|
+
# Cleanup
|
234
|
+
FileUtils.rm_rf(demo_dir) if Dir.exist?(demo_dir)
|
235
|
+
FileUtils.rm_rf('messages') if Dir.exist?('messages')
|
236
|
+
puts "\nā Demo completed and cleaned up"
|
237
|
+
end
|