Docs / ArchitectureKit / Guides / Stepping Through States

Stepping Through States

Sometimes the states before and after an event are needed, not only the latest one, for example for a history that tells what each event changed. To advance a state by a single stored event, call the StepStored function with the state, the state so far, and the event. It runs the upcasters and the Evolve rules exactly as reading from the database does, and returns the next state:

books := map[string]Book{}

projection := architecturekit.ProjectionFunc(func(ctx context.Context, event eventsourcingdb.Event) error {
  before := books[event.Subject]

  after, err := architecturekit.StepStored(bookState, before, event)
  if err != nil {
    return err
  }

  if !before.IsBorrowed && after.IsBorrowed {
    // The book was borrowed by this event.
  }

  books[event.Subject] = after
  return nil
})

For typed events, for example in a test, call the Step function instead.

The given state stays unchanged, so both states are at hand afterwards. For a state that holds slices, maps or pointers, that takes a Clone function (see Caching States). Without one, Step and StepStored return an error of the category ErrPermanent, rather than a next state that may share data with the one before. A state that consists of values only needs no Clone function.

Note that a stored event that the upcasters turn into several events is applied in full, and that FromLatest has no effect on a single step.