README.md in tobox-0.2.0 vs README.md in tobox-0.3.0
- old
+ new
@@ -13,10 +13,11 @@
- [Usage](#usage)
- [Configuration](#configuration)
- [Event](#event)
- [Features](#features)
- [Ordered event processing](#ordered-event-processing)
+ - [Inbox](#inbox)
- [Plugins](#plugins)
- [Zeitwerk](#zeitwerk)
- [Sentry](#sentry)
- [Datadog](#datadog)
- [Supported Rubies](#supported-rubies)
@@ -297,10 +298,18 @@
### group_column
Defines the column to be used for event grouping, when [ordered processing of events is a requirement](#ordered-event-processing).
+### inbox table
+
+Defines the name of the table to be used for inbox, when [inbox usage is a requirement](#inbox).
+
+### inbox column
+
+Defines the column in the outbox table which references the inbox table, when one is set.
+
<a id="markdown-event" name="event"></a>
## Event
The event is composed of the following properties:
@@ -359,9 +368,62 @@
end
# "order_created" will be processed first
# "billing_event_created" will only start processing once "order_created" finishes
```
+<a id="inbox" name="inbox"></a>
+### Inbox
+
+`tobox` also supports the [inbox pattern](https://event-driven.io/en/outbox_inbox_patterns_and_delivery_guarantees_explained/), to ensure "exactly-once" processing of events. This is achieved by "tagging" events with a unique identifier, and registering them in the inbox before processing (and if they're there, ignoring it altogether).
+
+In order to do so, you'll have to:
+
+1. add an "inbox" table in the database
+
+```ruby
+create_table(:inbox) do
+ column :inbox_id, :varchar, null: true, primary_key: true # it can also be a uuid, you decide
+ column :created_at, "timestamp without time zone", null: false, default: Sequel::CURRENT_TIMESTAMP
+end
+```
+
+2. add the unique id reference in the outbox table:
+
+```ruby
+create_table(:outbox) do
+ primary_key :id
+ column :type, :varchar, null: false
+ column :inbox_id, :varchar, null: true
+ # ...
+ foreign_key :inbox_id, :inbox
+```
+
+3. reference them in the configuration
+
+```ruby
+# tobox.rb
+inbox_table :inbox
+inbox_column :inbox_id
+```
+
+4. insert related outbox events with an inbox id
+
+```ruby
+order = Order.new(
+ item_id: item.id,
+ price: 20_20,
+ currency: "EUR"
+)
+DB.transaction do
+ order.save
+ DB[:outbox].insert(event_type: "order_created", inbox_id: "ord_crt_#{order.id}", data_after: order.to_hash)
+ DB[:outbox].insert(event_type: "billing_event_started", inbox_id: "bil_evt_std_#{order.id}", data_after: order.to_hash)
+end
+
+# assuming this bit above runs two times in two separate workers, each will be processed by tobox only once.
+```
+
+**NOTE**: make sure you keep cleaning the inbox periodically from older messages, once there's no more danger of receiving them again.
<a id="markdown-plugins" name="plugins"></a>
## Plugins
`tobox` ships with a very simple plugin system. (TODO: add docs).