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.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/.github/workflows/docs.yml +38 -0
- data/.gitignore +11 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +61 -0
- data/COMMITS.md +196 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +330 -0
- data/Rakefile +9 -0
- data/bunny_farm.gemspec +30 -0
- data/config/bunny.yml.erb +29 -0
- data/config/bunny_test.yml.erb +29 -0
- data/config/hipchat.yml.erb +12 -0
- data/docs/api/configuration.md +9 -0
- data/docs/api/consumer.md +8 -0
- data/docs/api/message-class.md +419 -0
- data/docs/api/publisher.md +9 -0
- data/docs/architecture/integration.md +8 -0
- data/docs/architecture/message-flow.md +11 -0
- data/docs/architecture/overview.md +448 -0
- data/docs/architecture/scaling.md +8 -0
- data/docs/assets/actions_dsl_flow.svg +109 -0
- data/docs/assets/architecture_overview.svg +152 -0
- data/docs/assets/best_practices_patterns.svg +203 -0
- data/docs/assets/bunny_farm_logo.png +0 -0
- data/docs/assets/configuration_api_methods.svg +104 -0
- data/docs/assets/configuration_flow.svg +130 -0
- data/docs/assets/configuration_hierarchy.svg +70 -0
- data/docs/assets/data_processing_pipeline.svg +131 -0
- data/docs/assets/debugging_monitoring.svg +165 -0
- data/docs/assets/ecommerce_example_flow.svg +145 -0
- data/docs/assets/email_campaign_example.svg +127 -0
- data/docs/assets/environment_variables_map.svg +78 -0
- data/docs/assets/error_handling_flow.svg +114 -0
- data/docs/assets/favicon.ico +1 -0
- data/docs/assets/fields_dsl_structure.svg +89 -0
- data/docs/assets/instance_methods_lifecycle.svg +137 -0
- data/docs/assets/integration_patterns.svg +207 -0
- data/docs/assets/json_serialization_flow.svg +153 -0
- data/docs/assets/logo.svg +4 -0
- data/docs/assets/message_api_overview.svg +126 -0
- data/docs/assets/message_encapsulation.svg +113 -0
- data/docs/assets/message_lifecycle.svg +110 -0
- data/docs/assets/message_structure.svg +138 -0
- data/docs/assets/publisher_consumer_api.svg +120 -0
- data/docs/assets/scaling_deployment_patterns.svg +195 -0
- data/docs/assets/smart_routing_diagram.svg +131 -0
- data/docs/assets/system_architecture_overview.svg +155 -0
- data/docs/assets/task_scheduling_flow.svg +139 -0
- data/docs/assets/testing_strategies.svg +146 -0
- data/docs/assets/workflow_patterns.svg +183 -0
- data/docs/assets/yaml_config_structure.svg +72 -0
- data/docs/configuration/environment-variables.md +14 -0
- data/docs/configuration/overview.md +373 -0
- data/docs/configuration/programmatic-setup.md +10 -0
- data/docs/configuration/yaml-configuration.md +12 -0
- data/docs/core-features/configuration.md +528 -0
- data/docs/core-features/error-handling.md +82 -0
- data/docs/core-features/json-serialization.md +545 -0
- data/docs/core-features/message-design.md +406 -0
- data/docs/core-features/smart-routing.md +467 -0
- data/docs/core-features/task-scheduling.md +67 -0
- data/docs/core-features/workflow-support.md +112 -0
- data/docs/development/contributing.md +345 -0
- data/docs/development/roadmap.md +9 -0
- data/docs/development/testing.md +14 -0
- data/docs/examples/order-processing.md +10 -0
- data/docs/examples/overview.md +269 -0
- data/docs/examples/real-world.md +8 -0
- data/docs/examples/simple-producer-consumer.md +15 -0
- data/docs/examples/task-scheduler.md +9 -0
- data/docs/getting-started/basic-concepts.md +274 -0
- data/docs/getting-started/installation.md +122 -0
- data/docs/getting-started/quick-start.md +158 -0
- data/docs/index.md +106 -0
- data/docs/message-structure/actions-dsl.md +163 -0
- data/docs/message-structure/fields-dsl.md +146 -0
- data/docs/message-structure/instance-methods.md +115 -0
- data/docs/message-structure/overview.md +211 -0
- data/examples/README.md +212 -0
- data/examples/consumer.rb +41 -0
- data/examples/images/message_flow.svg +87 -0
- data/examples/images/order_workflow.svg +122 -0
- data/examples/images/producer_consumer.svg +96 -0
- data/examples/images/task_scheduler.svg +140 -0
- data/examples/order_processor.rb +238 -0
- data/examples/producer.rb +60 -0
- data/examples/simple_message.rb +43 -0
- data/examples/task_scheduler.rb +263 -0
- data/images/architecture_overview.svg +152 -0
- data/images/bunny_farm_logo.png +0 -0
- data/images/configuration_flow.svg +130 -0
- data/images/message_structure.svg +138 -0
- data/lib/bunny_farm/.irbrc +7 -0
- data/lib/bunny_farm/generic_consumer.rb +12 -0
- data/lib/bunny_farm/hash_ext.rb +37 -0
- data/lib/bunny_farm/init_bunny.rb +137 -0
- data/lib/bunny_farm/init_hipchat.rb +49 -0
- data/lib/bunny_farm/message.rb +218 -0
- data/lib/bunny_farm/message_elements.rb +25 -0
- data/lib/bunny_farm/version.rb +3 -0
- data/lib/bunny_farm.rb +9 -0
- data/mkdocs.yml +148 -0
- metadata +244 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Basic Concepts
|
|
2
|
+
|
|
3
|
+
Understanding BunnyFarm's core concepts will help you design effective message-driven applications. This guide covers the fundamental principles behind BunnyFarm's architecture.
|
|
4
|
+
|
|
5
|
+
## Message-Centric Architecture
|
|
6
|
+
|
|
7
|
+
BunnyFarm is built around the concept of **messages as living entities**. Unlike traditional job queues where jobs are simple data structures, BunnyFarm messages are full Ruby classes that encapsulate both data and behavior.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
class OrderMessage < BunnyFarm::Message
|
|
13
|
+
# Data structure
|
|
14
|
+
fields :order_id, :customer_email, :items
|
|
15
|
+
|
|
16
|
+
# Behavior
|
|
17
|
+
actions :process, :ship, :cancel
|
|
18
|
+
|
|
19
|
+
def process
|
|
20
|
+
validate_order
|
|
21
|
+
charge_payment
|
|
22
|
+
update_inventory
|
|
23
|
+
success!
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Core Components
|
|
29
|
+
|
|
30
|
+
### 1. Message Classes
|
|
31
|
+
|
|
32
|
+
Message classes inherit from `BunnyFarm::Message` and define:
|
|
33
|
+
|
|
34
|
+
- **Fields**: The data structure using the `fields` DSL
|
|
35
|
+
- **Actions**: Available operations using the `actions` DSL
|
|
36
|
+
- **Methods**: Business logic for each action
|
|
37
|
+
|
|
38
|
+
### 2. Routing Keys
|
|
39
|
+
|
|
40
|
+
BunnyFarm uses a predictable routing pattern:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
MessageClassName.action
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
- `OrderMessage.process`
|
|
48
|
+
- `EmailMessage.send`
|
|
49
|
+
- `ReportMessage.generate`
|
|
50
|
+
|
|
51
|
+
This makes routing transparent and debuggable.
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
### 3. JSON Serialization
|
|
56
|
+
|
|
57
|
+
All message data is serialized as JSON for:
|
|
58
|
+
- **Human readability** - Easy debugging and monitoring
|
|
59
|
+
- **Language interoperability** - Other systems can read/write messages
|
|
60
|
+
- **Simplicity** - No complex binary protocols
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
## Message Lifecycle
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
1. **Creation**: Message instance is created with data
|
|
69
|
+
2. **Publishing**: Message is serialized to JSON and sent to RabbitMQ
|
|
70
|
+
3. **Routing**: RabbitMQ routes based on the routing key
|
|
71
|
+
4. **Consumption**: Worker receives and deserializes the message
|
|
72
|
+
5. **Processing**: The appropriate action method is called
|
|
73
|
+
6. **Acknowledgment**: Success/failure determines ACK/NACK
|
|
74
|
+
|
|
75
|
+
## Fields DSL
|
|
76
|
+
|
|
77
|
+
The `fields` DSL defines the expected data structure:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
class CustomerMessage < BunnyFarm::Message
|
|
81
|
+
fields :name, :email,
|
|
82
|
+
{ address: [:street, :city, :state, :zip] },
|
|
83
|
+
{ preferences: [:newsletter, :promotions] }
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This creates:
|
|
88
|
+
- Simple fields: `name`, `email`
|
|
89
|
+
- Nested objects: `address` with sub-fields
|
|
90
|
+
- Arrays: `preferences` as a list
|
|
91
|
+
|
|
92
|
+
## Actions DSL
|
|
93
|
+
|
|
94
|
+
The `actions` DSL defines available operations:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
class OrderMessage < BunnyFarm::Message
|
|
98
|
+
actions :validate, :process, :ship, :cancel, :refund
|
|
99
|
+
|
|
100
|
+
def validate
|
|
101
|
+
# Validation logic
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def process
|
|
105
|
+
# Processing logic
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ... other action methods
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Each action becomes a routable endpoint.
|
|
113
|
+
|
|
114
|
+
## Data Access
|
|
115
|
+
|
|
116
|
+
BunnyFarm provides hash-like access to message data:
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
message = CustomerMessage.new
|
|
120
|
+
|
|
121
|
+
# Setting data
|
|
122
|
+
message[:name] = "John Doe"
|
|
123
|
+
message[:email] = "john@example.com"
|
|
124
|
+
message[:address] = {
|
|
125
|
+
street: "123 Main St",
|
|
126
|
+
city: "Boston",
|
|
127
|
+
state: "MA",
|
|
128
|
+
zip: "02101"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Getting data
|
|
132
|
+
puts message[:name] # "John Doe"
|
|
133
|
+
puts message[:address][:city] # "Boston"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## State Management
|
|
137
|
+
|
|
138
|
+
Messages track their processing state:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
def process_order
|
|
142
|
+
validate_payment
|
|
143
|
+
|
|
144
|
+
if payment_valid?
|
|
145
|
+
charge_customer
|
|
146
|
+
success! # Mark as successful
|
|
147
|
+
else
|
|
148
|
+
failure("Invalid payment method")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
successful? # Returns true/false for ACK/NACK
|
|
152
|
+
end
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
State methods:
|
|
156
|
+
- `success!` - Mark operation as successful
|
|
157
|
+
- `failure(message)` - Mark operation as failed with reason
|
|
158
|
+
- `successful?` - Check if operation succeeded
|
|
159
|
+
- `failed?` - Check if operation failed
|
|
160
|
+
- `errors` - Array of error messages
|
|
161
|
+
|
|
162
|
+
## Configuration Patterns
|
|
163
|
+
|
|
164
|
+
BunnyFarm supports multiple configuration approaches:
|
|
165
|
+
|
|
166
|
+
### Environment Variables
|
|
167
|
+
```bash
|
|
168
|
+
export AMQP_HOST=localhost
|
|
169
|
+
export AMQP_EXCHANGE=my_exchange
|
|
170
|
+
export AMQP_QUEUE=my_queue
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Programmatic Configuration
|
|
174
|
+
```ruby
|
|
175
|
+
BunnyFarm.config do
|
|
176
|
+
env 'production'
|
|
177
|
+
app_id 'order_processor'
|
|
178
|
+
bunny_file 'config/rabbitmq.yml'
|
|
179
|
+
end
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### YAML Configuration
|
|
183
|
+
```yaml
|
|
184
|
+
production:
|
|
185
|
+
host: amqp.example.com
|
|
186
|
+
exchange_name: orders
|
|
187
|
+
queue_name: order_processing
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Error Handling
|
|
191
|
+
|
|
192
|
+
BunnyFarm provides built-in error handling:
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
def risky_operation
|
|
196
|
+
begin
|
|
197
|
+
perform_external_api_call
|
|
198
|
+
success!
|
|
199
|
+
rescue ExternalAPIError => e
|
|
200
|
+
failure("API call failed: #{e.message}")
|
|
201
|
+
rescue StandardError => e
|
|
202
|
+
failure("Unexpected error: #{e.message}")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
successful?
|
|
206
|
+
end
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Failed messages can be:
|
|
210
|
+
- Retried automatically (RabbitMQ feature)
|
|
211
|
+
- Sent to dead letter queues
|
|
212
|
+
- Logged for manual inspection
|
|
213
|
+
|
|
214
|
+
## Best Practices
|
|
215
|
+
|
|
216
|
+
### 1. Keep Actions Focused
|
|
217
|
+
Each action should have a single responsibility:
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
# Good
|
|
221
|
+
actions :validate, :process, :ship
|
|
222
|
+
|
|
223
|
+
# Avoid
|
|
224
|
+
actions :validate_and_process_and_ship
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 2. Use Meaningful Names
|
|
228
|
+
Choose descriptive names for clarity:
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
# Good
|
|
232
|
+
class OrderProcessingMessage
|
|
233
|
+
actions :validate_payment, :update_inventory
|
|
234
|
+
|
|
235
|
+
# Better than
|
|
236
|
+
class OrderMessage
|
|
237
|
+
actions :do_stuff, :handle
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 3. Handle Errors Gracefully
|
|
241
|
+
Always use proper error handling:
|
|
242
|
+
|
|
243
|
+
```ruby
|
|
244
|
+
def process
|
|
245
|
+
validate_data
|
|
246
|
+
return unless successful?
|
|
247
|
+
|
|
248
|
+
perform_work
|
|
249
|
+
return unless successful?
|
|
250
|
+
|
|
251
|
+
finalize
|
|
252
|
+
end
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### 4. Design for Idempotency
|
|
256
|
+
Make operations safe to retry:
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
def charge_payment
|
|
260
|
+
return if payment_already_charged?
|
|
261
|
+
|
|
262
|
+
# Perform charge
|
|
263
|
+
success!
|
|
264
|
+
end
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Next Steps
|
|
268
|
+
|
|
269
|
+
With these concepts in mind, you're ready to explore:
|
|
270
|
+
|
|
271
|
+
- **[Message Structure](../message-structure/overview.md)** - Deep dive into Fields and Actions DSL
|
|
272
|
+
- **[Configuration](../configuration/overview.md)** - Advanced configuration options
|
|
273
|
+
- **[Examples](../examples/overview.md)** - Real-world usage patterns
|
|
274
|
+
- **[API Reference](../api/message-class.md)** - Complete API documentation
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
BunnyFarm is distributed as a Ruby gem and can be installed using bundler or gem directly.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
Before installing BunnyFarm, ensure you have:
|
|
8
|
+
|
|
9
|
+
- **Ruby 2.5 or higher** - BunnyFarm supports modern Ruby versions
|
|
10
|
+
- **RabbitMQ server** - Either local installation or cloud service
|
|
11
|
+
- **Bundler** - For dependency management
|
|
12
|
+
|
|
13
|
+
## Installing BunnyFarm
|
|
14
|
+
|
|
15
|
+
### Using Bundler (Recommended)
|
|
16
|
+
|
|
17
|
+
Add this line to your application's Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'bunny_farm'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then execute:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Using Gem Directly
|
|
30
|
+
|
|
31
|
+
Install it yourself as:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gem install bunny_farm
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Setting up RabbitMQ
|
|
38
|
+
|
|
39
|
+
### Local Installation
|
|
40
|
+
|
|
41
|
+
#### macOS (using Homebrew)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Install RabbitMQ
|
|
45
|
+
brew install rabbitmq
|
|
46
|
+
|
|
47
|
+
# Start RabbitMQ server
|
|
48
|
+
brew services start rabbitmq
|
|
49
|
+
|
|
50
|
+
# Enable management plugin (optional but recommended)
|
|
51
|
+
rabbitmq-plugins enable rabbitmq_management
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### Ubuntu/Debian
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Install RabbitMQ
|
|
58
|
+
sudo apt-get update
|
|
59
|
+
sudo apt-get install rabbitmq-server
|
|
60
|
+
|
|
61
|
+
# Start RabbitMQ server
|
|
62
|
+
sudo systemctl start rabbitmq-server
|
|
63
|
+
sudo systemctl enable rabbitmq-server
|
|
64
|
+
|
|
65
|
+
# Enable management plugin
|
|
66
|
+
sudo rabbitmq-plugins enable rabbitmq_management
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Docker
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Run RabbitMQ with management plugin
|
|
73
|
+
docker run -d \
|
|
74
|
+
--name rabbitmq \
|
|
75
|
+
-p 5672:5672 \
|
|
76
|
+
-p 15672:15672 \
|
|
77
|
+
rabbitmq:3-management
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Cloud Services
|
|
81
|
+
|
|
82
|
+
BunnyFarm works with cloud RabbitMQ services:
|
|
83
|
+
|
|
84
|
+
- **CloudAMQP** - Managed RabbitMQ service
|
|
85
|
+
- **Amazon MQ** - AWS managed message broker
|
|
86
|
+
- **Google Cloud Pub/Sub** - With AMQP support
|
|
87
|
+
- **Azure Service Bus** - With AMQP 1.0 support
|
|
88
|
+
|
|
89
|
+
## Verification
|
|
90
|
+
|
|
91
|
+
Verify your installation by checking if BunnyFarm loads correctly:
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
require 'bunny_farm'
|
|
95
|
+
puts BunnyFarm::VERSION
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You should see the version number output without any errors.
|
|
99
|
+
|
|
100
|
+
## Environment Setup
|
|
101
|
+
|
|
102
|
+
Set up your environment variables for development:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
export AMQP_HOST=localhost
|
|
106
|
+
export AMQP_VHOST=/
|
|
107
|
+
export AMQP_PORT=5672
|
|
108
|
+
export AMQP_USER=guest
|
|
109
|
+
export AMQP_PASS=guest
|
|
110
|
+
export AMQP_EXCHANGE=bunny_farm_exchange
|
|
111
|
+
export AMQP_QUEUE=bunny_farm_queue
|
|
112
|
+
export AMQP_ROUTING_KEY='#'
|
|
113
|
+
export AMQP_APP_NAME=my_bunny_farm_app
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Next Steps
|
|
117
|
+
|
|
118
|
+
With BunnyFarm installed and RabbitMQ running, you're ready to:
|
|
119
|
+
|
|
120
|
+
1. **[Quick Start Guide](quick-start.md)** - Get your first message processing in 5 minutes
|
|
121
|
+
2. **[Basic Concepts](basic-concepts.md)** - Understand BunnyFarm's core concepts
|
|
122
|
+
3. **[Configuration](../configuration/overview.md)** - Learn about configuration options
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Quick Start
|
|
2
|
+
|
|
3
|
+
This guide will get you up and running with BunnyFarm in just a few minutes. We'll create a simple message class, publish a message, and process it.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before starting, make sure you have:
|
|
8
|
+
|
|
9
|
+
- [BunnyFarm installed](installation.md)
|
|
10
|
+
- RabbitMQ server running locally or accessible remotely
|
|
11
|
+
- Basic familiarity with Ruby
|
|
12
|
+
|
|
13
|
+
## Step 1: Create Your First Message Class
|
|
14
|
+
|
|
15
|
+
Create a file called `greeting_message.rb`:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
require 'bunny_farm'
|
|
19
|
+
|
|
20
|
+
class GreetingMessage < BunnyFarm::Message
|
|
21
|
+
# Define the fields this message expects
|
|
22
|
+
fields :name, :language
|
|
23
|
+
|
|
24
|
+
# Define the actions this message can perform
|
|
25
|
+
actions :send_greeting
|
|
26
|
+
|
|
27
|
+
def send_greeting
|
|
28
|
+
puts "Hello #{@items[:name]}! (in #{@items[:language]})"
|
|
29
|
+
|
|
30
|
+
# Mark the message as successfully processed
|
|
31
|
+
success!
|
|
32
|
+
|
|
33
|
+
# Return true to ACK the message
|
|
34
|
+
successful?
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Step 2: Configure BunnyFarm
|
|
40
|
+
|
|
41
|
+
Create a simple configuration (or use environment variables):
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
# Basic configuration using defaults
|
|
45
|
+
BunnyFarm.config do
|
|
46
|
+
app_id 'greeting_app'
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Step 3: Publish a Message
|
|
51
|
+
|
|
52
|
+
Create a file called `publisher.rb`:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
require_relative 'greeting_message'
|
|
56
|
+
|
|
57
|
+
# Configure BunnyFarm
|
|
58
|
+
BunnyFarm.config do
|
|
59
|
+
app_id 'greeting_publisher'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Create a new message
|
|
63
|
+
message = GreetingMessage.new
|
|
64
|
+
|
|
65
|
+
# Set the message data
|
|
66
|
+
message[:name] = 'Alice'
|
|
67
|
+
message[:language] = 'English'
|
|
68
|
+
|
|
69
|
+
# Publish the message with the 'send_greeting' action
|
|
70
|
+
message.publish('send_greeting')
|
|
71
|
+
|
|
72
|
+
if message.successful?
|
|
73
|
+
puts "Message published successfully!"
|
|
74
|
+
else
|
|
75
|
+
puts "Failed to publish message: #{message.errors.join(', ')}"
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Step 4: Create a Consumer
|
|
80
|
+
|
|
81
|
+
Create a file called `consumer.rb`:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
require_relative 'greeting_message'
|
|
85
|
+
|
|
86
|
+
# Configure BunnyFarm
|
|
87
|
+
BunnyFarm.config do
|
|
88
|
+
app_id 'greeting_consumer'
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
puts "Starting message consumer..."
|
|
92
|
+
puts "Press Ctrl+C to stop"
|
|
93
|
+
|
|
94
|
+
# Start processing messages (this will block)
|
|
95
|
+
BunnyFarm.manage
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Step 5: Run the Example
|
|
99
|
+
|
|
100
|
+
1. **Start the consumer** (in one terminal):
|
|
101
|
+
```bash
|
|
102
|
+
ruby consumer.rb
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
2. **Publish a message** (in another terminal):
|
|
106
|
+
```bash
|
|
107
|
+
ruby publisher.rb
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You should see output like:
|
|
111
|
+
|
|
112
|
+
**Consumer terminal:**
|
|
113
|
+
```
|
|
114
|
+
Starting message consumer...
|
|
115
|
+
Press Ctrl+C to stop
|
|
116
|
+
Hello Alice! (in English)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Publisher terminal:**
|
|
120
|
+
```
|
|
121
|
+
Message published successfully!
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Understanding What Happened
|
|
125
|
+
|
|
126
|
+
1. **Message Class**: `GreetingMessage` defines the structure and behavior
|
|
127
|
+
2. **Fields DSL**: `fields :name, :language` specifies expected data
|
|
128
|
+
3. **Actions DSL**: `actions :send_greeting` defines available operations
|
|
129
|
+
4. **Routing Key**: The message was routed using `GreetingMessage.send_greeting`
|
|
130
|
+
5. **JSON Serialization**: Data was automatically serialized/deserialized
|
|
131
|
+
6. **AMQP Flow**: Message traveled through RabbitMQ from publisher to consumer
|
|
132
|
+
|
|
133
|
+
## Next Steps
|
|
134
|
+
|
|
135
|
+
Now that you have a basic understanding, explore:
|
|
136
|
+
|
|
137
|
+
- **[Basic Concepts](basic-concepts.md)** - Understand BunnyFarm's architecture
|
|
138
|
+
- **[Message Structure](../message-structure/overview.md)** - Learn about the Fields and Actions DSL
|
|
139
|
+
- **[Configuration Options](../configuration/overview.md)** - Advanced configuration
|
|
140
|
+
- **[Examples](../examples/overview.md)** - More comprehensive examples
|
|
141
|
+
|
|
142
|
+
## Common Issues
|
|
143
|
+
|
|
144
|
+
### Connection Refused
|
|
145
|
+
If you see connection errors, ensure RabbitMQ is running:
|
|
146
|
+
```bash
|
|
147
|
+
# Check RabbitMQ status
|
|
148
|
+
sudo systemctl status rabbitmq-server
|
|
149
|
+
|
|
150
|
+
# Or for Docker
|
|
151
|
+
docker ps | grep rabbitmq
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Permission Denied
|
|
155
|
+
Make sure your AMQP credentials are correct in your environment variables or configuration.
|
|
156
|
+
|
|
157
|
+
### Messages Not Processing
|
|
158
|
+
Verify that your consumer is listening to the correct queue and routing key configuration.
|
data/docs/index.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# BunnyFarm
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="assets/bunny_farm_logo.png" alt="BunnyFarm - Lightweight AMQP Job Manager" width="400">
|
|
5
|
+
<br />
|
|
6
|
+
<p>
|
|
7
|
+
<a href="https://badge.fury.io/rb/bunny_farm"><img src="https://badge.fury.io/rb/bunny_farm.svg" alt="Gem Version" /></a>
|
|
8
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
Like a well-organized farm where messages hop efficiently from producers to consumers, BunnyFarm provides a lightweight Ruby gem for managing background jobs using RabbitMQ. Each message becomes a living entity with its own behavior, routing intelligently through the message broker to the right workers.
|
|
13
|
+
|
|
14
|
+
## What is BunnyFarm?
|
|
15
|
+
|
|
16
|
+
The bunny farm is an abstraction in which the messages are encapsulated as classes. Instances of these BunnyFarm::Messages are hopping around the RabbitMQ as JSON strings with routing keys in the form of `MessageClassName.action` where action is a method on the MessageClassName instance.
|
|
17
|
+
|
|
18
|
+
## Key Features
|
|
19
|
+
|
|
20
|
+
- **🐰 [Message-Centric Design](core-features/message-design.md)** - Classes encapsulate behavior and data
|
|
21
|
+
- **🔀 [Smart Routing](core-features/smart-routing.md)** - Automatic routing with ClassName.action keys
|
|
22
|
+
- **📨 [JSON Serialization](core-features/json-serialization.md)** - Simple, readable message format
|
|
23
|
+
- **⚙️ [Flexible Configuration](core-features/configuration.md)** - Environment, YAML, or programmatic setup
|
|
24
|
+
- **🔄 [Workflow Support](core-features/workflow-support.md)** - Multi-step processes with message chaining
|
|
25
|
+
- **⏰ [Task Scheduling](core-features/task-scheduling.md)** - Delayed execution with retry logic
|
|
26
|
+
- **🛡️ [Error Handling](core-features/error-handling.md)** - Built-in success/failure tracking
|
|
27
|
+
- **🎯 Simplicity First** - K.I.S.S. design philosophy
|
|
28
|
+
|
|
29
|
+
## Architecture Overview
|
|
30
|
+
|
|
31
|
+
BunnyFarm provides a clean, layered architecture that separates concerns and enables scalable message processing:
|
|
32
|
+
|
|
33
|
+
<img src="assets/architecture_overview.svg" alt="Architecture Overview" width="100%">
|
|
34
|
+
|
|
35
|
+
The architecture consists of four main layers:
|
|
36
|
+
|
|
37
|
+
1. **Ruby Application Layer** - Your web apps, API servers, schedulers, and worker processes
|
|
38
|
+
2. **BunnyFarm Library Layer** - Core components including Message classes, Publisher, Consumer, Config, and Router
|
|
39
|
+
3. **RabbitMQ Message Broker** - Handles message routing, queuing, and delivery with exchanges and queues
|
|
40
|
+
4. **Persistence & External Services** - Databases, email services, file storage, APIs, and caching layers
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
Get up and running with BunnyFarm in minutes:
|
|
45
|
+
|
|
46
|
+
### Installation
|
|
47
|
+
|
|
48
|
+
Add this line to your application's Gemfile:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
gem 'bunny_farm'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
And then execute:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bundle install
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Basic Usage
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
require 'bunny_farm'
|
|
64
|
+
require 'my_message_class'
|
|
65
|
+
|
|
66
|
+
# Configure BunnyFarm
|
|
67
|
+
BunnyFarm.config
|
|
68
|
+
|
|
69
|
+
# Start processing messages (blocks)
|
|
70
|
+
BunnyFarm.manage
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Publishing Messages
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
require 'bunny_farm'
|
|
77
|
+
|
|
78
|
+
BunnyFarm.config do
|
|
79
|
+
app_id 'my_job_name'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Create and publish a message
|
|
83
|
+
message = MyMessageClass.new
|
|
84
|
+
message[:field1] = 'Hello'
|
|
85
|
+
message[:field2] = 'World'
|
|
86
|
+
message.publish('action') # routing key: MyMessageClass.action
|
|
87
|
+
|
|
88
|
+
puts 'Success!' if message.successful?
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Why BunnyFarm?
|
|
92
|
+
|
|
93
|
+
- **Simplistic?** Because extensive is sometimes overkill
|
|
94
|
+
- **JSON?** Because binary compression is sometimes overkill
|
|
95
|
+
- **Bunny?** Who doesn't like bunnies? They're like cats with long ears
|
|
96
|
+
- **AMQP?** I like AMQP. I like RabbitMQ as an AMQP broker
|
|
97
|
+
|
|
98
|
+
BTW, at the farm bunnies grow best if planted ears up. 🐰
|
|
99
|
+
|
|
100
|
+
## What's Next?
|
|
101
|
+
|
|
102
|
+
- **[Installation Guide](getting-started/installation.md)** - Detailed installation and setup
|
|
103
|
+
- **[Quick Start](getting-started/quick-start.md)** - Get running in 5 minutes
|
|
104
|
+
- **[Basic Concepts](getting-started/basic-concepts.md)** - Understand the fundamentals
|
|
105
|
+
- **[Examples](examples/overview.md)** - Comprehensive, runnable examples
|
|
106
|
+
- **[API Reference](api/message-class.md)** - Complete API documentation
|