Fetch including uncommited during rebuild of projection #3706
-
Hello, I have a "simple" use case but it seems to be impossible to tackle. I have this simple aggregate: // Stars is the global rating over users rates
public record House(Guid Id, string Name, string Address, int NumberOfRooms, decimal? Stars); I have this event: public sealed record UserRate(int Rate); I have also this simple projection with this Apply: public class HouseProjection : SingleStreamProjection<House>
{
// ....
public async Task<House> Apply(UserRate @event, House house, IQuerySession session)
{
// When multiple Apply happens before being commited, this does not work as
// it only read commited from databse
// So, how to include uncommited changes during rebuild ?
var events = await session.Events.FetchStreamAsync(house.Id);
var stars = events
.Where(e => e.EventType == typeof(UserRate))
.Select(e => Convert.ToDecimal(((UserRate)e.Data).Rate))
.Union([Convert.ToDecimal(@event.Rate)]);
return house with
{
Stars = stars.Average(), // So this average does not work when there is more than one UserRate in the transaction
};
}
} This seems to work if there is only one BUTIf I have multiple |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
As i understand what is not working for you is if you append multiple events your projection value will be based on the persisted event + the most recent event? i.e. you do:
However if you do
Is that correctly understood, or is there something else not working? You can make this work in multiple ways however I would probably change the design instead, but here are some options if you are hellbent on this way of doing things or if you encounter another issue where you need access to the events being applied in the current session:
However as mentioned I would simplify this code by storing something like NumberOfRatings and TotalStars and calculate the average based on that so something like:
|
Beta Was this translation helpful? Give feedback.
-
You perfectly understood the issue. So the optimal workaround saoule be to redesign a littéralement bit. That is fair enough to add the number of rates in the aggregate but the issue only happens during rebuild currently. So I was wondering if there was a way and as you mentionned, I could create a custom projection. Thanks a lot. |
Beta Was this translation helpful? Give feedback.
-
@ChristPetitjean Slow down a second first, why are you calling this inside your projection: That's very highly not idiomatic, and in any kind of rebuild or async scenario, that's a giant N+1 you don't want. You'd ideally want your projection to work by incrementally applying changes to the snapshot, but never need to look backwards through the event stream. |
Beta Was this translation helpful? Give feedback.
As i understand what is not working for you is if you append multiple events your projection value will be based on the persisted event + the most recent event?
i.e. you do:
... SaveChanges -> Average = 2
... SaveChanges -> Average = 2.5
... SaveChanges -> Average = 2
However if you do
... SaveChanges -> Average 2
... SaveChanges -> Average 1.5
Is that correctly understood, or is there something else not working?
You can make this work in multiple ways however I would probably change the design instead, but here are some options if you are hellbent on this way of doing things or if you encounter another issue whe…