0.0
The project is in a healthy, maintained state
A Ruby gem providing the same event-sourcing primitives and in-memory/Postgres stores as the @eventstore-typescript package.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 5.18

Runtime

~> 1.4
 Project Readme

Gem Version

EventStoreRuby

A comprehensive Ruby implementation of event sourcing with real-time event subscriptions and projections. This system provides persistent event storage with automatic notification to subscribers for building responsive, event-sourced applications.

This library is based on the @ricofritzsche/eventstore TypeScript library and it provides the same event-sourcing primitives, including:

  • EventStore implementations
    • EventStoreRuby::MemoryEventStore – fully in-memory (great in tests)
    • EventStoreRuby::PostgresEventStore – persistent, PostgreSQL-backed
  • NotifierMemoryEventStreamNotifier for real-time fan-out of appended events
  • Query engine – powerful payload-predicate matching identical to the original TS implementation
  • Optimistic locking – conditional append with expected_max_sequence_number

Installation

Add to your Gemfile:

gem 'eventstore_ruby', '~> 0.1.1'

or:

$ gem install eventstore_ruby

Quick start (Memory)

require 'eventstore_ruby'

store = EventStoreRuby::MemoryEventStore.new

# Subscribe **before** writing so you get real-time notifications
subscription = store.subscribe do |events|
  puts "got #{events.size} event(s): #{events.map(&:event_type).join(', ')}"
end

# Append events
store.append([
  EventStoreRuby::Event.new(event_type: 'UserRegistered', payload: {user_id: 1}),
  EventStoreRuby::Event.new(event_type: 'EmailVerified',  payload: {user_id: 1})
])

# Historical query
filter  = EventStoreRuby.create_filter(%w[UserRegistered EmailVerified])
result  = store.query(filter)
puts "history has #{result.events.size} events, max seq ##{result.max_sequence_number}"

subscription.unsubscribe

Quick start (PostgreSQL)

# launch Postgres
$ docker run --name eventstore-pg -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres:15
$ export DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres"
require 'eventstore_ruby'

store = EventStoreRuby::PostgresEventStore.new
store.initialize_database # creates table & indexes on first run

# same API as memory store …

API overview

# Building filters
filter = EventStoreRuby.create_filter(%w[UserRegistered], [{user_id: 1}])

# Querying
qr = store.query(filter)        # => QueryResult (events + max_sequence_number)

# Combining multiple filters with OR – EventQuery

Often you need to fetch events that match **any** of several filter criteria.  
Instead of doing multiple round-trips you can combine `EventFilter`s into a single
`EventQuery` (logical OR):

```ruby
# Build individual filters
f_users  = EventStoreRuby.create_filter(['UserRegistered'])
f_orders = EventStoreRuby.create_filter(['OrderPlaced'], [{country: 'DE'}])

# Combine them
query = EventStoreRuby.create_query([f_users, f_orders])

# Works with both query and append
result = store.query(query)

# Conditional write based on the same logical context
store.append(new_events, query, expected_max_sequence_number: result.max_sequence_number)

EventQuery is supported by both the in-memory and PostgreSQL stores. Under the hood it is translated into OR conditions in SQL for Postgres, and on the in-memory store it simply checks each contained filter one after another.

Conditional append (optimistic locking)

store.append(events, filter, expected_max_sequence_number: qr.max_sequence_number)

Subscriptions

sub = store.subscribe do |events| … end sub.unsubscribe


For detailed objects & methods see the YARD docs or the source under `lib/eventstore_ruby/`.

## Development / Tests

```bash
$ bundle install
$ rake test   # runs Minitest suite (ports of all original Jest specs)

License

MIT © 2024 – originally by Ralf Westphal & Rico Fritzsche. Ruby port by Gazpacho Dev team (Manuel Ortega).