Crate chekov

source ·
Expand description

Chekov is a CQRS/ES Framework built on top of Actix actor framework.

Getting started

Installation

chekov = "0.1"

Chekov is using [::event_store] in background to interact with backend.

Application

Chekov is using Application as a way to separate usecases. You can defined multiple applications on the same runtime which can be useful to synchronise multiple domains.

But first, let’s define our first Application:

#[derive(Default)]
struct DefaultApp {}

// Application trait is here to preconfigure your chekov runtime.
// It tells that you want this `Application` to use a PostgresStorage.
impl chekov::Application for DefaultApp {
    type Storage = chekov::prelude::PostgresStorage;
}

If you want to know more about Application check the module documentation.

Defining our first Aggregate

One can create an aggregate that will be able to hold a state and execute commands on demand. Each Aggregate is unique and can’t be duplicated meaning that you can’t have the same aggregate instance running twice.

#[derive(chekov::Aggregate, Default, Clone)]
#[aggregate(identity = "user")]
struct User {
    user_id: uuid::Uuid,
    name: String
}

If you want to know more about aggregate check the module documentation.

Creating our first Event

An Aggregate produces events based on command execution. Defining an Event is pretty straightforward.

#[derive(Clone, chekov::Event, Deserialize, Serialize)]
struct UserCreated{}

#[derive(Clone, chekov::Event, Deserialize, Serialize)]
enum UserUpdated {
    NamedChanged(uuid::Uuid, String, String),
    Disabled {
        reason: String
    }
}

If you want to know more about Event check the module documentation.

Defining our first Command

The purpose of a command is to been executed on an Aggregate (or a CommandHandler but we will see that later). Each commands need to provide some basic information on how to deal with them. But let’s keep that simple for now:


#[derive(Clone, Debug, chekov::Command, Serialize, Deserialize)]
#[command(event = "UserCreated", aggregate = "User", handler = "UserValidator")]
struct CreateUser {
    #[command(identifier)]
    pub user_id: Uuid,
    pub name: String,
}

#[derive(Clone, Debug, chekov::Command, Serialize, Deserialize)]
#[command(event = "UserUpdated", aggregate = "User")]
struct UpdateUser {
    #[command(identifier)]
    pub user_id: Uuid,
    pub name: String,
}

Modules

Structs

Traits

  • Define an Aggregate
  • Application are high order logical seperator.
  • Define a Command which can be dispatch
  • Receives a command and an immutable Executor and optionally returns events
  • Define an Event which can be produced and consumed
  • Define an event applier
  • Define a struct as an EventHandler

Attribute Macros

Derive Macros