bunny_farm 0.1.2

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 (106) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.github/workflows/docs.yml +38 -0
  4. data/.gitignore +11 -0
  5. data/.travis.yml +3 -0
  6. data/CHANGELOG.md +61 -0
  7. data/COMMITS.md +196 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +330 -0
  11. data/Rakefile +9 -0
  12. data/bunny_farm.gemspec +30 -0
  13. data/config/bunny.yml.erb +29 -0
  14. data/config/bunny_test.yml.erb +29 -0
  15. data/config/hipchat.yml.erb +12 -0
  16. data/docs/api/configuration.md +9 -0
  17. data/docs/api/consumer.md +8 -0
  18. data/docs/api/message-class.md +419 -0
  19. data/docs/api/publisher.md +9 -0
  20. data/docs/architecture/integration.md +8 -0
  21. data/docs/architecture/message-flow.md +11 -0
  22. data/docs/architecture/overview.md +448 -0
  23. data/docs/architecture/scaling.md +8 -0
  24. data/docs/assets/actions_dsl_flow.svg +109 -0
  25. data/docs/assets/architecture_overview.svg +152 -0
  26. data/docs/assets/best_practices_patterns.svg +203 -0
  27. data/docs/assets/bunny_farm_logo.png +0 -0
  28. data/docs/assets/configuration_api_methods.svg +104 -0
  29. data/docs/assets/configuration_flow.svg +130 -0
  30. data/docs/assets/configuration_hierarchy.svg +70 -0
  31. data/docs/assets/data_processing_pipeline.svg +131 -0
  32. data/docs/assets/debugging_monitoring.svg +165 -0
  33. data/docs/assets/ecommerce_example_flow.svg +145 -0
  34. data/docs/assets/email_campaign_example.svg +127 -0
  35. data/docs/assets/environment_variables_map.svg +78 -0
  36. data/docs/assets/error_handling_flow.svg +114 -0
  37. data/docs/assets/favicon.ico +1 -0
  38. data/docs/assets/fields_dsl_structure.svg +89 -0
  39. data/docs/assets/instance_methods_lifecycle.svg +137 -0
  40. data/docs/assets/integration_patterns.svg +207 -0
  41. data/docs/assets/json_serialization_flow.svg +153 -0
  42. data/docs/assets/logo.svg +4 -0
  43. data/docs/assets/message_api_overview.svg +126 -0
  44. data/docs/assets/message_encapsulation.svg +113 -0
  45. data/docs/assets/message_lifecycle.svg +110 -0
  46. data/docs/assets/message_structure.svg +138 -0
  47. data/docs/assets/publisher_consumer_api.svg +120 -0
  48. data/docs/assets/scaling_deployment_patterns.svg +195 -0
  49. data/docs/assets/smart_routing_diagram.svg +131 -0
  50. data/docs/assets/system_architecture_overview.svg +155 -0
  51. data/docs/assets/task_scheduling_flow.svg +139 -0
  52. data/docs/assets/testing_strategies.svg +146 -0
  53. data/docs/assets/workflow_patterns.svg +183 -0
  54. data/docs/assets/yaml_config_structure.svg +72 -0
  55. data/docs/configuration/environment-variables.md +14 -0
  56. data/docs/configuration/overview.md +373 -0
  57. data/docs/configuration/programmatic-setup.md +10 -0
  58. data/docs/configuration/yaml-configuration.md +12 -0
  59. data/docs/core-features/configuration.md +528 -0
  60. data/docs/core-features/error-handling.md +82 -0
  61. data/docs/core-features/json-serialization.md +545 -0
  62. data/docs/core-features/message-design.md +406 -0
  63. data/docs/core-features/smart-routing.md +467 -0
  64. data/docs/core-features/task-scheduling.md +67 -0
  65. data/docs/core-features/workflow-support.md +112 -0
  66. data/docs/development/contributing.md +345 -0
  67. data/docs/development/roadmap.md +9 -0
  68. data/docs/development/testing.md +14 -0
  69. data/docs/examples/order-processing.md +10 -0
  70. data/docs/examples/overview.md +269 -0
  71. data/docs/examples/real-world.md +8 -0
  72. data/docs/examples/simple-producer-consumer.md +15 -0
  73. data/docs/examples/task-scheduler.md +9 -0
  74. data/docs/getting-started/basic-concepts.md +274 -0
  75. data/docs/getting-started/installation.md +122 -0
  76. data/docs/getting-started/quick-start.md +158 -0
  77. data/docs/index.md +106 -0
  78. data/docs/message-structure/actions-dsl.md +163 -0
  79. data/docs/message-structure/fields-dsl.md +146 -0
  80. data/docs/message-structure/instance-methods.md +115 -0
  81. data/docs/message-structure/overview.md +211 -0
  82. data/examples/README.md +212 -0
  83. data/examples/consumer.rb +41 -0
  84. data/examples/images/message_flow.svg +87 -0
  85. data/examples/images/order_workflow.svg +122 -0
  86. data/examples/images/producer_consumer.svg +96 -0
  87. data/examples/images/task_scheduler.svg +140 -0
  88. data/examples/order_processor.rb +238 -0
  89. data/examples/producer.rb +60 -0
  90. data/examples/simple_message.rb +43 -0
  91. data/examples/task_scheduler.rb +263 -0
  92. data/images/architecture_overview.svg +152 -0
  93. data/images/bunny_farm_logo.png +0 -0
  94. data/images/configuration_flow.svg +130 -0
  95. data/images/message_structure.svg +138 -0
  96. data/lib/bunny_farm/.irbrc +7 -0
  97. data/lib/bunny_farm/generic_consumer.rb +12 -0
  98. data/lib/bunny_farm/hash_ext.rb +37 -0
  99. data/lib/bunny_farm/init_bunny.rb +137 -0
  100. data/lib/bunny_farm/init_hipchat.rb +49 -0
  101. data/lib/bunny_farm/message.rb +218 -0
  102. data/lib/bunny_farm/message_elements.rb +25 -0
  103. data/lib/bunny_farm/version.rb +3 -0
  104. data/lib/bunny_farm.rb +9 -0
  105. data/mkdocs.yml +148 -0
  106. metadata +244 -0
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env ruby
2
+ # Task scheduler example - demonstrates scheduled/delayed message processing
3
+
4
+ require 'bundler/setup'
5
+ require 'bunny_farm'
6
+ require 'time'
7
+
8
+ # Message class for scheduled tasks
9
+ class ScheduledTask < BunnyFarm::Message
10
+ fields :task_id, :task_type, :scheduled_for, :payload, :retry_count
11
+ actions :execute, :retry, :report_failure
12
+
13
+ def execute(*args)
14
+ scheduled_time = Time.parse(@items[:scheduled_for])
15
+ current_time = Time.now
16
+
17
+ puts "\n⏰ Executing scheduled task ##{@items[:task_id]}"
18
+ puts " Type: #{@items[:task_type]}"
19
+ puts " Scheduled for: #{scheduled_time}"
20
+ puts " Current time: #{current_time}"
21
+
22
+ # Check if we should execute now
23
+ if current_time < scheduled_time
24
+ delay = (scheduled_time - current_time).to_i
25
+ puts " ⏳ Too early! Delaying for #{delay} seconds..."
26
+
27
+ # In a real system, you might requeue with a delay
28
+ # For demo, we'll just sleep
29
+ sleep [delay, 5].min # Cap at 5 seconds for demo
30
+ end
31
+
32
+ # Execute the task based on type
33
+ case @items[:task_type]
34
+ when 'email_reminder'
35
+ send_email_reminder
36
+ when 'data_backup'
37
+ perform_backup
38
+ when 'report_generation'
39
+ generate_report
40
+ when 'cleanup'
41
+ perform_cleanup
42
+ else
43
+ failure("Unknown task type: #{@items[:task_type]}")
44
+ return
45
+ end
46
+
47
+ success!
48
+ rescue => e
49
+ puts " ❌ Task failed: #{e.message}"
50
+
51
+ # Increment retry count
52
+ @items[:retry_count] = (@items[:retry_count] || 0) + 1
53
+
54
+ if @items[:retry_count] < 3
55
+ publish('retry')
56
+ else
57
+ publish('report_failure')
58
+ end
59
+
60
+ failure(e.message)
61
+ end
62
+
63
+ def retry(*args)
64
+ puts "\n🔄 Retrying task ##{@items[:task_id]} (attempt #{@items[:retry_count]})"
65
+
66
+ # Add exponential backoff
67
+ sleep_time = 2 ** @items[:retry_count]
68
+ puts " Waiting #{sleep_time} seconds before retry..."
69
+ sleep sleep_time
70
+
71
+ # Re-execute
72
+ publish('execute')
73
+ success!
74
+ end
75
+
76
+ def report_failure(*args)
77
+ puts "\n🚨 Task ##{@items[:task_id]} failed after #{@items[:retry_count]} attempts!"
78
+ puts " Sending failure notification..."
79
+
80
+ # In a real system, this might send alerts to administrators
81
+ # Log to error tracking service, send emails, etc.
82
+
83
+ success! # We successfully handled the failure
84
+ end
85
+
86
+ private
87
+
88
+ def send_email_reminder
89
+ puts " 📧 Sending email reminder..."
90
+ recipient = @items[:payload]['recipient'] || 'user@example.com'
91
+ subject = @items[:payload]['subject'] || 'Reminder'
92
+ puts " To: #{recipient}"
93
+ puts " Subject: #{subject}"
94
+
95
+ # Simulate email sending
96
+ sleep 0.5
97
+
98
+ # Randomly fail sometimes for demo
99
+ raise "SMTP connection failed" if rand > 0.8
100
+
101
+ puts " ✅ Email sent successfully"
102
+ end
103
+
104
+ def perform_backup
105
+ puts " 💾 Performing data backup..."
106
+ database = @items[:payload]['database'] || 'main_db'
107
+ puts " Database: #{database}"
108
+
109
+ # Simulate backup
110
+ sleep 1
111
+
112
+ backup_file = "/backups/#{database}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.sql"
113
+ puts " ✅ Backup completed: #{backup_file}"
114
+ end
115
+
116
+ def generate_report
117
+ puts " 📊 Generating report..."
118
+ report_type = @items[:payload]['type'] || 'daily_sales'
119
+ puts " Type: #{report_type}"
120
+
121
+ # Simulate report generation
122
+ sleep 0.8
123
+
124
+ puts " ✅ Report generated and sent to stakeholders"
125
+ end
126
+
127
+ def perform_cleanup
128
+ puts " 🧹 Performing cleanup tasks..."
129
+ target = @items[:payload]['target'] || 'temp_files'
130
+ puts " Target: #{target}"
131
+
132
+ # Simulate cleanup
133
+ sleep 0.3
134
+
135
+ puts " ✅ Cleaned up #{rand(10..50)} old #{target}"
136
+ end
137
+ end
138
+
139
+ # Main execution
140
+ if __FILE__ == $0
141
+ require 'optparse'
142
+
143
+ mode = nil
144
+ OptionParser.new do |opts|
145
+ opts.banner = "Usage: #{$0} [options]"
146
+ opts.on("-s", "--scheduler", "Run as task scheduler (producer)") { mode = :scheduler }
147
+ opts.on("-w", "--worker", "Run as task worker (consumer)") { mode = :worker }
148
+ opts.on("-h", "--help", "Show this help") do
149
+ puts opts
150
+ exit
151
+ end
152
+ end.parse!
153
+
154
+ if mode.nil?
155
+ puts "Please specify --scheduler or --worker mode"
156
+ exit 1
157
+ end
158
+
159
+ # Configure BunnyFarm
160
+ BunnyFarm.config do
161
+ env 'development'
162
+ app_id mode == :scheduler ? 'task_scheduler' : 'task_worker'
163
+
164
+ if mode == :worker
165
+ # Configure to receive all ScheduledTask actions
166
+ bunny Hashie::Mash.new(
167
+ YAML.load(
168
+ ERB.new(
169
+ File.read(
170
+ File.join(BunnyFarm::CONFIG.config_dir, BunnyFarm::CONFIG.bunny_file)
171
+ )
172
+ ).result, aliases: true
173
+ )[BunnyFarm::CONFIG.env].merge(
174
+ 'routing_key' => 'ScheduledTask.*'
175
+ )
176
+ )
177
+ end
178
+ end
179
+
180
+ if mode == :scheduler
181
+ puts "Task Scheduler"
182
+ puts "=" * 40
183
+ puts "Scheduling tasks for execution..."
184
+
185
+ # Create various scheduled tasks
186
+ tasks = [
187
+ {
188
+ task_id: "TASK-#{rand(1000..9999)}",
189
+ task_type: 'email_reminder',
190
+ scheduled_for: (Time.now + 2).to_s, # 2 seconds from now
191
+ payload: {
192
+ 'recipient' => 'alice@example.com',
193
+ 'subject' => 'Meeting in 15 minutes'
194
+ },
195
+ retry_count: 0
196
+ },
197
+ {
198
+ task_id: "TASK-#{rand(1000..9999)}",
199
+ task_type: 'data_backup',
200
+ scheduled_for: Time.now.to_s, # Execute immediately
201
+ payload: {
202
+ 'database' => 'users_db'
203
+ },
204
+ retry_count: 0
205
+ },
206
+ {
207
+ task_id: "TASK-#{rand(1000..9999)}",
208
+ task_type: 'report_generation',
209
+ scheduled_for: (Time.now + 5).to_s, # 5 seconds from now
210
+ payload: {
211
+ 'type' => 'weekly_analytics'
212
+ },
213
+ retry_count: 0
214
+ },
215
+ {
216
+ task_id: "TASK-#{rand(1000..9999)}",
217
+ task_type: 'cleanup',
218
+ scheduled_for: (Time.now + 3).to_s, # 3 seconds from now
219
+ payload: {
220
+ 'target' => 'log_files'
221
+ },
222
+ retry_count: 0
223
+ }
224
+ ]
225
+
226
+ tasks.each do |task_data|
227
+ msg = ScheduledTask.new
228
+
229
+ task_data.each do |key, value|
230
+ msg[key] = value
231
+ end
232
+
233
+ if msg.publish('execute')
234
+ puts "✅ Scheduled task #{task_data[:task_id]} (#{task_data[:task_type]})"
235
+ puts " Scheduled for: #{task_data[:scheduled_for]}"
236
+ else
237
+ puts "❌ Failed to schedule task: #{msg.errors.join(', ')}"
238
+ end
239
+
240
+ sleep 0.5
241
+ end
242
+
243
+ puts "\n📅 All tasks scheduled!"
244
+ puts "Run with --worker in another terminal to process them."
245
+
246
+ else # worker mode
247
+ puts "Task Worker"
248
+ puts "=" * 40
249
+ puts "Processing scheduled tasks..."
250
+ puts "Press Ctrl+C to exit"
251
+
252
+ begin
253
+ BunnyFarm.manage(false)
254
+ rescue Interrupt
255
+ puts "\n\nShutting down task worker..."
256
+ end
257
+ end
258
+
259
+ # Clean up
260
+ if BunnyFarm::CONFIG.connection && BunnyFarm::CONFIG.connection.open?
261
+ BunnyFarm::CONFIG.connection.close
262
+ end
263
+ end
@@ -0,0 +1,152 @@
1
+ <svg width="900" height="600" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Background transparent -->
3
+ <rect width="900" height="600" fill="transparent"/>
4
+
5
+ <!-- Title -->
6
+ <text x="450" y="35" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" fill="#e0e0e0">
7
+ BunnyFarm Architecture Overview
8
+ </text>
9
+
10
+ <!-- Ruby Application Layer -->
11
+ <g>
12
+ <rect x="50" y="80" width="800" height="120" rx="15" fill="#2d3748" stroke="#68d391" stroke-width="3"/>
13
+ <text x="450" y="110" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#68d391">
14
+ Ruby Application Layer
15
+ </text>
16
+
17
+ <!-- Producer Apps -->
18
+ <rect x="80" y="130" width="140" height="50" rx="8" fill="#1a202c" stroke="#68d391" stroke-width="1"/>
19
+ <text x="150" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">Web App</text>
20
+ <text x="150" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Form Submissions</text>
21
+
22
+ <rect x="240" y="130" width="140" height="50" rx="8" fill="#1a202c" stroke="#68d391" stroke-width="1"/>
23
+ <text x="310" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">API Server</text>
24
+ <text x="310" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">REST Endpoints</text>
25
+
26
+ <rect x="400" y="130" width="140" height="50" rx="8" fill="#1a202c" stroke="#68d391" stroke-width="1"/>
27
+ <text x="470" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">Scheduler</text>
28
+ <text x="470" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Cron Jobs</text>
29
+
30
+ <!-- Consumer Apps -->
31
+ <rect x="560" y="130" width="140" height="50" rx="8" fill="#1a202c" stroke="#ed8936" stroke-width="1"/>
32
+ <text x="630" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#ed8936">Worker 1</text>
33
+ <text x="630" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Background Jobs</text>
34
+
35
+ <rect x="720" y="130" width="140" height="50" rx="8" fill="#1a202c" stroke="#ed8936" stroke-width="1"/>
36
+ <text x="790" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#ed8936">Worker 2</text>
37
+ <text x="790" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Microservice</text>
38
+ </g>
39
+
40
+ <!-- BunnyFarm Library Layer -->
41
+ <g>
42
+ <rect x="50" y="240" width="800" height="100" rx="15" fill="#2d3748" stroke="#9f7aea" stroke-width="3"/>
43
+ <text x="450" y="270" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#9f7aea">
44
+ BunnyFarm Library
45
+ </text>
46
+
47
+ <!-- Core Components -->
48
+ <rect x="80" y="285" width="120" height="40" rx="5" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
49
+ <text x="140" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1a202c">Message</text>
50
+ <text x="140" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#1a202c">Base Class</text>
51
+
52
+ <rect x="220" y="285" width="120" height="40" rx="5" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
53
+ <text x="280" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1a202c">Publisher</text>
54
+ <text x="280" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#1a202c">Send Messages</text>
55
+
56
+ <rect x="360" y="285" width="120" height="40" rx="5" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
57
+ <text x="420" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1a202c">Consumer</text>
58
+ <text x="420" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#1a202c">Receive & Process</text>
59
+
60
+ <rect x="500" y="285" width="120" height="40" rx="5" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
61
+ <text x="560" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1a202c">Config</text>
62
+ <text x="560" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#1a202c">Settings</text>
63
+
64
+ <rect x="640" y="285" width="120" height="40" rx="5" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
65
+ <text x="700" y="300" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1a202c">Router</text>
66
+ <text x="700" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#1a202c">Routing Keys</text>
67
+ </g>
68
+
69
+ <!-- RabbitMQ Layer -->
70
+ <g>
71
+ <rect x="50" y="380" width="800" height="120" rx="15" fill="#1a365d" stroke="#2b6cb0" stroke-width="3"/>
72
+ <text x="450" y="410" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#90cdf4">
73
+ RabbitMQ Message Broker
74
+ </text>
75
+
76
+ <!-- Exchange -->
77
+ <rect x="120" y="430" width="140" height="50" rx="8" fill="#2b6cb0" stroke="#90cdf4" stroke-width="1"/>
78
+ <text x="190" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e6fffa">Exchange</text>
79
+ <text x="190" y="465" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#bee3f8">Topic Router</text>
80
+
81
+ <!-- Queues -->
82
+ <rect x="300" y="430" width="100" height="50" rx="8" fill="#2b6cb0" stroke="#90cdf4" stroke-width="1"/>
83
+ <text x="350" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e6fffa">Queue 1</text>
84
+ <text x="350" y="465" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#bee3f8">Orders</text>
85
+
86
+ <rect x="420" y="430" width="100" height="50" rx="8" fill="#2b6cb0" stroke="#90cdf4" stroke-width="1"/>
87
+ <text x="470" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e6fffa">Queue 2</text>
88
+ <text x="470" y="465" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#bee3f8">Tasks</text>
89
+
90
+ <rect x="540" y="430" width="100" height="50" rx="8" fill="#2b6cb0" stroke="#90cdf4" stroke-width="1"/>
91
+ <text x="590" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e6fffa">Queue 3</text>
92
+ <text x="590" y="465" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#bee3f8">Emails</text>
93
+
94
+ <!-- Management -->
95
+ <rect x="680" y="430" width="100" height="50" rx="8" fill="#2b6cb0" stroke="#90cdf4" stroke-width="1"/>
96
+ <text x="730" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e6fffa">Management</text>
97
+ <text x="730" y="465" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#bee3f8">Web UI</text>
98
+ </g>
99
+
100
+ <!-- Storage Layer -->
101
+ <g>
102
+ <rect x="50" y="540" width="800" height="50" rx="15" fill="#2d3748" stroke="#4a5568" stroke-width="2"/>
103
+ <text x="450" y="560" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#cbd5e0">
104
+ Persistence & External Services
105
+ </text>
106
+
107
+ <rect x="100" y="555" width="120" height="30" rx="5" fill="#4a5568"/>
108
+ <text x="160" y="573" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Database</text>
109
+
110
+ <rect x="240" y="555" width="120" height="30" rx="5" fill="#4a5568"/>
111
+ <text x="300" y="573" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Email Service</text>
112
+
113
+ <rect x="380" y="555" width="120" height="30" rx="5" fill="#4a5568"/>
114
+ <text x="440" y="573" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">File Storage</text>
115
+
116
+ <rect x="520" y="555" width="120" height="30" rx="5" fill="#4a5568"/>
117
+ <text x="580" y="573" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">APIs</text>
118
+
119
+ <rect x="660" y="555" width="120" height="30" rx="5" fill="#4a5568"/>
120
+ <text x="720" y="573" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Cache/Redis</text>
121
+ </g>
122
+
123
+ <!-- Flow Arrows -->
124
+ <defs>
125
+ <marker id="arrow-down" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
126
+ <polygon points="0 0, 10 3.5, 0 7" fill="#68d391"/>
127
+ </marker>
128
+ <marker id="arrow-up" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
129
+ <polygon points="0 0, 10 3.5, 0 7" fill="#ed8936"/>
130
+ </marker>
131
+ </defs>
132
+
133
+ <!-- Publishers to BunnyFarm -->
134
+ <line x1="310" y1="200" x2="310" y2="240" stroke="#68d391" stroke-width="2" marker-end="url(#arrow-down)"/>
135
+ <text x="320" y="220" font-family="Arial, sans-serif" font-size="10" fill="#68d391">publish</text>
136
+
137
+ <!-- BunnyFarm to RabbitMQ -->
138
+ <line x1="450" y1="340" x2="450" y2="380" stroke="#9f7aea" stroke-width="2" marker-end="url(#arrow-down)"/>
139
+ <text x="460" y="360" font-family="Arial, sans-serif" font-size="10" fill="#9f7aea">AMQP</text>
140
+
141
+ <!-- RabbitMQ to BunnyFarm (consumers) -->
142
+ <line x1="650" y1="380" x2="650" y2="340" stroke="#ed8936" stroke-width="2" marker-end="url(#arrow-up)"/>
143
+ <text x="660" y="360" font-family="Arial, sans-serif" font-size="10" fill="#ed8936">consume</text>
144
+
145
+ <!-- BunnyFarm to Consumers -->
146
+ <line x1="650" y1="240" x2="650" y2="200" stroke="#ed8936" stroke-width="2" marker-end="url(#arrow-up)"/>
147
+ <text x="660" y="220" font-family="Arial, sans-serif" font-size="10" fill="#ed8936">execute</text>
148
+
149
+ <!-- Workers to Storage -->
150
+ <line x1="720" y1="500" x2="720" y2="540" stroke="#4a5568" stroke-width="2" marker-end="url(#arrow-down)"/>
151
+ <text x="730" y="520" font-family="Arial, sans-serif" font-size="10" fill="#9ca3af">store/fetch</text>
152
+ </svg>
Binary file
@@ -0,0 +1,130 @@
1
+ <svg width="800" height="500" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Background transparent -->
3
+ <rect width="800" height="500" fill="transparent"/>
4
+
5
+ <!-- Title -->
6
+ <text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#e0e0e0">
7
+ BunnyFarm Configuration Options
8
+ </text>
9
+
10
+ <!-- Environment Variables -->
11
+ <g>
12
+ <rect x="50" y="70" width="220" height="180" rx="10" fill="#2d3748" stroke="#68d391" stroke-width="2"/>
13
+ <text x="160" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#68d391">Environment Variables</text>
14
+
15
+ <rect x="70" y="110" width="180" height="130" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
16
+ <text x="75" y="125" font-family="monospace" font-size="10" fill="#68d391">AMQP_HOST</text>
17
+ <text x="140" y="125" font-family="monospace" font-size="10" fill="#e0e0e0">=localhost</text>
18
+
19
+ <text x="75" y="140" font-family="monospace" font-size="10" fill="#68d391">AMQP_VHOST</text>
20
+ <text x="140" y="140" font-family="monospace" font-size="10" fill="#e0e0e0">=/</text>
21
+
22
+ <text x="75" y="155" font-family="monospace" font-size="10" fill="#68d391">AMQP_PORT</text>
23
+ <text x="140" y="155" font-family="monospace" font-size="10" fill="#e0e0e0">=5672</text>
24
+
25
+ <text x="75" y="170" font-family="monospace" font-size="10" fill="#68d391">AMQP_USER</text>
26
+ <text x="140" y="170" font-family="monospace" font-size="10" fill="#e0e0e0">=guest</text>
27
+
28
+ <text x="75" y="185" font-family="monospace" font-size="10" fill="#68d391">AMQP_PASS</text>
29
+ <text x="140" y="185" font-family="monospace" font-size="10" fill="#e0e0e0">=guest</text>
30
+
31
+ <text x="75" y="200" font-family="monospace" font-size="10" fill="#68d391">AMQP_EXCHANGE</text>
32
+ <text x="155" y="200" font-family="monospace" font-size="10" fill="#e0e0e0">=my_exchange</text>
33
+
34
+ <text x="75" y="215" font-family="monospace" font-size="10" fill="#68d391">AMQP_QUEUE</text>
35
+ <text x="135" y="215" font-family="monospace" font-size="10" fill="#e0e0e0">=my_queue</text>
36
+
37
+ <text x="75" y="230" font-family="monospace" font-size="10" fill="#68d391">AMQP_ROUTING_KEY</text>
38
+ <text x="175" y="230" font-family="monospace" font-size="10" fill="#e0e0e0">=#</text>
39
+ </g>
40
+
41
+ <!-- YAML Configuration -->
42
+ <g>
43
+ <rect x="300" y="70" width="220" height="180" rx="10" fill="#2d3748" stroke="#4299e1" stroke-width="2"/>
44
+ <text x="410" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#4299e1">YAML Configuration</text>
45
+ <text x="410" y="110" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">config/bunny.yml.erb</text>
46
+
47
+ <rect x="320" y="120" width="180" height="120" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
48
+ <text x="325" y="135" font-family="monospace" font-size="10" fill="#4299e1">defaults: &defaults</text>
49
+ <text x="330" y="150" font-family="monospace" font-size="10" fill="#68d391">host:</text>
50
+ <text x="360" y="150" font-family="monospace" font-size="10" fill="#f6e05e">&lt;%= ENV['AMQP_HOST'] %&gt;</text>
51
+ <text x="330" y="165" font-family="monospace" font-size="10" fill="#68d391">port:</text>
52
+ <text x="360" y="165" font-family="monospace" font-size="10" fill="#f6e05e">&lt;%= ENV['AMQP_PORT'] %&gt;</text>
53
+ <text x="325" y="180" font-family="monospace" font-size="10" fill="#4299e1">development:</text>
54
+ <text x="330" y="195" font-family="monospace" font-size="10" fill="#e0e0e0">&lt;&lt;: *defaults</text>
55
+ <text x="325" y="210" font-family="monospace" font-size="10" fill="#4299e1">production:</text>
56
+ <text x="330" y="225" font-family="monospace" font-size="10" fill="#e0e0e0">&lt;&lt;: *defaults</text>
57
+ </g>
58
+
59
+ <!-- Programmatic Configuration -->
60
+ <g>
61
+ <rect x="550" y="70" width="220" height="180" rx="10" fill="#2d3748" stroke="#9f7aea" stroke-width="2"/>
62
+ <text x="660" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#9f7aea">Ruby Configuration</text>
63
+ <text x="660" y="110" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">BunnyFarm.config block</text>
64
+
65
+ <rect x="570" y="120" width="180" height="120" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
66
+ <text x="575" y="135" font-family="monospace" font-size="10" fill="#9f7aea">BunnyFarm.config do</text>
67
+ <text x="580" y="150" font-family="monospace" font-size="10" fill="#68d391">env</text>
68
+ <text x="605" y="150" font-family="monospace" font-size="10" fill="#e0e0e0">'production'</text>
69
+ <text x="580" y="165" font-family="monospace" font-size="10" fill="#68d391">app_id</text>
70
+ <text x="620" y="165" font-family="monospace" font-size="10" fill="#e0e0e0">'my_worker'</text>
71
+ <text x="580" y="180" font-family="monospace" font-size="10" fill="#68d391">bunny_file</text>
72
+ <text x="645" y="180" font-family="monospace" font-size="10" fill="#e0e0e0">'custom.yml'</text>
73
+ <text x="580" y="195" font-family="monospace" font-size="10" fill="#9ca3af"># Custom settings</text>
74
+ <text x="575" y="230" font-family="monospace" font-size="10" fill="#9f7aea">end</text>
75
+ </g>
76
+
77
+ <!-- Configuration Flow -->
78
+ <g>
79
+ <rect x="50" y="280" width="700" height="120" rx="10" fill="#2d3748" stroke="#f6e05e" stroke-width="2"/>
80
+ <text x="400" y="305" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#f6e05e">Configuration Priority Flow</text>
81
+
82
+ <!-- Priority boxes -->
83
+ <rect x="80" y="325" width="120" height="60" rx="8" fill="#68d391" stroke="#68d391" stroke-width="1"/>
84
+ <text x="140" y="345" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1a202c">1. Defaults</text>
85
+ <text x="140" y="365" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">Built-in values</text>
86
+
87
+ <rect x="220" y="325" width="120" height="60" rx="8" fill="#4299e1" stroke="#4299e1" stroke-width="1"/>
88
+ <text x="280" y="345" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1a202c">2. YAML</text>
89
+ <text x="280" y="365" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">Config file</text>
90
+
91
+ <rect x="360" y="325" width="120" height="60" rx="8" fill="#68d391" stroke="#68d391" stroke-width="1"/>
92
+ <text x="420" y="345" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1a202c">3. ENV Vars</text>
93
+ <text x="420" y="365" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">Environment</text>
94
+
95
+ <rect x="500" y="325" width="120" height="60" rx="8" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
96
+ <text x="560" y="345" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1a202c">4. Ruby Code</text>
97
+ <text x="560" y="365" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">Programmatic</text>
98
+
99
+ <rect x="640" y="325" width="120" height="60" rx="8" fill="#e53e3e" stroke="#e53e3e" stroke-width="1"/>
100
+ <text x="700" y="345" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1a202c">Final Config</text>
101
+ <text x="700" y="365" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">Used by app</text>
102
+
103
+ <!-- Arrows -->
104
+ <defs>
105
+ <marker id="arrow-priority" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
106
+ <polygon points="0 0, 10 3.5, 0 7" fill="#f6e05e"/>
107
+ </marker>
108
+ </defs>
109
+
110
+ <line x1="200" y1="355" x2="220" y2="355" stroke="#f6e05e" stroke-width="2" marker-end="url(#arrow-priority)"/>
111
+ <line x1="340" y1="355" x2="360" y2="355" stroke="#f6e05e" stroke-width="2" marker-end="url(#arrow-priority)"/>
112
+ <line x1="480" y1="355" x2="500" y2="355" stroke="#f6e05e" stroke-width="2" marker-end="url(#arrow-priority)"/>
113
+ <line x1="620" y1="355" x2="640" y2="355" stroke="#f6e05e" stroke-width="2" marker-end="url(#arrow-priority)"/>
114
+ </g>
115
+
116
+ <!-- Example Use Cases -->
117
+ <g>
118
+ <rect x="50" y="420" width="700" height="70" rx="10" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
119
+ <text x="400" y="440" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#f6e05e">Common Configuration Patterns</text>
120
+
121
+ <text x="70" y="460" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#68d391">Development:</text>
122
+ <text x="150" y="460" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Local RabbitMQ, default settings</text>
123
+
124
+ <text x="400" y="460" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#4299e1">Production:</text>
125
+ <text x="470" y="460" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Environment variables for security</text>
126
+
127
+ <text x="70" y="475" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#ed8936">Testing:</text>
128
+ <text x="125" y="475" font-family="Arial, sans-serif" font-size="11" fill="#e0e0e0">Custom config with test-specific settings</text>
129
+ </g>
130
+ </svg>