Closed sancho20021 closed 1 year ago
Hi @sancho20021, for any feedback you'll want to use a query, this is a very simple one to configure. The most basic setup would be to use a GenericQuery
to serialize a view with this list.
struct ExistingAggregatesView {
aggregate_ids: Vec<String>
}
impl View<MyAggregate> for ExistingAggregatesView {
fn update(&mut self, event: &EventEnvelope<MyAggregate>) {
self.aggregate_ids.push(event.aggregate_id);
}
}
This obviously only works with small number of aggregates. For a production system you'd probably want to use a database table with a single aggregate_id
column and create a custom query.
struct ExistingAggregatesQuery {
database_client: DatabaseClient,
}
#[async_trait]
impl Query<MyAggregate> for ExistingAggregatesQuery {
async fn dispatch(&self, aggregate_id: &str, events: &[EventEnvelope<MyAggregate>]) {
for event in events {
self.database_client.execute("INSERT INTO aggregate_id_table VALUES (?)", event.aggregate_id);
}
}
}
Thank you. Will I be able to access these queries /views inside the handle
of a command
?
Accessing the view from within the aggregate is accomplished in a similar fashion by configuring your aggregate's Services
associated type.
For the latter example this might look like:
struct MyServices {
db_client: Box<dyn AbstractDatabaseClient>,
}
Note the database client should be a boxed dynamic type since you'll need to swap it out with a mock client in your tests.
This client is then available within the handle
method of your aggregate.
Take a look at our services example in the demo application for a complete example (client test implementation is here).
Hi @sancho20021, for any feedback you'll want to use a query, this is a very simple one to configure. The most basic setup would be to use a
GenericQuery
to serialize a view with this list.struct ExistingAggregatesView { aggregate_ids: Vec<String> } impl View<MyAggregate> for ExistingAggregatesView { fn update(&mut self, event: &EventEnvelope<MyAggregate>) { self.aggregate_ids.push(event.aggregate_id); } }
Okay, but how can I create a Query which will use this View in memory, without any ViewRepository
?
https://doc.rust-cqrs.org/application_persisted_views.html in the tutorial they wrap similar view in a PostgresViewRepository, but I would like to have an in-memory query which I would use in handling requests for my server.
Okay, but how can I create a Query which will use this View in memory, without any
ViewRepository
?https://doc.rust-cqrs.org/application_persisted_views.html in the tutorial they wrap similar view in a PostgresViewRepository, but I would like to have an in-memory query which I would use in handling requests for my server.
See the SimpleLoggingQuery
example in our demo application. Something similar can be used to accept new events and persist information in memory.
If I understand correctly, implementations of Store are intended to return Default::default() in case the aggregate is not found. Sometimes in handling commands (say, extending someones fitness club card, where card is an aggregate) you have to check for the entity existence.
Workaround: make the aggregate an enum with two variants to simulate
Option
.The case where this is needed seems very common, so I would suggest to modify the framework to satisfy these needs. But I have almost no experience in ES/CQRS, so I may be missing something.