timesource 0.1.3

Event sourcing with TimescaleDb
Documentation
#![allow(dead_code)]

use chrono::{DateTime, Utc};
use minicbor::{Decode, Encode};
use thiserror::Error;
use timesource::{Aggregate, TimesourceEvent};
use uuid::Uuid;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UserState {
    pub name: Option<String>,
    pub surname: Option<String>,
}

#[derive(Debug)]
pub enum UserCommand {
    Create,
    SetName {
        name: String,
        surname: Option<String>,
    },
}

#[derive(Debug, Clone, PartialEq, Eq, TimesourceEvent, Decode, Encode)]
#[timesource(encoding = "cbor")]
pub enum UserEvent {
    #[b(0)]
    Created,
    #[b(1)]
    NameChanged {
        #[b(0)]
        name: String,
        #[b(2)]
        surname: Option<String>,
    },
}

#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum UserError {
    #[error("Already created")]
    AlreadyCreated,
    #[error("Not yet created")]
    NotYetCreated,
}

#[derive(Debug, Default, Clone, Copy)]
pub struct UserAggregate;

impl Aggregate for UserAggregate {
    type State = UserState;
    type Event = UserEvent;
    type Command = UserCommand;
    type Error = UserError;

    fn apply_first(
        _: Uuid,
        event: &Self::Event,
        _: DateTime<Utc>,
        _event_id: Option<u64>,
    ) -> Result<Self::State, Self::Error> {
        if let UserEvent::Created = event {
            return Ok(UserState {
                name: None,
                surname: None,
            });
        }

        Err(UserError::NotYetCreated)
    }

    fn apply_next(
        state: &mut Self::State,
        event: &Self::Event,
        _: DateTime<Utc>,
        _event_id: Option<u64>,
    ) -> Result<(), Self::Error> {
        match event {
            UserEvent::Created { .. } => Err(UserError::AlreadyCreated),

            UserEvent::NameChanged { name, surname } => {
                state.name = Some(name.clone());
                state.surname = surname.clone();

                Ok(())
            }
        }
    }

    fn handle_first(command: Self::Command) -> Result<Vec<Self::Event>, Self::Error> {
        if let UserCommand::Create = command {
            return Ok(vec![UserEvent::Created]);
        }

        Err(UserError::NotYetCreated)
    }

    fn handle_next(
        _state: &Self::State,
        command: Self::Command,
    ) -> Result<Vec<Self::Event>, Self::Error> {
        match command {
            UserCommand::Create => Err(UserError::AlreadyCreated),
            UserCommand::SetName { name, surname } => {
                Ok(vec![UserEvent::NameChanged { name, surname }])
            }
        }
    }
}