Delayed Rabbit
A lightweight Ruby gem for scheduling delayed background jobs using RabbitMQ's delayed message exchange plugin.
Features
- Schedules jobs with custom delays using RabbitMQ's x-delayed-message plugin
- Uses JSON serialization for job data
- Configurable exchange and queue settings
- Simple API for publishing delayed jobs
- Rails integration support
- Automatic connection management
- Persistent message delivery
- Support for custom routing keys
- Dead-letter queue support
Requirements
- Ruby 3.2+
- RabbitMQ 3.8+ with x-delayed-message plugin enabled
- Bunny gem (~> 2.18)
- JSON serialization support
Installation
Enabling RabbitMQ Plugin
Before using this gem, you need to enable the delayed message plugin in RabbitMQ:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
Ruby Gem Installation
Add this line to your application's Gemfile:
gem 'delayed_rabbit'
And then execute:
bundle install
Or install it yourself as:
gem install delayed_rabbit
Rails Integration
1. Install the Gem
Add to your Gemfile:
gem 'delayed_rabbit'
2. Run the Installer
Run the generator to set up configuration files:
rails generate delayed_rabbit:install
This will create:
-
config/initializers/delayed_rabbit.rb
- Main configuration file -
config/rabbitmq.yml
- Environment-specific RabbitMQ settings
3. Configure RabbitMQ
Edit config/rabbitmq.yml
with your RabbitMQ settings:
development:
host: localhost
port: 5672
user: guest
password: guest
vhost: /
production:
host: <%= ENV['RABBITMQ_HOST'] %>
port: <%= ENV['RABBITMQ_PORT'] || 5672 %>
user: <%= ENV['RABBITMQ_USER'] %>
password: <%= ENV['RABBITMQ_PASSWORD'] %>
vhost: <%= ENV['RABBITMQ_VHOST'] || '/' %>
4. Use in Your Application
In Models/Services
class UserNotifier
def self.send_welcome_notification(user)
DelayedRabbit::JobPublisher.publish(
{
type: "welcome_email",
user_id: user.id,
email: user.email
},
delay_ms: 5000, # 5 seconds delay
routing_key: "notifications.welcome"
)
end
end
In Controllers
class UsersController < ApplicationController
def create
user = User.create(user_params)
UserNotifier.send_welcome_notification(user)
redirect_to root_path, notice: 'User created successfully'
end
end
Using Rake Tasks
The gem provides a rake task for testing:
# Enqueue a test job with 5 second delay
bundle exec rake delayed_rabbit:enqueue_test_job[5000]
# Enqueue a notification job
bundle exec rake jobs:enqueue_notification[5000,123]
Usage (Non-Rails)
If you're not using Rails:
require 'delayed_rabbit'
# Configure manually
DelayedRabbit.configure do |config|
config.connection_options = {
host: "localhost",
port: 5672,
user: "guest",
password: "guest"
}
end
# Create a publisher
publisher = DelayedRabbit::JobPublisher.new
# Publish a job
publisher.publish(
{
type: "email_notification",
recipient: "user@example.com"
},
delay_ms: 5000
)
# Close connection
publisher.close
Using with Rails
- Add the gem to your Gemfile
- Run the rake task to enqueue a test job:
bundle exec rake delayed_rabbit:enqueue_test_job[5000]
You can also create your own rake tasks for specific job types:
namespace :jobs do
desc "Enqueue a notification job"
task :enqueue_notification, [:delay_ms, :user_id] => :environment do |t, args|
delay_ms = args[:delay_ms].to_i || 5000
user_id = args[:user_id]
job_data = {
type: "notification",
user_id: user_id,
message: "Welcome notification"
}
DelayedRabbit::JobPublisher.publish(job_data, delay_ms: delay_ms, routing_key: "notifications.#{user_id}")
end
end
Advanced Usage
Custom Exchange Configuration
publisher = DelayedRabbit::JobPublisher.new(
exchange_options: {
type: "x-delayed-message",
durable: true,
auto_delete: false,
arguments: {"x-delayed-type" => "direct"} # Change to direct exchange
}
)
Custom Queue Configuration
publisher = DelayedRabbit::JobPublisher.new(
queue_options: {
durable: true,
exclusive: false,
auto_delete: false,
arguments: {
"x-dead-letter-exchange" => "dlx_exchange",
"x-dead-letter-routing-key" => "dlx_key",
"x-message-ttl" => 3600000 # 1 hour TTL
}
}
)
Using with Rails Environment
You can configure different settings based on Rails environment:
# config/initializers/delayed_rabbit.rb
DelayedRabbit.configure do |config|
config.connection_options = {
host: Rails.env.production? ? "rabbitmq-prod" : "localhost",
port: 5672,
user: Rails.application.credentials.rabbitmq[:user],
password: Rails.application.credentials.rabbitmq[:password]
}
end
Configuration Options
Connection Options
-
host
: RabbitMQ server hostname -
port
: RabbitMQ server port (default: 5672) -
user
: Username for authentication -
password
: Password for authentication -
vhost
: Virtual host to connect to (default: "/") -
automatic_recovery
: Enable automatic connection recovery -
network_recovery_interval
: Time between recovery attempts
Exchange Options
-
type
: Exchange type (default: "x-delayed-message") -
durable
: If true, exchange will survive broker restarts -
auto_delete
: If true, exchange will be deleted when last queue unbinds -
arguments
: Additional exchange arguments
Queue Options
-
durable
: If true, queue will survive broker restarts -
exclusive
: If true, queue can only be consumed by this connection -
auto_delete
: If true, queue will be deleted when last consumer disconnects -
arguments
: Additional queue arguments (e.g., TTL, dead-letter exchange)
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -am 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Create a Pull Request
Troubleshooting
Common Issues
-
Plugin Not Enabled
- Ensure the delayed message plugin is enabled in RabbitMQ
- Run:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
-
Connection Issues
- Verify RabbitMQ server is running
- Check connection credentials
- Verify network connectivity
-
Message Not Received
- Check if exchange exists
- Verify queue bindings
- Check message TTL settings
Debugging Tips
- Enable Bunny logging:
Bunny.logger.level = Logger::DEBUG
- Use RabbitMQ management UI to:
- Monitor exchanges and queues
- Check message delivery
- View connection status
License
The gem is available as open source under the terms of the MIT License.
Support
For support, please:
- Check the documentation
- Search existing issues
- Open a new issue if needed
- For urgent issues, consider professional support options
Security
If you discover a security vulnerability, please contact the maintainers directly instead of opening a public issue. We will work to address the vulnerability as quickly as possible.