Giter Site home page Giter Site logo

eventmill's Introduction

eventmill โ€ƒ

Latest Release Documentation License Rustc Support 1.39+ Build Status

Event sourcing and CQRS for Rust applications

very much work in progress!

[dependencies]
eventmill = "0.4"

to use the derive macros from the eventmill-derive crate activate the derive feature:

[dependencies]
eventmill = { version = "0.4", features = ["derive"] }    

Usage example

Define your domain events:

const EVENT_NAMESPACE: &str = "https://github.com/innoave/eventmill/examples/counter";

#[derive(EventType, Debug, Clone, PartialEq)]
#[event_source(EVENT_NAMESPACE)]
#[event_type_version("V1")]
#[event_type("Incremented")]
struct Incremented;

Define your aggregate:

#[derive(AggregateType, Debug)]
#[id_field(id)]
#[initialize_with_defaults]
struct Counter {
    id: i32,
    hits: u64,
}

Implement the business logic for applying events to the aggregate:

impl Aggregate<Incremented> for Counter {
    fn apply_event(&mut self, _event: &DomainEvent<Incremented, Self>) {
        self.hits += 1;
    }
}

Define a command:

#[derive(Debug, PartialEq)]
struct Increment;

Implement the business logic so that the aggregate is able to handle the command:

impl HandleCommand<Increment, Self> for Counter {
    type Event = Incremented;
    type Error = Infallible;
    type Context = ();

    fn handle_command(
        &self,
        _command: Increment,
        _context: &Self::Context,
    ) -> Result<Vec<NewEvent<Self::Event, Counter>>, Self::Error> {
        Ok(vec![NewEvent {
            aggregate_id: self.id,
            data: Incremented,
        }])
    }
}

Bringing it all together using the Core dispatcher:

fn main() {
    let event_store = InMemoryStore::new();
    let core = Core::new(event_store);

    let aggregate_id = 4711;

    let increment_command = DomainCommand {
        aggregate_id,
        aggregate_generation: Generation::default(),
        data: Increment,
    };

    let versioned_counter: VersionedAggregate<Counter> = core
        .dispatch_command(increment_command, &())
        .expect("counter incremented");

    assert_eq!(versioned_counter.state().hits, 1);
}

These code samples are taken from the counter example. Take a look at eventmill-examples for more insights.

TODO

  • define basic abstractions and API
  • provide a first example on how it looks like to use the API
  • make more examples to polish the API
  • write rust-doc for the API
  • support async/await or switch to async as the only option
  • consider providing default implementations for eventstores and other building blocks
  • ...

eventmill's People

Contributors

haraldmaida avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

tdcare kotlin2018

eventmill's Issues

Plan for Projections?

I'm trying to find out the bounds of this library: to know, if I choose this as basis, what I'll have to implement myself outside of this lib.

Right now, there is no projection in place. Nor do I see any mention of other event-processors (WorkFlows, Reactors, etc) in the code or the readme.

I'm currently in need of an event-source system that projects data into files (KML/GML/XML) and into a database (PostGIS).

Is this planned as part of this library? Or is this deliberately left out of the library and left for the implementer?

If the latter, it might be a good idea to outline some additional requirements (or a sample implementation), so that an implementer has something stable-ish to work against. E.g. a processor might need to implement mutex-locks and/or cursors; whose implementation depends greatly on details such as the ID of-, ordering of-, delivery of- events.

Persistent event storage planned?

Thanks for the great work so far: loving the clean and clear API!

I'm trying to find out the bouds of this library: to know, if I choose this as basis, what I'll have to implement myself outside of this lib.

Right now, there is only a InMemoryStore implementation for events; which is great for a PoC and maybe some use-cases, but I need persistent storage. Anything would do for now: from JsonFilesStorage to PostgresStorage to GetEventSourcedStorage.

Is this planned? Or is this deliberately left out of the library and left for the implementer?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.