What about event sourcing?

00:05.38
Chris Morrell
All right welcome back to another episode of overengineered the podcast where we ask the very important question. What's the absolute best way to do things that don't particularly matter. Ah today I am back with my friend skyler and Bogg did and ah we're here to talk about.

00:23.86
Skyler Katz
Hello hello.

00:24.21
Chris Morrell
Event sourcing welcome back guys.

00:25.25
Bogdan Kharchenko
Hello hello this is the most exciting thing I've been thinking about the whole week and I'm just kidding. It is a interesting topic and I'm looking forward to speaking about it for sure, especially after hearing the conversation you've had with Daniel at the last podcast I think it eras some eyebrows.

00:32.54
Chris Morrell
Ah, well.

00:44.74
Bogdan Kharchenko
Kind of an interesting conversation to have.

00:48.22
Chris Morrell
For sure. Yeah I mean it's definitely it's it's back in the air between us talking about it and him talking about it on no plans to merge and just ah I don't know it coming up a couple times for us I am excited um, and so i. I was saying before we started I think just to set the stage. Let's like have a quick conversation about what exactly event sourcing is and how event sourcing um works in the like Pg p lairvell world or how we've used event sourcing and then um, we'll go from there. So ah, I'll just sort of start and you two pepper me with questions when I get something when I miss something or get something wrong and we'll go from there. Um, so event sourcing is.

01:33.98
Bogdan Kharchenko
Sounds good.

01:40.41
Chris Morrell
Basically this premise that instead of just updating models in your database you store the events that happen in your application and ah trigger and use those events to to change the state of your application. Um.

02:00.31
Chris Morrell
I think the way that Daniel described it in the last podcast is really a nice analogy like we as object-oriented programmers deal with nouns for the most part and event sourcing is effectively thinking in verbs and there are lots of times. When we're dealing with verbs and we're trying to model them as nouns I think that's like such a great way to talk about it. Um, and so in an event sourced application instead of just ah, changing a user record right? You might store a user. Updated profile event and then have that event store all the changed data on that event and then use that data to update your user records. Um, and it's usually talked about. In the context of stuff like banking or financial systems anything where you kind of already have this concept of a ledger It's really easy to draw the analogy. But I think that in a lot of places. Um, we deal with. Stuff that happens that has an effect and um, we lose a lot of the context of the stuff that happens and we try to make up for it with audit logs or other packages that kind of are tracking history or using things like status columns see the previous.

03:31.15
Chris Morrell
Episode Um, and you know when when we get into those places where we're trying to fake having this historical data. Um, that's a good pointer for maybe we need event sourcing or maybe we want to consider event sourcing. Um.

03:50.33
Chris Morrell
And I want to get into the like sort of the language around it in a minute but this conversation kind of came up because we've used event sourcing for a couple of things inside of our apps and Echy. Um, and it's been really useful and I think talking about it again. Got me personally fired up. Thinking. Ah, there are a couple other places that it really would be a good fit but like I was saying on the the previous podcast I Do think that it it comes with some ah you know it comes with some tradeoffs certainly in a.

04:29.30
Chris Morrell
Layerrave app that usually works 1 very specific way or like follows the typical layer Ofville conventions if all of a sudden you're doing everything with events and so I was I'm kind of thinking of this both as an opportunity to just talk about event sourcing and and think about. Ah, when it's useful and also just sort of to have our little debate about whether we want to embrace event sourcing a little bit more within our apps. Um, so that's kind of that's kind of the the backstory and the basic premise. Um, and then I think. I do want to get into sort of some of these terms. Ah so that we're all sort of on the same page but is there anything that I missed before we get to the to the actual like vocabulary.

05:18.25
Skyler Katz
I Don't think so I think that's I think that's a good, a good overview.

05:26.62
Bogdan Kharchenko
Yeah I am looking forward to here all the vocabulary definitions I feel like we need to have a disclaimer for the audience at least for me I am not an event source expert and I would love to learn some of these. Ah. Ah, you know definitions of the verbs and the things that we're going to talk about so I'm looking forward as much as you are to hearing all about this. So with that Chris teach us some so.

05:50.65
Chris Morrell
All right so all right I'm going to try to keep this as brief as possible while while covering the the bases. Um right? So the the core thing is events right? We've got events. Um, and we have some sort of dispatcher that fires events and you know for the for we have been using the spotsy package the spotsy event sourcing package. There's also event sauce which is a very popular php event sourcing package. Um, but you know for the listener at home. Just the regular laravell event dispatcher can do a lot of this stuff and um, there's nothing stopping you from implementing something that uses ah the concepts of event sourcing without using a formal event sourcing package so we've got events. That we dispatch. Um an important thing about those events is they need to be stored somewhere right? So we' so we're storing them in a mysql database I think for a lot of laravel developers. That's perfectly fine. Um, I just checked and we're at about 12000000 events in our events table and it is perfectly performant. There's no issues with querying that data. Um, kind of because of the way because of the access patterns that you have around events.

07:15.11
Chris Morrell
You're as long as you're indexing them Properly. You're never going to have to do these complex queries on that table. So. It's really just pulling them out of the database in an ordered manner. Um, so you know relational databases are really good at doing that. Um, so. You've got your events and then on the other side of it. You've got your projectors and reactors. They're typically called but really just think of them as listeners right? So when I Fire a um user updated profile event a listener can listen to that. User updateated profile event and actually find that user s record in the database and change their that user s table to reflect the changes that they made this is ah not the best example, but it's fine and the main difference Between. Just using the regular larevel event dispatcher and regular event listeners is we need to store those events to the database and then potentially play those events or handle those events. In a queue or even replay them later or you know there's a little bit more of a separation. It's not just all happening in memory like a typical um larivell event life cycle and then the hardest piece in here.

08:46.99
Chris Morrell
To Really wrap your head about around is aggregates and aggregate roots. Um, and they're kind of in the middle of it all. Um, and so the aggregate or aggregate route is really just that an aggregation of all the event. Data that has happened thus far. Um, at the point of time ah that we are. We are in either if you're replaying events. It might be a point in time in the past or if the event just fired. It might be the current point in time. But. The aggregate route is really a place to hold all of the state of your application as it relates to the event system such that you can dispatch future events and guard against Invalid future events right? so. For example, um, we have an exam system that uses event sourcing under the hood and ah someone shouldn't be able to answer a question if the exam has ended so when you try to fire. Ah, ah you know a user answered question event there needs to be some sort of state that understands like is the exam still Active. So The aggregate route is the place to hold all that state for the current point in time.

10:19.10
Chris Morrell
And keep it kind of separate from your app The the application state because this needs to work regardless of where your application happens to be um because a big you know one of the values of event sourcing. Maybe maybe ah overstated value but value nonetheless is the. Opportunity to replay events so you don't want to ever get yourself in a position where your um event sourcing system relies on the current state of your application. So in this exam example which I think maybe is a good example to give right? You might have a. User started an exam or a started exam event right? that that has the exam and some metadata about it and timestamp of when they started and who the user what user started the exam. Um, and then you might have a you know, answered question Event. You might have a Skipped. Question event a couple things like that. Um and our aggregate route when we fire a exam started event the aggregate route would then store. Okay, who's the user that's taking this exam session. When does the session end based on the time limit for the exam and when a an exam question answered event is when when we try to fire an exam question answered event The aggregate route can look at that. Um time limit.

11:51.22
Chris Morrell
And say hey is is the time that the person tried to answer this question after the exam ended. Well then we're going to trigger an exception instead of letting them fire that event and maybe even fire a separate event that was like user tried to answer question after exam ended. You know you. You can do all sorts of stuff like that. So The aggregate route is is going to be the tricky one to kind of to get a sense of but that's that's the basic Premise. It's just like. Place to hold the current state of your event system separate from your application and I was I was thinking about this a little bit and almost feels like for anyone who's used to writing um, react or any sort of like ah.

12:45.18
Chris Morrell
Functional Ui It's almost like the um the aggregate route the data on the aggregate route is your context and your um, your projectors are use effect um hooks. And know if that's ah useful to anyone but I was I'm trying to draw that parallel.. It's not perfect. Um, it's just like another way to think about it. Um I know I've been okay ahead.

13:11.63
Skyler Katz
1 thing that 1 thing that helped me understand aggregate roots a little bit better was that ah aggregate roots. You can think of like they're just in memory. Um, when you persist an aggregate route. What's actually happening is all of the events are being saved to the database or the event store. Um, but your aggregate route is just in-memory and it gets built up every single time you ask for a specific aggregate route. It gets rebuilt based off of the events that have. Happened already and been saved. Um, and so I don't know it was hard for me to try to think about like oh you have this, you have this ah exam aggregate route. But then you also have an exam traditional like lairval model. It's like well how are those connected and they're not. Really connected. Um a projector might save something off to a regular lareville model but your accurate route is just in memory. It has state of where things are right now. Um, but I don't know that helped me a little bit.

14:23.31
Chris Morrell
Yeah I Think that's a really, That's ah, that's a good distinction and it's also worth I think ah an another useful thing to think about is when your system is built using event sourcing. Your events and aggregate route can hold the state of what happened and your database models can then be the data that you need to present your application and so it it gives you this flexibility to. Kind of store everything you could ever possibly want in your events and you know aggregate that data in your route to the to the degree that you need it but then project that data in the format that is actually useful for how you're going to present it in your Ui right. So it. It leads to some interesting considerations around normalization because you don't need to build your database models in a way that they like can theoretically hold all the data that you ever might need to collect. Instead you can build your database models specifically the way you need to query them for your application and so in the exam you know we're Storing. We're storing a bunch of sort of security. Um, you know, Ip address browse our fingerprinting like that sort of stuff.

15:55.74
Chris Morrell
We may need but the actual exam session table doesn't need to have the Ip address of the user in it. Um, and if we ever need to audit. We can just project those events into a new table for auditing purposes. Um.

16:15.37
Chris Morrell
And it's yeah, it's like that flexibility and and then the other thing that what you said Skylar made me think of is yes it is in-memory but that doesn't mean you can't you know, optimize. So for example, the spotsy package lets you snapshot and aggregate root. Um, so at any moment you can build up your aggregate route from all the events that have happened in your system and then save a snapshot and then next time you retrieve that aggregate route instead of having to replay say the 50 events that got you to that moment in time. Just fetch the snapshot and then replay any events that have fired since that snapshot was stored and so there are ways to optimize that so that you're not like constantly recomputing the state of anything back from the beginning of time although in reality recomputing that state. Is not very expensive and there are plenty of times when it's just fine to do that. So.

17:15.45
Bogdan Kharchenko
I will say I mean this conversation is great but I love to like take a step back as I always do and talk about kind of like how we approach things in a traditional parallell application. For example, perhaps we can talk about just kind of like ah a general user flow using you know the eloquent or m. And how we could maybe build up on the idea of event sourcing I feel like for me at least it took me a little bit of like understanding. Well what is the benefit of event sourcing right? and like I know that there's a lot of things that we're talking about kind of like snapshots aggregates and. Events and everything like and honestly it's a bit even overwhelming hearing you guys talk about it. So um, you know I was thinking like you know perhaps we can set up an example of um, you know you have a controller you know a user controller that has a store method and in that method. You know you would traditionally say user Colon Colon create and you would create a user and maybe from here we can transition into this event sourcing.

18:17.66
Chris Morrell
You know, let's actually we we talked about this briefly on the last podcast. Let's actually use this ah job assignment system. Um, because I think that's going to be a better you know there there are cases that are not great example like you wouldn't necessarily want to use event sourcing for.

18:23.27
Bogdan Kharchenko
Oh sure.

18:35.21
Chris Morrell
So Let's use 1 where we might actually have a case to use it and so I think that might be a better example. Imagine just a tool where opportunities for work come in and then those jobs can be assigned to different people and then those people can. Sort of transition those jobs through it's assigned to them and then maybe they scheduled it and then they've completed it and then maybe it's been reviewed and paid or something like that you know like where it goes through a bunch of different stages does that seem like a reasonable example.

19:03.91
Bogdan Kharchenko
Sharp.

19:09.32
Bogdan Kharchenko
Yeah, yeah, so I mean in this example, right? Um, you know traditionally we would do what we would have like a job controller or an opportunity controller where you know we create some sort of job right? There's the store method and we write directly into the jobs table with some information about the. You know the job itself and then we subsequently could have like an update ah update method on our jobs controller that could change the status right? and I also feel like you know I feel like 1 of the things that um.

19:37.24
Chris Morrell
Who.

19:43.83
Bogdan Kharchenko
You know we may not realize but I feel like we kind of use like event sourcing if you use audits or not event sourcing but just kind of like history tracking of a given column using Audit Logs and I feel like that's something that we've been doing you know, ah, inadvertently almost.. It's kind of like. Ah, trying to recreate the status of a model based on audit Logs and I think like for me one of the things that kind of made some of the event sourcing Click is well instead of trying to um, recreate. Ah, history from a given models audit table. You know you could create a model from the events you know and I feel like it's like a little bit of a paradigm shift of how we actually deal with data I don't know Maybe you guys have some experience on how that works or you know. Comments.

20:41.46
Chris Morrell
No I Think that's I think that's absolutely right I think that audit Logs Auto Logs are useful. Um, and there are lots of cases where where audit logs are the right? The right tool? Um, but certainly the moment that you start reaching for audit logs to try to like get. Back to well where was this at some point in the past that is certainly a hint that maybe maybe ah event sourcing would be a good good ah tool here.

21:07.47
Skyler Katz
Well and so in this in this jobs example like we ran into an issue where when we changed the person who was assigned a job. We kind of like erase everything about the job and put it back into the like newly assigned category but a situation happened where like. Person was assigning it to an employee of their own company. It's like someone had done part of the job and then they were changing the assignment to another person to finish it. But we ah basically like removed all their data and we went back to like our audit log and then like manually. Changed this information but like because we only had this one table. It. It created this like weird Problem. We were like oh well like that's not really a thing that we really thought about like changing it to someone who. Was picking up the work where it left off rather than just starting it over.

22:07.54
Chris Morrell
Right? right? And that's like that's ah I think that's such a good example of where just like the status column starts to fall apart because it's like something can transition from assigned to assigned.

22:24.15
Chris Morrell
But actually be in a totally new state and have a totally new status right? like and even you know the the naive way of approaching this where you just say like what was the old status. What's the new status is there any like sort of cleanup that we have to do to. Take it to that new state. Um, you know where with with this ah job assignment stuff. What we would have done was just ah, clear out the assigned user change the state to. Unassigned and then immediately assign it to a new user. Um it. It got to that new assigned state in a totally different way than if it had just been new and then assigned for the first time. And you lose all that context when you just update the model directly so in in the example that Bogden was giving right? Yeah there's a jobs controller. There's an update method on it. The admin goes and picks a new status from a dropdown and and does a put. Request to the update method and maybe there's a little bit of logic in there that looks at the old status in the new status and does a little adjustment based on on what the transition was maybe you're even using a package you could use a you know a state state machine.

23:56.57
Chris Morrell
Library that handles transitions but in the end, it's always just kind of now updating the new state and you know this is a perfect example because ah for for business reasons we need to know when was it assigned and when was it scheduled. And when was it completed and we have some Sla requirements around you know what's the time between assigned and completed or what's the time between scheduled and assigned um and so not only are we storing the status column but we're storing the. These different status timestamps because they mean something to the application and I mean I don't want to just rehash the conversation that we had last episode but you know you just see it starts to fall apart with this traditional just model controller. Approach ah, when the the actual flow of the application is through states you know or through um you know where the transition between different states matters a lot.

25:10.86
Bogdan Kharchenko
Yeah I think like 1 the um, you know another point I believe that like is a benefit with event sourcing or just kind of like this paradigm of like you know, ah firing some sort of events and you know, um, you know, ah just reacting to those events is. You know, ah, even a basic example of you know? Yes, you want to update the status of a job but there may be say a webhook or something that gets pushed from a third party that also updates a job. Well now you could just trigger that same exact event that could handle. You know, kind of like a little bit of validation and business logic within that event almost to push it forward. You know and I think that's like 1 um benefit that I feel like is a little bit challenging and you know the basic controller writing directly to the database because you could. Potentially have you know 2 places of where the logic lives or you know you could have to or you may have to like create some sort of like repository that holds some of these common functionality that you have to reuse. Um and you know by I feel like by having an eventing. It's triggered um that then kind of like. Validates that this action is kind of like almost allowed right? like is the status change from ah you know new job to schedule job allowed. Um, you know for a job that you know um say is deleted you know and.

26:43.50
Bogdan Kharchenko
So I think there's a lot of interesting ways to like encapsulate complex business logics and different events and I think that's like 1 additional benefit that you know is not clear or not visible in the surface.

26:56.58
Chris Morrell
yeah yeah I mean and that's and that's where the aggregate route comes into into play like the aggregate route becomes this sort of single entry point for all that stuff right? So to just kind of continue. Our example. Um, in an event sourced world. Ah there would there would certainly be a model called job or opportunity right? Um, but there's also going to be an aggregate route. Ah for the opportunity as well, right? And that. Object the that the ah, let's job aggregate. Let's call it right? We'll have a method. Um, you know, maybe ah, a static method called like new job right? and it accepts all of the data. That comes in from whatever source and whether that's from the administrative panel or coming from like a third party webhook or whatever. Um, that fires the event that represents a new opportunity arrived in the system right? and. Typically that would be um, tied to something like a eu id um, so that you know it's still not You're not worried about the specific database identity of that. You're just saying like this is a new opportunity that came in.

28:32.18
Chris Morrell
And then your ah your system would just call that method that method might have some validation of of the incoming data. Um, and then trigger the event and and separate. Separate from that you would have a projector that takes this on you know has just listens for the ah new opportunity event or at you know a it should be an event so like ah a new opportunity arrived or something like that I don't Know. Um.

29:08.18
Chris Morrell
Or Job offered Maybe um and that ah that listener that projector would essentially do ah job coal and Colon Create. You know, calling a regular eloquent model. And it would store that you you Id as well as any other data that you want to be on your job model for your for your application. Um later ah that job gets assigned right? and so your aggregate route you'd retrieve your aggregate route. The job aggregate by that you you Id and you would fight you would call a sign on the aggregate route under the hood. The application is going to fetch all of the events. That were fired on that U U I D which in this case is only going to be one just the ah you know job was created event and it's going to replay internally within the aggregate that event. To so to set up the internal state of the Aggregate. It's going to reapply that event to the aggregate route. Um, and you know just think of that as basically like a reducer function your aggregate is just taking Ah, you know, ah a stream of events and reducing them down to a state.

30:39.70
Chris Morrell
So Your aggregate route is probably going to need to store the current status of the job which is just New. Um, you know, maybe it's going to store some timestamps. Maybe it's going to store some other stuff that it needs but in this case, all the aggregate routes going to need to store is this this that the. Current state of the job is new right? And so when you call a sign The aggregate route can say okay well I replayed all the events internally or reapplied all the events internally. Ah, it's valid to transition from a new to an assigned state. So we'll let. The the um job was assigned event get fired and that will fire with all the data. Um, it'll probably have the assigned user Id Um, maybe some notes that ah an admin added when they were assigning it maybe. You know, probably the admin that did the assignment. Um, maybe some other metadata. You know, um and that event gets fired and now your projector is listening for job was assigned and when it sees a job was assigned it now it looks up. Job in your database your your eloquent model that has the aggregate you you Id of that event that job was created earlier so it fetches it from the database and now maybe all your projector does is say you know job. Update.

32:15.19
Chris Morrell
Status is assigned user Id is event user Id right? and so we just walk through you know the happy path when the job is scheduled all the system all that aggregate route needs to do is well Now. Ah, for the same same case like it hit the you know we we fetch the Aggregate. We retrieve the aggregate by it's a U Id we call schedule on it. The Aggregate's going to reapply all the previous events. So now when it sees the created and then assigned it's going to. Update: Its internal status to assigned and it's going to say okay well it was assigned so that means it's allowed to go into ah Scheduled. Um, and so it'll let the job was scheduled eventfire and so on and so forth right? So in this case. There is sort of this Um, the aggregate is kind of storing the same data as as what you stored in the database. Um, but those start to diverge as these systems systems get more complex. Ah, and so you know just. You just have to kind of trust that. That's the case right now but it definitely is um and the the thing that's really interesting is we can have a job was a signed event that our projector. Um.

33:49.60
Chris Morrell
Just sets the user Id and the status to assigned but we might have a job was reassigned event that in the beginning maybe just sets the user Id and the status to assigned because at the current state of our application. That's all that matters. But there's an important difference because now we have an understanding that this job got to the assigned status in 1 of 2 different ways and down the road if it turns out that we need to do other work when a job is reassigned. We can. Replay those events. We can update our projectors and we can replay all those old events and project new state as needed and so having an understanding of what what happened to get the thing in the state that it is. Becomes more and more valuable over time.

34:52.65
Skyler Katz
Exactly now and like so so given given this example, um of like that was a happy path. So let's say a job comes in as created and so the aggregate like puts it as created and then um, a webhook from a third party system.

34:54.60
Chris Morrell
Um.

35:10.55
Skyler Katz
Tries to schedule it as the next event it goes to schedule but it's in a new like the new State the created state and so it never fires the schedule event instead. It throws an exception like ah, a job has to be ah.

35:30.20
Skyler Katz
Assigned before it can be scheduled, but not only like maybe in addition to throwing an exception. It also fires an event that said like job was so job tried to be scheduled before assigned and that event. Has a reactor or projector that sends an email to an admin that says like something happened that wasn't like this bad thing happened that we didn't Want. Um I don't know there's There's some like those those paths.

36:04.24
Chris Morrell
Um, Ray I mean.

36:08.22
Skyler Katz
Um, can become a little bit easier to to reason about in the like specific case as opposed to this controller that maybe has like now all these extra spots.

36:22.46
Chris Morrell
Um, well I would take that even further like what if what we wanted was um if if ah you know a third party. Ah you know partner sends more than 3 invalid status updates. We want to notify them right? We want to notify them and we want to notify admins right in the traditional in the traditional just model application now we're storing a column on the vendor that's like. Ah, invalid webhook count right? That is like really awkward and then we have to reset it ah at at the appropriate time and like it doesn't really have any. It just feels weird in. In all other contexts except for this one case whereas if yeah, if in our um, assigned method. Um, we check is this valid and then if it's not we trigger a. You know, attempted to um, set job status to an invalid state event right? Then our aggregate route can just apply listen for that event internally.

37:54.49
Chris Morrell
And every time it sees it. It just increments an internal counter for the number of times. It's seen that um since it triggered a you know, notified vendor of bad Api calls event or something like that and ah. When it see when that count gets to 3 it does something else and then resets the count to 0 and now that count is just held internal to your aggregate route in a way that makes a lot of sense from the event stream perspective and your application doesn't have to look at it. Outside of the event stream perspective. You know.

38:34.60
Skyler Katz
And then let's say like six months down the line an admin wants to see a list of all of our vendors and who's done this portly well late like now you know we can make a new projector. That stores this in a table that just has like the vendor name and their ah incident count and we can replay all of the events that have ever happened and project that final so that final count and then have an index view. That's just like the vendor name and. And their count because some some staff person or an admin like wanted to see that. Ah you know that report from a from a ui perspective.

39:20.17
Chris Morrell
Yeah, and I mean this is maybe a little bit of a out of ah you know an unlikely case but stuff like this does come up and when you're when you think about things in events. You just have a lot of flexibility to to sort of. After the fact to decide. Oh I Want to look at this data in a slightly different way. Well as long as you have the data. Um, you can just go back and just just use historical data to do new things which is really powerful.

39:54.39
Bogdan Kharchenko
So I have a question about this example about you know bad status updates just helped me understand a little bit more. So For example, you know we have this so-called vendor sending us invalid you know statuses and you know we have to record those statuses right. And so I'm assuming every time a status comes up say hits our like Controller. We record that thing we persist that into our like so snapshot slash aggregate route. But then immediately we have to check to see if. If we want to like react to something. Um.

40:34.80
Chris Morrell
Well, you wouldn't even let the event fire if it's invalid so you would never yeah, you wouldn't even fire the like a job was scheduled event instead. You would fire a different event. So.

40:38.36
Bogdan Kharchenko
I see I see so you would check.

40:50.88
Bogdan Kharchenko
I see I see Okay, next.

40:54.74
Chris Morrell
Yeah, you're not, You're not um, you're not persisting an invalid event and and that's kind of that is the that is the fundamental job of the aggregate route is to guard against dispatching invalid events.

41:06.96
Bogdan Kharchenko
Well, But how do you then you know keep track of the number of invalid statuses. They've sent and you trigger a different event I see. Okay.

41:15.30
Chris Morrell
You trigger a different event you would trigger a vendor attempted to schedule a job you know or something like that and you can just decide like how granular you want that to be is it like a.

41:25.82
Bogdan Kharchenko
Andval Um, right invalid status. Yeah okay I see.

41:33.11
Chris Morrell
Vendor Attempted to assign job that was new or do you just trigger like a vendor ah attempted invalid job transition and you just store the status that it was in the status that they tried to attempt you know.

41:45.19
Bogdan Kharchenko
Sure right.

41:48.88
Skyler Katz
Um, vendor made an oopsie event.

41:50.42
Chris Morrell
Yes, exactly.

41:50.56
Bogdan Kharchenko
I got you? Okay, well that yeah I suppose that makes a lot of sense. So then you would persist Obviously those things and then that other um, you know validation aspect would just look for all of the persisted. You know counts of those events right? Okay, got it. Okay, all right? well.

42:05.10
Chris Morrell
Exactly? Yeah, yeah, yeah, so the the reason that this came up right is we are doing. Um, we're doing a ah pretty big billing refactor and we're so we're.

42:09.42
Bogdan Kharchenko
Ah, help me understand that.

42:24.29
Chris Morrell
Ah, implementing. Um, we're switching from authorized dot net to stripe for some stuff and you know stripe is fundamentally a very evented um implementation right? Everything comes through ah webhooks and so. When we were first. Um when we were first sort of tackling this the conversation around event sourcing came up a little bit but um I essentially made the call that um we should just implement. It. Sort of outs and not using the the formal event sourcing processes even though it's it is kind of event. You know it's it's event driven anyway, um, but for reasons and and I think that now that.

43:17.59
Chris Morrell
Um, I've just been thinking about event sourcing again I'm I'm questioning that decision and I think we're at a place where you know because a lot of the implementation is is already. Um you know, just reacting to events. It wouldn't be ah it wouldn't be a particularly difficult refactor to take the code that we have and instead of sort of these bespoke event Handlers Web Hook handlers um use use projectors and reactors and an aggregate route for the subscription or you know, whatever it might be. Um, and when we first started talking about it. Um, you know the the point came up that this may be a really good use case for event sourcing but it does. Um, it does It's it. It's less obvious to you know the traditional larevell developer How things work and is it worth sort Of. Um. You know, hiding some of this behavior behind a you know different paradigm. Um, and I I Just thought it'd be really interesting to have that conversation here because I think there's something to it. Um.

44:45.69
Chris Morrell
I'm not convinced that it that that's I you know I I still am sort of feeling like especially in the case of of stripe where you're really dealing with a lot of webhook reacting to webhooks just using a formal event sourcing process might might. I think it might be the right call but I just I don't know I wanted to have that and I know Skyler your initial reaction was just like it just feels like it might be harder to reason about if we're not always inside this event sourcing stuff and billing is. Something that we're going to be dealing with a lot so like is it worth that cost and I wonder if you're still feeling that or if you've kind of changed your position at all or and where you are.

45:36.66
Skyler Katz
Yeah I mean I think um I had I had heard of event sourcing before I started at Internatche but I had never used it and.

45:47.45
Skyler Katz
So I was just like man. There's all these terms and like well I don't have a cs degree. Maybe if I had a cs degree like I'd understand what an aggregate root and a projector and all this stuff was and I was just like like I don't know I just want to like have my models and like keep with the defaults but I spent literally 3 hours watch some videos read some blog posts and now I'm like oh like I I get it and I actually think there's a lot of places where this would have been useful in in past jobs that I've had like I like I worked.

46:20.31
Chris Morrell
It's all events everywhere.

46:23.62
Skyler Katz
For a long time on ah on a Cms product and we we like had ah versions like people could create new versions of existing content. Um, and so we had this like table with the actual content and then another table with the versions. Ah, but someone like wants to preview a version but not publish it well like we didn't have a way to do that and so then we had this third table that was like preview. Ah and then like oh well it needs to go through an approval process if it's just an editor and not an admin and like we had just had all these terrible like. It was really hard to work with in in a quote unquote traditional traditional sense and like event sourcing while it adds a level of complexity initially like could have simplified the implementation of that and so. Looking at all this code that we have for billing here already is like man this is a lot of weird like weird edge cases that are being covered that event sourcing like at least it's got more guardrails. And it's got conventions of how to do something and um, you know in the sense of billing where a user might be entering credit card information an admin might be crediting their account with something stripe sending a webhook authorized dot net is sending a like. Ah.

47:57.48
Skyler Katz
Settlement notification like we've got all these different things in different places and jobs are running to do subscriptions like I don't know event sourcing might kind of contain all of those different places in ah in a way that makes it.

48:14.92
Skyler Katz
Ah, easier to easier to work with.

48:16.84
Bogdan Kharchenko
I love how what 3 are our video made Skyler an event source junkie.

48:21.30
Skyler Katz
I know before I was like man listening to Daniel on all these different podcasts talking about event sourcing and I was just like I like it's overblown but now I'm like oh man Daniel was right.

48:30.91
Bogdan Kharchenko
Black magic yeah I mean um, you know I think um, you know as far as the ah you know stripe example you know I don't have you know I have some. Doubts also with event sourcing because I also feel like you know it is a bit of black magic and I feel like anybody coming from like a traditional background like you Kyler like you Chris and you know me and many other people who would be listening to this. You know it is a little bit of um, you know. Once you get your feet wet. Maybe then you'll start to really appreciate understand it I think that's part of it as far as the stripe implementation stuff. You know what I worry about is you know are we collecting are we like ever going to be in a position to replay those events. To project different data and I know that we have a different payment processor right now that is painful. Um, which we.

49:31.13
Chris Morrell
Um, it's authorized dot net. It's the worst I'm I'm happy to say their name and disparage it because they're awful.

49:38.38
Bogdan Kharchenko
Yes, but I feel like if authorized thatnet could send us events. Um, you know they would probably be terrible. But um, you know it would be nice to replay some of this stuff in our database. You know we've certainly over the years have made mistakes we are human. We're not. Perfect and you know it would be nice to say hey just replay 5 years worth of authorize that and events to bring somebody's like um, status up to speed or whatever it is so I do think that there is some value in recording some of these stripe events. But I also um, you know are we kind of. Ah, is our application. You know if we don't record it. It's almost like our application is like a projector of stripe events. Ah they send us the events and we kind of like crunch them down and we do stuff you know, but I suppose if we record them then we could also um. You know, replay those events and I don't know how valuable that is I mean on 1 hand sounds like valuable but what is your initial gut.

50:40.23
Chris Morrell
Um, I mean I think the the promise of being able to replay events is incredibly enticing. Um, and I think being able to replay events in. Development and testing is very has already proven to be and incredibly valuable because um, yeah.

51:03.18
Skyler Katz
I mean I have a real have a real world example that we were just working on earlier this week where so in in our application like a user can go from paid to to just like a guest user and if they go back to paid within. Twelve months of downgrading like we will reinstate them at their like level with all of their path like all of their like credits and things like they're there. But if it's after twelve months then like we don't we don't we give them some things but not everything and. So we've got to like store this date about like when when were they downgraded when were they upgraded and if we had these events like the event itself would have that date. But if we change our minds and we say now it's eleven months or now it's thirteen months like we've got all these events that our user was downgraded user was upgraded I don't know I think like this is is a case where like we were relying on this date that wasn't necessarily set correctly and people that had been downgraded for years like we're getting. Platinum status or whatever like when they shouldn't have and it was confusing to them and to staff into us and like we couldn't quite figure out. How did they get into this state because we thought they deactivated in 2011 but like for some reason we just don't know.

52:39.55
Skyler Katz
Because all we have is where they were at when we where the database was.

52:44.32
Chris Morrell
Right? Yeah and and to be able to I mean even without that's the thing is like the promise of replaying events is really enticing and I I Do think that there's value there. But even Beyond just replaying the events like. In that case of that person that that ah there was an issue with being able to just look at the stream of events. Um and debug by just that instead of trying to like. Recreate all of that history from all the other data and the audit logs and all these different like you know various data points that we have around the application. Um, that alone would have been really helpful right? But um. Yeah I mean I I Definitely think that um, replaying events is is a powerful feature of this you know architecture and I think that it can come into play even if it's not I mean you know the the. Big promise is you know if we go back to the exam system. Ah you know we test every you know the the exam system is tested incredibly heavily and went through Tons of Q A So Obviously this didn't happen but imagine a world where ah we accidentally.

54:18.60
Chris Morrell
Didn't add up their score correctly in our ah you know in our projector we were doing like a you know ah plus equals and. Like we needed to be like resetting I don't know I can't think of a case where this would actually happen but like we we somehow were screwing up the score and maybe it was like it was just like a rounding error. So. It only came up in these really edge cases where it was like. You know, multiple choice question and it was an odd number of options and there was like you know where it just didn't come up enough. Um, and so people were were getting these like fractional scores in the rounding wasn't working the way. Um, it was intended to work right? That's ah, that's a that's a theoretical scenario. Um. The the like real like promise of being able to replay events is theoretically in that case we would be able to go back and change round to floor to seal or whatever it was that you know whatever that the bug was and then. Either just delete the entire exam sessions table and rerun all of those events and now all the sessions come with um the correct scoring or if you make all of your projectors idempotent then you just replay all the events and.

55:47.80
Chris Morrell
Um, they just get applied in order again and they you know it just it just recalculates that score for each session. Um, and I think that there's a lot of like that's really interesting to me. But. We've never been in a position to do that yet. So I don't know I mean I imagine that actually replaying 12000000 events would take a while and so there's like downtime considerations and there's like what if things what if there is an error like. Halfway through the process like um, there's a bunch of questions that I don't know the answer to yet. Um, yes.

56:28.41
Skyler Katz
You could replay to a new table and then after it finishes you deploy again pointing to that new table in your Ui there's you know there's some options.

56:42.65
Chris Morrell
Um, and that's actually what's what's even cooler there is you can update your projector to ah project to 2 tables then replay all your events into the new table. While that's happening all of the events that get triggered during the the migration are just getting projected into 2 places so you have up totate state on both tables and then once everything synced up and I mean this is what we did with ah with ah. System in the past when we were actually moving to this event source system was we just projected everything into 2 places and that way we were you know able to to do it over time without having to like make that that moment in time switch. Um.

57:37.17
Bogdan Kharchenko
Yeah, no, it definitely sounds like a very compelling argument I feel like you know after also doing some research on the event sourcing and you know having this conversation and just kind of looking back at some of the old event sourcing code that we have you know I think that it is a really good solution.

57:37.36
Chris Morrell
Yeah.

57:56.65
Bogdan Kharchenko
You know, um to kind of like handle complex logic such as the exam system like you mentioned earlier we have to you know, be able to prove that a certain person has taken this course and like storing their ip address with every answer is just not viable. Um, so you know I think that there's a lot of benefits and even for you know, even if we do have to replay. You know it sounds like there's some options that we could even if it takes a while and we need to have ah and we need to use a computere a cpu that has not yet been developed to replay 12000000 events you know I'm sure that we'll be able to. Do it in time you know it sounds like there's an offramp. Um, you know to be able to project into different tables to be able to you know do various things I feel like some of it still you know feels like ah black magic to me and I'm sure Skyyler probably feels the same way and I'm sure Chris you have some doubts. That's where I think we are at least.

58:55.69
Chris Morrell
Yeah I mean the other thing about replaying events and this I actually think is the bigger upside is there's the scenario where you replay events just to um to fix ah fix something or maybe capture new data that you need. Um, right? because going back to this job assignment system. Maybe ah maybe in the beginning when a job was scheduled. Event is fired and a job is so was assigned event is fired all we're doing is updating the status of the job in our in our eloquent model. But maybe six months out you know our partner comes back and says hey we want you know we want to start auditing. Um the you know, ah, the new to assigned timing. Of your application because like you agree to certain standards and now we're in a position where oh shoot we haven't been storing those timestamps on the the jobs table but we have those events and I think um. Think the use cases for replaying events into new projectors is much more I imagine that comes up more I mean that's something that we've already done. Um, but I imagine that comes up more often where okay this new requirement comes in and now.

01:00:25.95
Chris Morrell
Instead of having to store all of these times stamps on the jobs table when those timestamps don't really matter ah to the application. Um, that's that's consuming that um that model we can instead just write a new projector. That projects. Um these you know time averages into or you know these these daily or weekly or monthly um, averages to a new table that is custom built for the auditing purposes. Ah, you know so that we can just show like you know in January you know our average time between us to between new and assigned was you know 16 hours and our highest was 28 hours and our lowest was 2 hours or what you know? Whatever whatever data we need and in February you know we just could we aggregate. However, we want and all that would be necessary to make that happen is um, build up. The necessary state add any necessary so necessary state to the aggregate route to do those calculations and because you know to Skyler's point at the very beginning the aggregate route is just in memory. You can add new stuff to it whenever you want because it's going to be recomputed.

01:02:00.87
Chris Morrell
Um, you might have to you might have to wipe out your snapshots If you're going to do that. But um, and now we just we just have a new feature that we can build from this historical data. Um, and I think in terms of projection that feels to me like a. A bigger upside or or more realistic upside than this kind of like imagined world where you just wipe your entire application state and replay all your events to get a new one I think well it's nice to know that that's like sort of there on the table I I Imagine that's like that's something that you do. Very infrequently.

01:02:38.39
Skyler Katz
Yeah, and I think that there's like 2 There's like two stories that I'm still not fully not fully like convinced but mostly because I just don't know they like haven't done enough research is Like. What's the testing story to this because it's so nice in larevel to just be like job Factory like create a job and then like assert some stuff and and like hit an endpoint and so like is there are there good testing facilities to like create a couple of events and then you know.

01:03:06.59
Chris Morrell
Yes.

01:03:12.89
Skyler Katz
Expect some things or and so like that's like 1 part and sounds like the answer is yes like use a package that's open source that has all that stuff and great and then I think like another interesting conversation have is like all right like event sourcing is obviously not for everything but like what like what are some things that's like probably not worth. Doing it on. Um and I know like Daniel mentioned you shouldn't like make your authentication event sourced but like I wonder like should your users be event sourced like you know do we need to keep a history of like when they updated their profile.

01:03:50.38
Chris Morrell
Yeah I mean this I'm going to give the most unsatisfying answer. Ah it depends right? like there are I think there are cases where authentication could be event sourced. Maybe not like not to the degree where you're actually like.

01:03:56.33
Skyler Katz
Sure.

01:04:07.36
Chris Morrell
Projecting their session on a queue in the you know like ah but yeah, you may if it's really important to your system from like a security and auditing perspective to note like exactly when people logged in.

01:04:13.34
Bogdan Kharchenko
I.

01:04:26.81
Chris Morrell
Um, and maybe you know you you care about where they logged in from and like you want to trigger specific events if someone logs in from like 1 continent and then logs in from a different continent within like 30 seconds or something you know like. There are use cases where from like a security and auditing perspective you may want to um, use event sourcing for for things like authentication. Um, and yeah and in the same way like if the state of. Your users and their their transition between those states is important right? if you need to say like this person used a different company name six months ago and they changed their company name. You know five and a half months ago like it may be worth it right? Ah, but on the flip side if you're never going to ask those questions. It's probably way way way overkill.

01:05:31.10
Skyler Katz
Down.

01:05:33.15
Bogdan Kharchenko
Yeah I could certainly see you know having an authentication kind of like tracking people's locations and stuff I feel like I've done this without events sourcing by just writing custom data into an audit log like a person logged in from this place and now it's in the audit log. Um, but you know it's a very primitive you know obviously way of doing things I think the other question that I also have like like when do you actually project events like if we take this you know, ah example of you know, recording where you logged in from like I don't want to compute that data. During the login process I Just want to write that event So would there be kind of like a background job of some sort process that says like just go through all of the latest logins and you know, ah, project them and do whatever else needs to happen.

01:06:29.91
Chris Morrell
Yeah I mean this this is getting a little bit to the edge of my um, my comfort level with with specifically how like the the library that we use the spotsy library but um. Yeah I imagine that you would essentially um, you would need to trigger a user logged in event and then maybe have like a reactor that um runs On. On the queue that listens for the user logged in event and you know fires a set like does the um you know the um, Ip Lookup Geo stuff in the background on the queue and fires like and it.

01:07:18.00
Bogdan Kharchenko
Sure.

01:07:24.30
Chris Morrell
Additional like user login was geocoded event or something like that. You know what I mean like um because yeah you you obviously don't necessarily want to do that direct inside your um, synchronous login method.

01:07:40.00
Bogdan Kharchenko
Yeah I feel like you know in on this episode. We haven't talked about overengineering anything yet and I feel like what if we overengineered like a basic user registration flow using event sourcing that like triggers an event like would that be. Ah, an interesting way to explore some of the event sourcing magic.

01:08:06.91
Chris Morrell
I Don't know would I feel like we've kind of already walked through you know other flows I don't know that we would really um that we would really get to anything new there.

01:08:18.54
Skyler Katz
I think it would be interesting to like so Lairva has all these breeze starter kits that have like authentication out of the box. It'd be interesting to like make a breeze starter kit. That's like an event sourcing breeze starter kit where yeah like instead of it. Creating the user directly It's firing a user register sort of end into the event sourcing thing and it's like projecting that data like that that like how do we? How do you like? what are so which isn't necessarily overengineered but it's like how do we get like. Our default like larebel conventions but also like integrate this event sourcing paradigm um without it feeling like we're going against the framework ah which like is all vibes. For the most part but still like that matters.

01:09:13.92
Chris Morrell
Yeah, so I think you know something that I've been thinking about a ton is sort of the branding of event sourcing and like yeah these things like ah aggregate root and c q Rs and CRDT and projectors and reactors and you know aggregate versioning and all this stuff like it's it's hard. It's just like inaccessible in a way and even if it's not even if all those terms are perfectly fine. They yeah, they don't vibe with the larall sort of way and I I do think that there is an opportunity to sort of like implement a package that gives you a lot. Of the power of event sourcing but just feels more you know artisanal.

01:10:16.72
Skyler Katz
Throw some facades on there and make it like just so easy to use event sourcing that it becomes like easy. It doesn't feel like it's heavy handed. Obviously there's tradeoffs to every like major architectural decision. But makes it easier if it feels like you're not fighting the the framework.

01:10:42.78
Chris Morrell
Um, right right? So here's here's another concept that I did want to introduce. Um, so the the the term is ah Cqr s Command and query responsibility segregation.

01:10:59.46
Chris Morrell
And well first I'll describe what it is and then and then I'll bring it back to Layerville the idea of ah of cqr as is essentially that um for an event sourced application to really function. Well. You have to segregate your commands your write activity from your queries your read activity and like in in a formal event sourcing model your your like um application is going to trigger commands. Expecting nothing in return then that's going to write to your write model your write database. It might like and that's effectively just saving events in the in the database and then your event system is going to. Separate from sort of the rest of your application. Ah read those the the history of those commands I mean and you don't actually need technically you don't need the like projector process right? You could um. Always just instantiate your state by reapplying all the events and never project but typically like you want to be able to query your data. Um, and so you know you have the the application triggers commands those get written and then.

01:12:33.70
Chris Morrell
Some magic happens. You know whether it's those commands are processed on a queue. Maybe those commands are processed synchronously in your application but like from sort of the cqs perspective like these things are segregated you write and then something happens. And now you have a read model that you can read from um and and and so your read model in sort of the Laravell world would be eloquent models right? and your right model would be the aggregate root triggering events. Um. And by separating those things out like you need to separate those things out to kind of get a lot of the value that we talked about but I think that fundamentally this separation of reads and writes. Just feels really un laravellli right? where you're just like oh now I have like ah I'm doing all this work in 1 place for one side of the interaction and then I have to do all this work in another place to do to get the other side of the and interaction and like. I've got this like job aggregate route and I've got this job model and I have like to apply my job events inside of the job aggregate and then I also have to project my job events into my job model and like it just starts to feel.

01:14:08.43
Chris Morrell
Really heavy handed and so the thing that I keep on wondering is like is there a way to implement. You know, implement sort of the principles of cqrs. Um, While. Making the ergonomics of it nicer inside of like a traditional Layerville application and I don't know I think that's like almost a question for another episode but it's just like something to to at least think about or start start thinking about.

01:14:45.18
Skyler Katz
Yeah I don't know I think I think you can get you. You have the potential of getting into weird situations where then you're like aggregates are pulling in data from. Ah. Previous like state of where things are somewhere else but I don't know because there's no I don't have like a good use use case one way or another I will say like it feels like a lot. But if you I mean Laraville has model events. And observers and policies and lots of things that are kind of spread out that act on like you fire an event and then you can register a listener or you can register a model observer or you can have model events in a boot method on. Model like there's already. Ah, you can already have ah layers of abstraction and so is it really that much more to say like you have your projectors that are writing to your eloquent models and you have your aggregates that are um. You know, handling your events and we can come up with some like more more lairvell ask naming conventions of those things but I don't actually think it's that ah I would have agreed with you.

01:16:18.00
Skyler Katz
Two weeks ago but like I don't actually know that it's that much more now.

01:16:23.72
Chris Morrell
That's fair, yeah and I mean maybe there are I I do imagine that there are ways to to make it feel a little bit better. Um, while still getting getting all the power of um.

01:16:40.65
Chris Morrell
Of that separation.

01:16:40.67
Bogdan Kharchenko
So let's talk about you know some of the packages. Let's say I want to create a new you know project or I want to tinker around with event sourcing you know is you know I know that there's the spotsy package out there. There's also the event sauce package like you know what do you think is. Ah, good approach. You know to to start with you know I feel like you know we we should bring some value to our listeners and how does 1 you know, just go build events and project them and you know replay them where where do you get all that testing magic you were talking about earlier and.

01:17:18.75
Chris Morrell
Um, well the spotsy package um comes with a lot of nice testing convenience out of the box. Um I think that.

01:17:29.35
Skyler Katz
And which in their Docs they say that they were inspired by event sauces testing conveniences. So I'll put it out there that yeah.

01:17:35.31
Chris Morrell
Oh there, you go.

01:17:37.70
Bogdan Kharchenko
So so it sounds like event sauce is like the O G P P version.

01:17:40.72
Chris Morrell
Yeah, yeah, I've never used event sauce and I haven't dug into it event sauce I know is it goes deeper than the spotsy package and I think that it touches on a bunch of things that or or. You know has answers to a bunch of questions that I've run into already. You know a big one is just like um when you have multiple aggregates that are sort of part of the same thing right? If you think about our our example of like the vendor. Sending a status. Update That's Invalid. You know you you would argue that the actual event that you're triggering about the vendor should actually happen on the vendor aggregate and I think event sauce has um, ah. Better story around sort of multiple aggregates all being part of the same interaction whereas the spotsy package is a little bit more strict about this idea that everything happens to 1 aggregate and 1 Aggregate. Only. Or 1 aggregate route Only um and I think that the I think that event sauce you know supports. Um, more of the um formal event stores and and maybe has more formal concepts built in.

01:19:13.46
Chris Morrell
The reason that we chose the spotsy package when we did was that the spotsy package already feels like it's making event sourcing more accessible to laravell developers. Um, you know it does use a lot of laravele conventions. The testing helpers tie in nicely with. The you know larave testing feature set. Um, and yeah, it's just you know it's it's like a a ah lairravell package through and through um that said. Um I know Skyler was saying this earlier before we started recording and I I think that this resonated with me too that um, it's it's nice to use 1 of these packages. But if someone's getting started I I do think that there's a lot of value in. Trying to implement the concepts yourself before reaching for a package because the reality is it's not that hard a lot of what these packages do is just like provide formal mechanisms for stuff that you're going to eventually need. Or you know guard against um, you know potential bad scenarios that you might not know to guard against in the beginning right? There's value there but like just building it out in the beginning and just using the event dispatcher and and like ah.

01:20:44.67
Chris Morrell
A listener and a stored event model and you know write your own. Um your own stuff on top of that I think it's where I would start if I was like trying to get my head wrapped around it. Um.

01:20:58.38
Bogdan Kharchenko
Yeah I mean I was gonna say I feel like writing your own event source package when you don't know what it is is is a big undertaking I think in my mind I do think the happy medium perhaps is like you know, actually sitting down and looking at the source code of spotty package to figure out how it is. It works I mean unless you've already wrapped your head around. You know how events sourcing works and you know you're very confident to get the event-driven workflow and how the aggregate route works I think for an average person who has not experienced that. That is a big challenge I totally get where you're coming from Chris but I feel like it's ah it's a huge ask I don't know I would say look at some source code. Maybe you know we could include some material that we've found on event sourcing. Um, you know for people to also like educate themselves. Um, you know about some of the concepts and maybe in like the description of the podcast I think that'll be really cool.

01:22:02.51
Chris Morrell
Yeah, we definitely can. There's that event sorcery. Um Youtube series. That's also a really good place to to start and I can add that to notes.

01:22:10.57
Skyler Katz
Yeah I mean I think like we don't my my statement earlier off off the podcast about like maybe we if we're going to do this more. We should write our own was more that like ah if this is going to be. Like if it's first if it's for a project. That's just like for learning like using a package is is great like writing it yourself is great. But if this is for like a thing that's making money is providing jobs for people if you're relying on something that you don't totally understand how it works that can become a risk. And like if the package does make changes that you don't Want. We're kind of like you're kind of stuck whereas like if this is a main part of the application maybe writing our own makes sense in this context. Also maybe it's an opportunity to overengineer something you know like there's.

01:23:01.96
Chris Morrell
Especially if those package changes are in private final state.

01:23:04.66
Skyler Katz
There's lots of options.

01:23:10.60
Skyler Katz
Oh man getting spicy on the on the podcast. But I think like there's there are um, there are tradeoffs. There are benefits of an open source package because fixing bugs and things like that. But the tradeoff is like you're kind of so. Ah, Beholden to like what the community wants the package to do or what the maintainer of the package wants in or out of it and um I think it really it really depends. But if you look at the source code of spoty or event sauce and you're overwhelmed like watch some videos. And then maybe implement your own.. That's just the bare minimum of of what you need, Um, and in that sense it can be.. It's in the in the sense of like it's not that hard. Yeah, if you like watch some videos and read some blog posts. You may find that it is not as hard. Um, but if you look at the at the package and you're like oh my gosh. There's all this stuff like at the at the end of the day. It's not that much stuff if you start with like a bare minimum a minimal implementation.

01:24:19.60
Chris Morrell
Yeah I mean another thing about like when you're writing a package you know the the spotsy package. For example, has a you know an event repository interface and then an event. Repository abstract event repository and then an eloquent event repository and all of that makes sense from a package perspective because they're trying to implement something that is flexible while defining a clear interface for ah, writing to and and reading events and I mean when we were looking at it. There was a period of time when when we were looking at writing our own Dynamodb implementation of that event repository interface and so having you know, having all those layers of abstraction ah makes a ton of sense at the package level. Um, but. Internally right? We're not. We don't need ah an event repository interface and an abstract event repository and an eloquent event Repository. We can just have an event repository. Ah, ah that. I Mean we can just have an event a stored events model and use eloquent and not have a repository at all and like that works perfectly fine for us and you know I think that that's definitely true about these packages is they need to account for a ton of different scenarios and any application only needs to account for.

01:25:51.47
Chris Morrell
There specific scenario.

01:25:53.90
Skyler Katz
Agreed.

01:25:58.58
Chris Morrell
All right? This feels like um, a good place to start to slow down. Um, you know I worry in the back of my mind. There's a tiny part of me that's like.

01:26:13.83
Chris Morrell
People are going to listen to this and we will have never set the stage well enough for the conversation. It's going to make no sense I Hope not um, but I I think I don't know I think that this. This architecture makes a lot of sense in a lot of places and I definitely want to keep on sort of exploring it and talking about it. Um, both for our application and and and I do really want to come back to this question of you know is there a way to rethink some of the terms for. Specifically the the world of Layer L Developers and Laville applications or rethink some of the you know the structure to make these things still have the benefit that they have but kind of work within the traditional Layerl Applications. War.

01:27:10.67
Skyler Katz
I think like if you've come to the hour and 27 minute mark of this episode and you're like I still don't understand event sourcing ah go watch the first 14 episodes of Sean Mccool's event sorcery course on Youtube. It's free. Ah, and it's it answers a lot of those questions I think like I was skeptical until after listening to that and like he doesn't he talks about event sourcing using ph p but he's really. Like he caveats a lot of things that like it has nothing to do with the ph p language like you could write event sourcing applications in any language with or without a framework and um, but it's super It's super helpful I gave me like now I feel like yeah I could go in and write some event sourcing code and. And understand what the heck I'm talking about.

01:28:08.10
Chris Morrell
Um, and I I'll ah I'll shout it out even though I haven't um, looked at it in a long time but you know Spotsy has a whole advanced advanced sourcing um course that they released um, you know it's a paid course. But um. You know I'm ah i' a little salty about it because a lot of that content used to just be included in the ah spotsy event sourcing documentation and now it's behind this paywall but you know you got to get paid I don't mind ah paying ah a company for the work that they do so um, that's another resource. I can't I can't speak exactly to the quality of it because I haven't looked at the paid courseru I've just seen some of the um resources that kind of led up to that. Um, but again like that's very specific to laraville applications. So I think for laraville developers. Um. It's good to have it. There.

01:29:04.79
Bogdan Kharchenko
Yeah I will say you know I agree with Skyler I also watch that same Youtube video and I feel like personally myself I don't know if you guys know much about me but I used to be a paramedic back in the day and I read a lot of books about how to intubate people and that was cool but then. You have to go and actually do it so I feel like you have to watch this course you got to go get the ah you know the spotsy package the event sorcery package read some documentation and actually make something because otherwise you know, um, if you cannot put it into practice. It's useless. I think that's really my position for.

01:29:42.72
Chris Morrell
Um, and I Yeah, that's I think that's true of everything right? like you can you can understand the Theory. Um, and I mean you know I I I Yeah Rail against private private methods and and final classes. Um, sometimes they're perfectly fine. But like if you don't know when and how to use something you can you can get caught up in using it the wrong way or or like you know. I Don't know Maybe that's a bad analogy to draw. But.

01:30:17.67
Skyler Katz
Um I didn't understand the difference between private and protected until I started working here and Chris changed my Pr the first pr I I made and said we don't we don't do private here. Why know now. But i.

01:30:23.12
Bogdan Kharchenko
What? what.

01:30:28.75
Chris Morrell
The the difference is that private is something that you never type into code and protected is something that you use when it's not public.

01:30:40.50
Skyler Katz
Yes, indeed.

01:30:43.95
Bogdan Kharchenko
Ah, yes.

01:30:45.86
Chris Morrell
Ah, and final is a word that you can just leave out of your vocabulary.

01:30:53.73
Chris Morrell
All right? Well I think that's a perfect place to stop. This has been fun until next time.

01:30:54.96
Bogdan Kharchenko
Ah.

01:30:59.68
Skyler Katz
Indeed it has see you.

01:31:01.12
Bogdan Kharchenko
See you guys.

Creators and Guests

Chris Morrell
Host
Chris Morrell
Father of two. Mostly talking about PHP/Laravel/React on Twitter. He/him.
Skyler Katz
Guest
Skyler Katz
YIMBY | PHP | Improv | Cycling | Civics | He/Him
What about event sourcing?
Broadcast by