Book Of Eventicle

Intro

Eventicle is an opinionated library for building distributed event based NodeJS applications.

It uses Domain Driven Design principles, and lets you build systems that use technologies like Kafka natively.

Quick Start

This sets up an in memory event driven system that can later be run on Kafka, Redis and Postgres.

Install
yarn add @eventicle/eventiclejs
Configure Eventicle
import {
  setEventSourceName,
  eventClientOnDatastore,
  InMemoryDatastore,
  setDataStore,
  setEventClient, eventClient, EventicleEvent
} from '@eventicle/eventiclejs';


  setEventSourceName('my-cool-service');

// in service data storage abstraction. Used by the internals of eventicle, can also be used in app code
  setDataStore(new InMemoryDatastore());

// The connection to the event transport, this is in memory and stores events and state in the current datastore
  setEventClient(eventClientOnDatastore());
Observe an event

Treat an event stream as a simple Topic, do not request any historical data.

  eventClient().hotStream("app.streamname", "my-consumer", async (event: EventicleEvent) => {
    console.log("An event of type " + event.type)
    console.log(event)
  }, error => {
    console.log("An error occurred");
    console.log(error)
  })
Emit an event

Emit an event to a stream, all following Eventicle event machinery is built on this

  // raw event client. Used mainly for special case external integration
  await eventClient().emit([
    {
      type: "user.created",
      data: { (1)
        userName: "Personal Person"
      }
    }
  ], "app.streamname")
1 The event payload
Fully replay an event stream

This starts at the beginning of stream app.streamname, and will receive all historical events, then finish. _Mostly used for offline, batch or automation actions, such as a view upgrade or full stream schema update

  await eventClient().coldStream("app.streamname", async (event: EventicleEvent) => {
    console.log("An event of type " + event.type)
    console.log(event)
  }, error => {
    console.log("An error occurred");
    console.log(error)
  }, () => console.log("Event stream has fully replayed"))
Fully replay an event stream and continue to observe

This starts at the beginning of stream app.streamname, and will receive all historical events. It will then continue to observe the stream. Used for most runtime stream consumption

  await eventClient().coldStream("app.streamname", async (event: EventicleEvent) => {
    console.log("An event of type " + event.type)
    console.log(event)
  }, error => {
    console.log("An error occurred");
    console.log(error)
  }, () => console.log("Event stream has fully replayed"))

Next …​

Now you’ve seen the basics of an event based system, the creation and observation of events, you can start to add in more conceptual pieces.

  • Views, a way to process streams of events into data structures that can be queried efficiently.

  • Aggregate Roots, components that store state, generate events, and enforce rules about how they relate to each other. Often, implemented as a formal state machine using XState.

  • Commands, components that record changes to the system by taking events and emitting them to streams.

  • Sagas, event driven workflows. Implementing asynchronous business logic and integration with external systems in a way that safely isolates them from your core application logic.