DCB-compatible event store library in Ruby with support for PostgreSQL.
En57 owns its PostgreSQL schema and tracks the installed schema version in
the database. Add the rake tasks to your application's Rakefile:
require "en57/tasks"Then install or update the schema with DATABASE_URL:
DATABASE_URL=postgres://localhost:5432/en57 bundle exec rake en57:migrateTo inspect the current schema status without applying changes:
DATABASE_URL=postgres://localhost:5432/en57 bundle exec rake en57:statusRun en57:migrate before using the event store for the first time.
Use EventStore.for_pg when En57 should own a pg connection.
event_store = En57::EventStore.for_pg("postgres://localhost:5432/en57")Use EventStore.for_sequel when your app already owns a Sequel database.
database = Sequel.connect("postgres://localhost:5432/en57")
event_store = En57::EventStore.for_sequel(database)Use EventStore.for_active_record when your app uses ActiveRecord.
ActiveRecord::Base.establish_connection("postgres://localhost:5432/en57")
event_store = En57::EventStore.for_active_recordevent_store.append(
[
En57::Event.new(
type: "OrderPlaced",
data: { amount: 100 },
tags: ["order_id:123", "customer:42"],
),
],
)events = event_store.read.each.to_aevent, position = event_store.read.each_with_position.firstevents = event_store.read.with_tag("order_id:123", "customer:42").each.to_aevents = event_store.read.after(42).each.to_aorders = event_store.read.of_type("OrderPlaced").with_tag("order_id:123")
price_changes = event_store.read.of_type("PriceChanged")
events = (orders | price_changes).each.to_aExample: consume credits only once per account.
account_scope = event_store.read.with_tag("account:x")
begin
event_store.append(
[
En57::Event.new(
type: "CreditsUsed",
data: { amount: 100 },
tags: ["account:x"],
),
],
fail_if: account_scope.of_type("CreditsUsed"),
)
rescue En57::AppendConditionViolated
# lost the race; another writer already consumed credits
endTo ignore events at or before a known position, scope the fail_if condition
with after.
last_read_event_position = 42
event_store.append(
[En57::Event.new(type: "CreditsUsed", tags: ["account:x"])],
fail_if: event_store.read.of_type("CreditsUsed").after(last_read_event_position),
)Example: ensure no event exists with this email tag before writing.
email_tag = "email:alice@example.com"
begin
event_store.append(
[
En57::Event.new(
type: "UserRegistered",
data: { name: "Alice" },
tags: [email_tag],
),
],
fail_if: event_store.read.with_tag(email_tag),
)
rescue En57::AppendConditionViolated
# email already used
end