Class: Sourced::Projector::EventSourced

Inherits:
Sourced::Projector show all
Defined in:
lib/sourced/projector.rb

Overview

An EventSourced projector fetches initial state from past events in the event store. And then after reacting to events and updating state, it can save it to a DB table, a file, etc.

Examples:


class CartListings < Sourced::Projector::EventSourced
  # Initial in-memory state
  def init_state(id)
    { id:, total: 0 }
  end

  # Evolve listing record from events
  evolve Carts::ItemAdded do |listing, event|
    listing[:total] += event.payload.price
  end

  # Sync listing record to a file
  sync do |listing, _, _|
    File.write("/listings/#{listing[:id]}.json", JSON.dump(listing)) 
  end
end

Constant Summary

Constants included from Sync

Sync::CallableInterface

Constants included from Evolve

Evolve::NOOP_HANDLER, Evolve::PREFIX

Instance Attribute Summary

Attributes inherited from Sourced::Projector

#id, #seq, #state

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Sourced::Projector

#handle_events, handled_events, #initialize, #inspect

Methods included from Consumer

#consumer, #consumer_info

Methods included from Sync

included, #run_sync_blocks

Methods included from Evolve

#evolve, included

Constructor Details

This class inherits a constructor from Sourced::Projector

Class Method Details

.handle_events(events) ⇒ Object



104
105
106
107
108
109
# File 'lib/sourced/projector.rb', line 104

def handle_events(events)
  # The current state already includes
  # the new events, so we need to load upto events.first.seq
  instance = load(events.first.stream_id, upto: events.first.seq - 1)
  instance.handle_events(events)
end

.load(stream_id, upto: nil) ⇒ Sourced::Projector::EventSourced

Load from event history

Parameters:

  • stream_id (String)

    the stream id

Returns:



115
116
117
# File 'lib/sourced/projector.rb', line 115

def load(stream_id, upto: nil)
  new(stream_id).load(upto:)
end

Instance Method Details

#load(after: nil, upto: nil) ⇒ Object

TODO: this is also in Decider. DRY up?



121
122
123
124
125
126
127
128
# File 'lib/sourced/projector.rb', line 121

def load(after: nil, upto: nil)
  events = backend.read_event_stream(id, after:, upto:)
  if events.any?
    @seq = events.last.seq 
    evolve(state, events)
  end
  self
end