Replies: 8 comments
-
There is no built-in snapshotting at the moment. It should be possible to handle this with existing functionality. There are at least two approaches:
What you would probably need is a custom AggregateRoot::Repository. In
Here snapshots are stored and loaded from same stream as events. POC for an older RES: https://gist.github.com/mpraglowski/e3c57aa3407445c8b612d863b836cf5b My personal experience with snapshots so far was that they're good short-term remedy. They may hide or defer issues that could be solved with a better aggregate design. In my case that was two small aggregates (both with <10 events per stream) in place of one big (up to 1000 events in stream) to model same functionality. |
Beta Was this translation helpful? Give feedback.
-
Thank you for the detailed response @pawelpacana. To add more context, I am planning to be using this with a sort of "digital wallet", where I have many add/remove amount events to calculate the wallet's balance. How would I slim that down to different aggregates if I have many transactions in a usecase where I need to get the current wallet balance? I'm still new to event sourcing and I am wondering how to handle something like this, because we do expect a lot of transactions on these wallets. |
Beta Was this translation helpful? Give feedback.
-
Making the aggregates right when it comes to size of data/events and responsibilities is crucial to a good design. In short, you want to have the smallest possible amount of data in the aggregate that is needed to make the decision whether a change is possible or not. This is different that with ActiveRecord-driven design. When you use event sourcing, you usually have an aggregate event sourced. The events are in a stream dedicated to that aggregate.
There's some chance that what you need is just a read model to calculate that. Is the balance then used to make some further decisions? What is it used for? |
Beta Was this translation helpful? Give feedback.
-
@andrzejkrzywda So there's a lot of business logic behind the balance; which is actually different types of balances (e.g. balance that you got from a cashback, and then needing to show reports with percentages with which cashback was used, and so on). I was thinking of having an aggregate per user per balance type (e.g. permanent balance and cashback balance). The balance will also frequently be added to or deducted for transactions. That's obviously going to grow a lot overtime and snapshotting seemed like a solution to avoid having to replay too many events. Is a read model considered a better solution than snapshotting? Also a read model still has to replay all events, no? Thanks so much for the help! |
Beta Was this translation helpful? Give feedback.
-
@obahareth Just to confirm on the original question - yes, it's easy to do snapshots with RailsEventStore, the trick to follow the code here: https://gist.github.com/mpraglowski/e3c57aa3407445c8b612d863b836cf5b However, as was pointed out by @pawelpacana - but let me be opinionated here too. If you need snapshots, then the high-level design went wrong. There's rarely a need to have aggregates with more than 100 events. Usually the problem is having an aggregate (and a stream) around a wrong concept. Getting back to your example - I'd love to learn more about this specific need. In one of my app, I thought I needed an Account aggregate to keep balance. But in fact, it wasn't needed and we removed that code. Aggregates are different beasts than read models or projections. Aggregates are about making decisions - can this payment be initiated? Then maybe Payment is an aggregate? In my experience it's best when aggregates are event-sourced on the fly. Read models are all about displaying infomations. For example if a wallet is a balance based on all payments, then we build a read model on that. Now, read models can have different persistence mechanisms. If the number of events is big, then you don't go for event sourcing on the fly. Instead you store the last result and always update the last when a new event arrives. You can just use ActiveRecord for that. It does sound to me, like what you need is read models. Especially, when you say that it's for reports. Reports are read models. Obviously, you do need aggregates too, most likely. But they don't need to match read models 1-1. I'm sorry if I'm making it sound too complex. It's actually simple, but very different than the normal Rails-way Actice-Record design. Feel free to ask more or explain your example in more details - I hope I will be able to help. |
Beta Was this translation helpful? Give feedback.
-
My question has been answered very thoroughly and I've received a lot of help, thanks! Closing this issue. |
Beta Was this translation helpful? Give feedback.
-
For the reference, the third possible solution could be having separate stream for snapshots from given stream. For example, for stream |
Beta Was this translation helpful? Give feedback.
-
...and apply later events in |
Beta Was this translation helpful? Give feedback.
-
Is there any way to do snapshotting in this library? If not, is there a recommended way that a user of the library handles this themselves? I am evaluating a number of different libraries and this is a feature that's necessary for us.
For reference, I mean something like this feature from Sequent:
https://www.sequent.io/docs/concepts/snapshotting.html
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions