Code Monkey home page Code Monkey logo

thefabric-io / eventsourcing Goto Github PK

View Code? Open in Web Editor NEW
26.0 26.0 2.0 54 KB

An efficient and robust Event Sourcing library for Go, designed for scalability and ease of use. Tailored for PostgreSQL, this library provides essential functionalities for storing and retrieving a sequence of events as the source of truth for the state of your application's aggregates. ๐Ÿš€

License: MIT License

Go 100.00%
aggregate data-modeling ddd event-sourcing events eventstore go-generics golang postgresql state-management

eventsourcing's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eventsourcing's Issues

Proposal: Introducing StorageNamer Interface for Customizable Storage Entity Naming in Aggregates

Right now, we're tying aggregates to their storage based on the aggregate state type, like so:

// Type returns the type of the aggregate.
func (a *Aggregate[S]) Type() string {
    return a._type
}

This works, but I'm thinking we can do better, especially as we scale up. So, here's what I'm proposing: a StorageNamer interface.

type StorageNamer interface {
    StorageName() string
}

This interface aims to provide a more explicit and customizable way for aggregates to define their corresponding storage entities (like database tables or collections). It could significantly improve the way the library handles storage naming conventions, making it more adaptable to different storage backends and user needs.

The implementation of this interface would be optional. If an aggregate state does not implement StorageNamer, the library would default to using the aggregate state's type as the storage identifier.

Add Examples

First, thank you for sharing this work. Generics seem like a great use case here and I appreciate you sharing your work.

And, I think adding examples will go a long way toward helping others realize value from the work you have shared. I myself am finding some trouble getting my Events to work as I expect. If I could reference an example it would help me ensure I'm setting up my function signatures correctly.

Thank you.

Adjust the Order of Event Application to Capture Latest State Changes

I've noticed a potential area for enhancement in our event application logic that could improve the accuracy and reliability of our domain model's state evolution. Specifically, I propose we adjust the order of operations in the Apply method of our event handling to apply modification and inception recorders after the event has been applied to the aggregate. This change aims to ensure that recorders capture the most up-to-date state of the aggregate.

Current Implementation:

In our current implementation, the Apply method in our event structure performs several operations in the following order:

  1. Increment the aggregate version.
  2. Append the event to the list of changes.
  3. Set the aggregate ID from the event state if applicable.
  4. Record inception and modification dates if the event state implements InceptionRecorder or ModificationRecorder.
  5. Merge event metadata into aggregate metadata.
  6. Apply the state changes from the event to the aggregate.
  7. Clone the aggregate and set it on the event.

Here's the relevant code snippet for context:

func (e *Event[S]) Apply(aggregate *Aggregate[S]) {
    // Initial setup and state capture...
    
    if v, ok := e.State().(InceptionRecorder[S]); ok {
        v.RecordInception(&e.occurredAt, aggregate)
    }

    if v, ok := e.State().(ModificationRecorder[S]); ok {
        v.RecordModification(&e.occurredAt, aggregate)
    }
    
    // Applying state changes...
    e.State().Apply(aggregate)

    // Post-application steps...
}

Proposed Change:

I suggest we modify the sequence to apply the event to the aggregate before executing the inception and modification recorders. This adjustment ensures that any transformations to the aggregate's state, including additions of new value objects or other modifications, are fully reflected before we capture their inception or modification timestamps.

func (e *Event[S]) Apply(aggregate *Aggregate[S]) {
    // Initial setup...
    
    // First, apply state changes to ensure the latest state is captured
    e.State().Apply(aggregate)
    
    // Then, record inception and modifications with the updated state
    if v, ok := e.State().(InceptionRecorder[S]); ok {
        v.RecordInception(&e.occurredAt, aggregate)
    }

    if v, ok := e.State().(ModificationRecorder[S]); ok {
        v.RecordModification(&e.occurredAt, aggregate)
    }
    
    // Final steps...
}

Benefits:

  • Flexibility: It allows for a more nuanced handling of state changes, particularly for cases where the exact moment of state modification is critical (e.g., when an occurredAt date must be applied to a newly added value object from the aggregate).

I believe this adjustment will provide a more robust foundation for our event sourcing system, capturing state changes more accurately and flexibly. I welcome feedback on this proposal, including any concerns or additional benefits I may not have considered.

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.