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,140 @@
1
+ <svg width="800" height="550" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Background transparent -->
3
+ <rect width="800" height="550" fill="transparent"/>
4
+
5
+ <!-- Title -->
6
+ <text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#e0e0e0">
7
+ Task Scheduler with Retry Logic
8
+ </text>
9
+
10
+ <!-- Scheduler (Producer) -->
11
+ <g>
12
+ <rect x="50" y="70" width="150" height="100" rx="10" fill="#2d3748" stroke="#9f7aea" stroke-width="2"/>
13
+ <text x="125" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#9f7aea">SCHEDULER</text>
14
+ <text x="125" y="115" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Creates tasks with</text>
15
+ <text x="125" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">scheduled times</text>
16
+ <text x="125" y="145" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">ā° schedule_for</text>
17
+ <text x="125" y="160" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">šŸ”„ retry_count: 0</text>
18
+ </g>
19
+
20
+ <!-- Worker (Consumer) -->
21
+ <g>
22
+ <rect x="600" y="70" width="150" height="100" rx="10" fill="#2d3748" stroke="#ed8936" stroke-width="2"/>
23
+ <text x="675" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#ed8936">WORKER</text>
24
+ <text x="675" y="115" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Executes scheduled</text>
25
+ <text x="675" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">tasks at right time</text>
26
+ <text x="675" y="145" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">⚔ Execute actions</text>
27
+ <text x="675" y="160" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">šŸ”„ Handle retries</text>
28
+ </g>
29
+
30
+ <!-- Task Types -->
31
+ <g>
32
+ <rect x="250" y="70" width="300" height="100" rx="10" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
33
+ <text x="400" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#68d391">Task Types</text>
34
+
35
+ <g>
36
+ <rect x="270" y="110" width="60" height="25" rx="3" fill="#4299e1" stroke="#4299e1" stroke-width="1"/>
37
+ <text x="300" y="125" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">šŸ“§ Email</text>
38
+
39
+ <rect x="340" y="110" width="60" height="25" rx="3" fill="#68d391" stroke="#68d391" stroke-width="1"/>
40
+ <text x="370" y="125" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">šŸ’¾ Backup</text>
41
+
42
+ <rect x="410" y="110" width="60" height="25" rx="3" fill="#ed8936" stroke="#ed8936" stroke-width="1"/>
43
+ <text x="440" y="125" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">šŸ“Š Report</text>
44
+
45
+ <rect x="480" y="110" width="60" height="25" rx="3" fill="#9f7aea" stroke="#9f7aea" stroke-width="1"/>
46
+ <text x="510" y="125" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1a202c">🧹 Cleanup</text>
47
+ </g>
48
+
49
+ <text x="400" y="155" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#9ca3af">Different task types with specific logic</text>
50
+ </g>
51
+
52
+ <!-- Execution Flow -->
53
+ <g>
54
+ <text x="400" y="210" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#f6e05e">Execution Flow</text>
55
+
56
+ <!-- Execute -->
57
+ <rect x="100" y="230" width="100" height="60" rx="8" fill="#2d3748" stroke="#68d391" stroke-width="2"/>
58
+ <text x="150" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">EXECUTE</text>
59
+ <text x="150" y="265" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Check timing</text>
60
+ <text x="150" y="280" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Run task logic</text>
61
+
62
+ <!-- Success -->
63
+ <rect x="250" y="230" width="100" height="60" rx="8" fill="#2d3748" stroke="#68d391" stroke-width="2"/>
64
+ <text x="300" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">āœ… SUCCESS</text>
65
+ <text x="300" y="265" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Task completed</text>
66
+ <text x="300" y="280" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Send notifications</text>
67
+
68
+ <!-- Retry -->
69
+ <rect x="450" y="230" width="100" height="60" rx="8" fill="#2d3748" stroke="#f6e05e" stroke-width="2"/>
70
+ <text x="500" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#f6e05e">šŸ”„ RETRY</text>
71
+ <text x="500" y="265" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Exponential</text>
72
+ <text x="500" y="280" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">backoff delay</text>
73
+
74
+ <!-- Failure -->
75
+ <rect x="600" y="230" width="100" height="60" rx="8" fill="#2d3748" stroke="#e53e3e" stroke-width="2"/>
76
+ <text x="650" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#e53e3e">āŒ FAILURE</text>
77
+ <text x="650" y="265" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Max retries</text>
78
+ <text x="650" y="280" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e0e0e0">Send alerts</text>
79
+ </g>
80
+
81
+ <!-- Flow Arrows -->
82
+ <defs>
83
+ <marker id="arrow-green-2" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
84
+ <polygon points="0 0, 10 3.5, 0 7" fill="#68d391"/>
85
+ </marker>
86
+ <marker id="arrow-yellow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
87
+ <polygon points="0 0, 10 3.5, 0 7" fill="#f6e05e"/>
88
+ </marker>
89
+ <marker id="arrow-red" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
90
+ <polygon points="0 0, 10 3.5, 0 7" fill="#e53e3e"/>
91
+ </marker>
92
+ </defs>
93
+
94
+ <!-- Execute to Success -->
95
+ <line x1="200" y1="250" x2="250" y2="250" stroke="#68d391" stroke-width="2" marker-end="url(#arrow-green-2)"/>
96
+ <text x="225" y="245" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#68d391">success</text>
97
+
98
+ <!-- Execute to Retry -->
99
+ <line x1="200" y1="270" x2="450" y2="270" stroke="#f6e05e" stroke-width="2" marker-end="url(#arrow-yellow)"/>
100
+ <text x="325" y="285" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#f6e05e">error (retry < 3)</text>
101
+
102
+ <!-- Retry back to Execute -->
103
+ <path d="M 500 230 Q 400 190 150 230" stroke="#f6e05e" stroke-width="2" fill="none" marker-end="url(#arrow-yellow)"/>
104
+ <text x="350" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#f6e05e">retry after delay</text>
105
+
106
+ <!-- Retry to Failure -->
107
+ <line x1="550" y1="260" x2="600" y2="260" stroke="#e53e3e" stroke-width="2" marker-end="url(#arrow-red)"/>
108
+ <text x="575" y="255" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e53e3e">max retries</text>
109
+
110
+ <!-- Retry Logic Details -->
111
+ <g>
112
+ <rect x="50" y="330" width="700" height="120" rx="10" fill="#2d3748" stroke="#f6e05e" stroke-width="2"/>
113
+ <text x="400" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#f6e05e">Retry Logic with Exponential Backoff</text>
114
+
115
+ <g>
116
+ <text x="70" y="380" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#68d391">Attempt 1:</text>
117
+ <text x="140" y="380" font-family="Arial, sans-serif" font-size="12" fill="#e0e0e0">Execute immediately → Fail → Wait 2¹ = 2 seconds</text>
118
+
119
+ <text x="70" y="400" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#f6e05e">Attempt 2:</text>
120
+ <text x="140" y="400" font-family="Arial, sans-serif" font-size="12" fill="#e0e0e0">Execute after delay → Fail → Wait 2² = 4 seconds</text>
121
+
122
+ <text x="70" y="420" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#ed8936">Attempt 3:</text>
123
+ <text x="140" y="420" font-family="Arial, sans-serif" font-size="12" fill="#e0e0e0">Execute after delay → Fail → Give up, send alert</text>
124
+ </g>
125
+ </g>
126
+
127
+ <!-- Code Example -->
128
+ <g>
129
+ <rect x="50" y="470" width="700" height="70" rx="10" fill="#1a202c" stroke="#4a5568" stroke-width="1"/>
130
+ <text x="400" y="490" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#9ca3af">Task Definition Example</text>
131
+
132
+ <text x="60" y="510" font-family="monospace" font-size="10" fill="#f6e05e">task_type:</text>
133
+ <text x="120" y="510" font-family="monospace" font-size="10" fill="#e0e0e0">"email_reminder"</text>
134
+ <text x="250" y="510" font-family="monospace" font-size="10" fill="#f6e05e">scheduled_for:</text>
135
+ <text x="340" y="510" font-family="monospace" font-size="10" fill="#e0e0e0">"2024-01-01 14:30:00"</text>
136
+
137
+ <text x="60" y="525" font-family="monospace" font-size="10" fill="#f6e05e">payload:</text>
138
+ <text x="110" y="525" font-family="monospace" font-size="10" fill="#e0e0e0">{ recipient: "user@example.com", subject: "Meeting reminder" }</text>
139
+ </g>
140
+ </svg>
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env ruby
2
+ # Order processing example with multiple actions and error handling
3
+
4
+ require 'bundler/setup'
5
+ require 'bunny_farm'
6
+ require 'json'
7
+
8
+ # Example of a more complex message class for order processing
9
+ class OrderMessage < BunnyFarm::Message
10
+ # Define fields including nested structures
11
+ fields :order_id, :total_amount, :status,
12
+ { customer: [:name, :email, :phone] },
13
+ { items: [:product_id, :quantity, :price] },
14
+ :created_at
15
+
16
+ # Define multiple actions for different stages of order processing
17
+ actions :validate, :process_payment, :ship, :cancel
18
+
19
+ def validate(*args)
20
+ puts "\nšŸ“‹ Validating order ##{@items[:order_id]}"
21
+
22
+ # Check required fields
23
+ if @items[:customer][:email].nil? || @items[:customer][:email].empty?
24
+ failure("Customer email is required")
25
+ return
26
+ end
27
+
28
+ if @items[:total_amount].to_f <= 0
29
+ failure("Invalid order amount: #{@items[:total_amount]}")
30
+ return
31
+ end
32
+
33
+ # Simulate validation
34
+ sleep 0.5
35
+
36
+ puts " āœ… Order validation passed"
37
+ puts " Customer: #{@items[:customer][:name]} (#{@items[:customer][:email]})"
38
+ puts " Amount: $#{'%.2f' % @items[:total_amount]}"
39
+
40
+ # Update status
41
+ @items[:status] = 'validated'
42
+
43
+ # Publish next step
44
+ publish('process_payment')
45
+
46
+ success!
47
+ end
48
+
49
+ def process_payment(*args)
50
+ puts "\nšŸ’³ Processing payment for order ##{@items[:order_id]}"
51
+
52
+ # Simulate payment processing
53
+ sleep 1
54
+
55
+ # Randomly simulate payment success/failure for demo
56
+ if rand > 0.2 # 80% success rate
57
+ puts " āœ… Payment successful: $#{'%.2f' % @items[:total_amount]}"
58
+ @items[:status] = 'paid'
59
+
60
+ # Publish next step
61
+ publish('ship')
62
+ success!
63
+ else
64
+ puts " āŒ Payment failed - insufficient funds"
65
+ @items[:status] = 'payment_failed'
66
+
67
+ # Publish cancellation
68
+ publish('cancel')
69
+ failure("Payment processing failed")
70
+ end
71
+ end
72
+
73
+ def ship(*args)
74
+ puts "\nšŸ“¦ Shipping order ##{@items[:order_id]}"
75
+ puts " To: #{@items[:customer][:name]}"
76
+ puts " Email: #{@items[:customer][:email]}"
77
+
78
+ # Simulate shipping process
79
+ sleep 0.5
80
+
81
+ tracking_number = "TRK#{rand(100000..999999)}"
82
+ puts " 🚚 Tracking number: #{tracking_number}"
83
+
84
+ @items[:status] = 'shipped'
85
+ @items[:tracking_number] = tracking_number
86
+
87
+ # Send notification email (simulated)
88
+ send_notification('shipped')
89
+
90
+ success!
91
+ end
92
+
93
+ def cancel(*args)
94
+ puts "\nāŒ Cancelling order ##{@items[:order_id]}"
95
+ puts " Reason: #{@errors.last if @errors}"
96
+
97
+ @items[:status] = 'cancelled'
98
+
99
+ # Send cancellation email (simulated)
100
+ send_notification('cancelled')
101
+
102
+ success! # Even cancellation is handled successfully
103
+ end
104
+
105
+ private
106
+
107
+ def send_notification(type)
108
+ puts " šŸ“§ Sending #{type} notification to #{@items[:customer][:email]}"
109
+ end
110
+ end
111
+
112
+ # Producer/Consumer combo for demonstration
113
+ if __FILE__ == $0
114
+ require 'optparse'
115
+
116
+ mode = nil
117
+ OptionParser.new do |opts|
118
+ opts.banner = "Usage: #{$0} [options]"
119
+ opts.on("-p", "--producer", "Run as producer") { mode = :producer }
120
+ opts.on("-c", "--consumer", "Run as consumer") { mode = :consumer }
121
+ opts.on("-h", "--help", "Show this help") do
122
+ puts opts
123
+ exit
124
+ end
125
+ end.parse!
126
+
127
+ if mode.nil?
128
+ puts "Please specify --producer or --consumer mode"
129
+ exit 1
130
+ end
131
+
132
+ # Configure BunnyFarm
133
+ BunnyFarm.config do
134
+ env 'development'
135
+ app_id mode == :producer ? 'order_producer' : 'order_consumer'
136
+
137
+ if mode == :consumer
138
+ # Configure to receive all OrderMessage actions
139
+ bunny Hashie::Mash.new(
140
+ YAML.load(
141
+ ERB.new(
142
+ File.read(
143
+ File.join(BunnyFarm::CONFIG.config_dir, BunnyFarm::CONFIG.bunny_file)
144
+ )
145
+ ).result, aliases: true
146
+ )[BunnyFarm::CONFIG.env].merge(
147
+ 'routing_key' => 'OrderMessage.*'
148
+ )
149
+ )
150
+ end
151
+ end
152
+
153
+ if mode == :producer
154
+ puts "Order Processing Producer"
155
+ puts "=" * 40
156
+
157
+ # Create sample orders
158
+ orders = [
159
+ {
160
+ order_id: "ORD-#{rand(1000..9999)}",
161
+ total_amount: 99.99,
162
+ status: 'new',
163
+ customer: {
164
+ name: 'John Doe',
165
+ email: 'john@example.com',
166
+ phone: '+1-555-0123'
167
+ },
168
+ items: [
169
+ { product_id: 'PROD-001', quantity: 2, price: 49.99 }
170
+ ],
171
+ created_at: Time.now.to_s
172
+ },
173
+ {
174
+ order_id: "ORD-#{rand(1000..9999)}",
175
+ total_amount: 149.50,
176
+ status: 'new',
177
+ customer: {
178
+ name: 'Jane Smith',
179
+ email: 'jane@example.com',
180
+ phone: '+1-555-0124'
181
+ },
182
+ items: [
183
+ { product_id: 'PROD-002', quantity: 1, price: 149.50 }
184
+ ],
185
+ created_at: Time.now.to_s
186
+ },
187
+ {
188
+ order_id: "ORD-#{rand(1000..9999)}",
189
+ total_amount: 0, # This will fail validation
190
+ status: 'new',
191
+ customer: {
192
+ name: 'Bad Order',
193
+ email: '', # This will also fail
194
+ phone: ''
195
+ },
196
+ items: [],
197
+ created_at: Time.now.to_s
198
+ }
199
+ ]
200
+
201
+ orders.each do |order_data|
202
+ msg = OrderMessage.new
203
+
204
+ # Populate message fields
205
+ order_data.each do |key, value|
206
+ msg[key] = value
207
+ end
208
+
209
+ # Start the order processing workflow
210
+ if msg.publish('validate')
211
+ puts "āœ… Sent order #{order_data[:order_id]} for validation"
212
+ else
213
+ puts "āŒ Failed to send order: #{msg.errors.join(', ')}"
214
+ end
215
+
216
+ sleep 1
217
+ end
218
+
219
+ puts "\nšŸ“¬ All orders sent for processing!"
220
+
221
+ else # consumer mode
222
+ puts "Order Processing Consumer"
223
+ puts "=" * 40
224
+ puts "Waiting for order messages..."
225
+ puts "Press Ctrl+C to exit"
226
+
227
+ begin
228
+ BunnyFarm.manage(false)
229
+ rescue Interrupt
230
+ puts "\n\nShutting down order processor..."
231
+ end
232
+ end
233
+
234
+ # Clean up
235
+ if BunnyFarm::CONFIG.connection && BunnyFarm::CONFIG.connection.open?
236
+ BunnyFarm::CONFIG.connection.close
237
+ end
238
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ # Producer example - sends messages to RabbitMQ
3
+
4
+ require 'bundler/setup'
5
+ require 'bunny_farm'
6
+ require_relative 'simple_message'
7
+
8
+ # Configure BunnyFarm
9
+ BunnyFarm.config do
10
+ env 'development'
11
+ app_id 'greeting_producer'
12
+ end
13
+
14
+ puts "BunnyFarm Producer Example"
15
+ puts "=" * 40
16
+ puts "Sending messages to RabbitMQ..."
17
+ puts "Queue: #{BunnyFarm::CONFIG.bunny.queue_name}"
18
+ puts "Exchange: #{BunnyFarm::CONFIG.bunny.exchange_name}"
19
+ puts "=" * 40
20
+
21
+ # Create and send hello messages
22
+ 3.times do |i|
23
+ msg = GreetingMessage.new
24
+ msg[:name] = "User #{i + 1}"
25
+ msg[:greeting_type] = 'hello'
26
+ msg[:timestamp] = Time.now.to_s
27
+
28
+ if msg.publish('say_hello')
29
+ puts "āœ… Sent hello message for User #{i + 1}"
30
+ else
31
+ puts "āŒ Failed to send hello message: #{msg.errors.join(', ')}"
32
+ end
33
+
34
+ sleep 0.5
35
+ end
36
+
37
+ # Create and send goodbye messages
38
+ 2.times do |i|
39
+ msg = GreetingMessage.new
40
+ msg[:name] = "Guest #{i + 1}"
41
+ msg[:greeting_type] = 'goodbye'
42
+ msg[:timestamp] = Time.now.to_s
43
+
44
+ if msg.publish('say_goodbye')
45
+ puts "āœ… Sent goodbye message for Guest #{i + 1}"
46
+ else
47
+ puts "āŒ Failed to send goodbye message: #{msg.errors.join(', ')}"
48
+ end
49
+
50
+ sleep 0.5
51
+ end
52
+
53
+ puts "\nšŸ“¬ All messages sent!"
54
+ puts "Run consumer.rb in another terminal to process them."
55
+
56
+ # Clean up
57
+ if BunnyFarm::CONFIG.connection && BunnyFarm::CONFIG.connection.open?
58
+ BunnyFarm::CONFIG.connection.close
59
+ puts "Connection closed."
60
+ end
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ # Simple message class example
3
+
4
+ require 'bundler/setup'
5
+ require 'bunny_farm'
6
+
7
+ # Define a simple message class for processing greetings
8
+ class GreetingMessage < BunnyFarm::Message
9
+ # Define the fields this message expects
10
+ fields :name, :greeting_type, :timestamp
11
+
12
+ # Define the actions this message can handle
13
+ actions :say_hello, :say_goodbye
14
+
15
+ def say_hello(*args)
16
+ puts "šŸ‘‹ Hello, #{@items[:name]}!"
17
+ puts "Received at: #{@items[:timestamp]}"
18
+
19
+ # Simulate some processing
20
+ sleep 0.5
21
+
22
+ # Mark as successful
23
+ success!
24
+ end
25
+
26
+ def say_goodbye(*args)
27
+ puts "šŸ‘‹ Goodbye, #{@items[:name]}!"
28
+ puts "Until next time at: #{@items[:timestamp]}"
29
+
30
+ # Simulate some processing
31
+ sleep 0.5
32
+
33
+ # Mark as successful
34
+ success!
35
+ end
36
+ end
37
+
38
+ if __FILE__ == $0
39
+ puts "Simple Message Class Example"
40
+ puts "=" * 40
41
+ puts "This file defines the GreetingMessage class."
42
+ puts "Use producer.rb to send messages and consumer.rb to process them."
43
+ end