Outboxer is an implementation of the transactional outbox pattern for Ruby on Rails applications.
It helps you migrate to event-driven architecture with at least once delivery guarantees.
1. Install gem
bundle add outboxer bundle install2. Generate schema migrations, publisher script and tests
bundle exec rails g outboxer:install3. Migrate database
bundle exec rails db:migrate4. Generate event schema and model
bundle exec rails generate model Event type:string created_at:datetime --skip-timestamps bundle exec rails db:migrate5. Queue outboxer message after event created
# app/models/event.rb class Event < ApplicationRecord after_create do |event| Outboxer::Message.queue(messageable: event) end end6. Derive event type
# app/models/accountify/invoice_raised_event.rb module Accountify class InvoiceRaisedEvent < Event; end end7. Create derived event type
bundle exec rails cActiveRecord::Base.logger = Logger.new(STDOUT) Accountify::InvoiceRaisedEvent.create!(created_at: Time.current)8. Observe transactional consistency
TRANSACTION (0.2ms) BEGIN Event Create (0.4ms) INSERT INTO "events" ... Outboxer::Message Create (0.3ms) INSERT INTO "outboxer_messages" ... TRANSACTION (0.2ms) COMMIT 8. Publish outboxer messages
# bin/outboxer_publisher Outboxer::Publisher.publish_message do |publisher, message| # TODO: publish message here endTo integrate with Active Cable, Sidekiq, Bunny, Kafka, AWS SQS and others, see the publisher integration guide.
To ensure you have end to end coverage:
bundle exec rspec spec/bin/outboxer_publisher
Monitor using the built-in web UI:
Rails
# config/routes.rb require 'outboxer/web' mount Outboxer::Web, at: '/outboxer'Rack
# config.ru require 'outboxer/web' map '/outboxer' { run Outboxer::Web }All contributions are welcome!
Open-sourced under LGPL v3.0.