Closed nanderstabel closed 7 months ago
Hi @nanderstabel,
Thanks for using the package and the feedback.
Just to be clear, I believe we are talking about loading a view using something other than aggregate ID, and not about loading the aggregate. The latter is something you should never need to do while the former is something that you absolutely need in nearly any real world application.
This is a known limitation of the current ViewRepository
. One that I'm not happy about but I have not yet found a clean way to extend this functionality while still keeping the package lightweight (or maybe it is time to change our tenets).
For internal applications we have built custom read-only repositories as their construction is rather trivial with the databases supported and, for that matter, they would be implemented that way in most other applications anyway.
Thank you!
Yeah you're right I was confusing view and aggregate ID. In the mean time we got what we wanted just by using a second set of:
ViewRepository
--> MemRepository<EmailView, Account>
impl View<Account> for EmailView
, where EmailView
only has one single field: account_id
Query
--> copies most of the GenericQuery
implementations, but overwrites the loaded view_context.view_instance_id
with the email address corresponding to the account.This way every time a new account is created, not only the AccountView
gets updated, but the EmailView
as well.
So in the previous example we are now doing something like this:
pub async fn query_handler(
Path(email): Path<String>,
State(state): State<ApplicationState>,
) -> Response {
// Retrieve the account_id using the email
let account_id = match state.email_query.load(&email).await {
Ok(view) => view.account_id,
Err(err) => {
println!("Error: {:#?}\n", err);
return (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response();
}
};
// Now the full account view can be retrieved using the account_id
let view = match state.account_query.load(&account_id).await {
Ok(view) => view,
Err(err) => {
println!("Error: {:#?}\n", err);
return (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response();
}
};
match view {
None => StatusCode::NOT_FOUND.into_response(),
Some(account_view) => (StatusCode::OK, Json(account_view)).into_response(),
}
}
Thanks for building this crate!
If you have nothing else to add please feel free to close this issue :)
My team is happily utilizing this crate, however, we're a bit stuck at the moment with the following:
It seems like aggregate instances can only be retrieved from the store by their aggregate IDs(?). For example, if I have a
BankAccount
Aggregate
:Then I can indeed the specific
BankAccount
instance usingaccount_id
(from https://github.com/serverlesstechnology/cqrs-demo/blob/main/src/route_handler.rs#L11-L26):But in some situations I might not have access to the
account_id
, but I still want to be able to find theBankAccount
instance that I need, for example using an email address:So my main question is, what is the intended way of implementing a way to retrieve an
Aggregate
instance not by its ID, but rather by something else (email or something else)?Else would it make sense to add a find/search method to the
ViewRepository
trait? If so, I would be more than happy to contribute this.