cqrs icon indicating copy to clipboard operation
cqrs copied to clipboard

Add BoundedContext abstraction

Open carlos-verdes opened this issue 1 year ago • 1 comments

A single cqrs framework should be able to manage more than one aggregate.

Related with #90

carlos-verdes avatar Aug 30 '24 05:08 carlos-verdes

That's certainly not the design here.

This is probably more of a naming problem since 'framework' implies you might handle multiple aggregates.

davegarred avatar Oct 26 '24 13:10 davegarred

Correct me if I'm wrong but let's say I need to implement a Query that read events from 2 different aggregates, from the documentation the simplest Query example looks like this:

struct SimpleLoggingQuery {}

#[async_trait]
impl Query<BankAccount> for SimpleLoggingQuery {
    async fn dispatch(&self, aggregate_id: &str, events: &[EventEnvelope<BankAccount>]) {
        for event in events {
            println!("{}-{}\n{:#?}", aggregate_id, event.sequence, &event.payload);
        }
    }
}

On this example (and others looks similar) I have to provide one aggregate type only, hence I can't handle events from other one.

One option is to create an enum with all aggregates the query is interested in + implement From trait like this:

enum BankQueryInput {
  case BankAccount(BankAccount),
  case TaxesAggregate(TaxesAggregate),
}

impl From<BankAccount> for BankQueryInput {
  ...
}

This way I could write a Query which is interested on bank account movements and tax events. Let me know if this example has sense to you.

carlos-verdes avatar Nov 06 '24 04:11 carlos-verdes

With two aggregates you'll need two different Query implementations, but these can absolutely work on the same backing store.

davegarred avatar Feb 21 '25 14:02 davegarred

How it can work if 1 store is linked to 1 aggregate? It simply can't right?

carlos-verdes avatar Feb 24 '25 06:02 carlos-verdes

struct BankAccountAggregate;
struct CustomerAggregate;

struct MySharedQuery {}

impl Query<BankAccountAggregate> for MySharedQuery {
   ...
}

impl Query<CustomerAggregate> for MySharedQuery {
   ...
}

davegarred avatar Feb 24 '25 16:02 davegarred

So you will have 2 instances of the same query working in parallel, like creating 2 listeners, 1 per aggregate, then both will write the state on the same table or collection right?

I was thinking on a more simple scenario where the query receives interleaved events from both aggregates, but this approach has sense too as we can't enforce that both aggregates live on the same infrastructure.

carlos-verdes avatar Feb 25 '25 05:02 carlos-verdes

That is not supported, in CQRS terms order of events only makes sense within a single aggregate.

davegarred avatar Feb 25 '25 18:02 davegarred

I still have doubts your example would work with a real example but I'll have a look into it. I created my own library (replay) based on this library but with a different approach.

carlos-verdes avatar Feb 26 '25 06:02 carlos-verdes