Event Sourcing in Laravel with EventSauce

Dries Vints

Dries Vints discusses event sourcing in Laravel with EventSauce

Transcript

00:00:00 everyone as everyone knew good like Justin said I'm Teresa I work for laravel I do most of the open source up I'm basically yes all closing in on your issue oh wait I can say it okay let's write it again hey I'm Greece I'm super nice guy helping you out so I thought like um I was gonna wear this shirt and would be pretty unique today but like have the audience's wearing it but I'm like the only person obligated to wear it so I guess it's fine okay so we have a lot to cover and I only have 30 minutes so

00:00:37 let's get going today we will be talking about event sourcing and what I mostly want to achieve with the stock today like there's tons of theoretical stuff out there yet what I want to achieve with the stock today is like show you a really pragmatic way to introduce Lehr event sourcing in a lara flap like there's tons of coat in the stock there's almost no theory so if you don't know what event sourcing is I recommend that the talks is gonna be recorded that afterwards you might like revisit again

00:01:09 to to see how it's actually implement but it's mostly going to be code samples will be using event sauce for people who don't know what it is it's library made by friendly young who you probably know from Firefly system and just like a really easy way to get started with events event sourcing in a pitch be application it's really focused on queuing and how how storage is done and also as some really cool cool testing tooling in mind what we'll be using in stock is our main domain and process will be get up and our process will be

00:01:47 like a pull request and for people who don't know whether the may know process domain think of anything let's your app is actually about like if your get up your domain is like open source repositories source code sharing and the process is a get up pull request for anything about the slightest amusing font awesome here for the for the icons we have screw you Steve I am using font awesome so for people that eagle-eyes this isn't really the icon for pull requests it's actually the branching icon but because

00:02:22 the pull request I icon came with the pro the page feature I just used like CSS transform - rotate it and flip it and you know basically looks the same that's so cheap I am anyways just to clear up some confusion up front like I'm going to use the worst model and command a lot and they're not the same thing as an eloquent model and a console command think of model in this way is like the structure of your code in your application the way how you model your software and commands your are basically you can refer to them as

00:03:00 huge ops which you already know so there's like four different questions I want to answer in this talk but because I mostly saw time to answer one of them we're going to go really quickly over the first three to just to like give you a little bit of a hint about what event sourcing actually is and we can go immediately to the part of how we're going to implement it so what is the event sourcing I know like a lot of people like my thing is like this magical thing that will solve all of your problems and it does in some sort

00:03:35 of way but it brings along a lot of like constraints like difficulty and implementing it but you get a lot of come back from it and just to like get immediately started out with some code so you can get a grasp for what it's about when you like working in a traditional way you might in a laravel app you might like use an eloquent model to do some really crowd like operations like create a new record and database updated overwrite the existing data what that was in there delete existing data and how event sourcing really tackles

00:04:13 this is it's it's makes use of events which you already know in level maybe perhaps and Staggs those upon each other and derives the states from those events in the read moles I know this might sound like a little bit like a lot right now and abstract but we're gonna get into how it's done you know in a bit what's the best takeaway you can need to get from this talk from this slide is that instead of like using crud like operation to emit events and you save those in the storage and that was if we're the writing side of operations

00:04:54 and for read sites we're also doing like a little bit of a different thing so for Apollo chorus you might need like the polar cross itself you need its author you need the comments to display beneath it so we need like three tables in your database to do some joints and your I get the data and displayed to the front-end and an event sourcing what you're instead doing like instead of like doing the real traditional relationship thing you're optimizing your read site for its specific use cases so in this case you might have

00:05:31 like a specific table for the pull request few which are viewing and just in search one record but all the data you need to display that item so your reach becomes super fast and super simple and Ian again like this might be a little bit abstract but we'll get to more details in a bit so like I said like your reads become easier because of this because you're optimizing for your read cite your rights become a little bit harder trade-offs I think it was frankly younger who said that even sourcing makes the easy thing hard but

00:06:06 makes our thing easy trade-offs again but there's a lot to be said for both techniques something you really need to know about event sourcing is that history cannot change no matter what because you're stacking events and you're actually saving that historical state and you're deriving state from those events it cannot change because changing history can be done you can travel back in time not yet at least so make sure you don't change history because events or police will come and find you so you

00:06:43 might ask yourself like why why would you use events or why would you need it actually and there's like a couple of things like like I said like I don't have much time right now to get into this specific part but just to give you like a really heads-up about some of the benefits you get you're like I said like your reach sights your read models become really fast you're optimizing for you read sites you can predict the future basically like imagine that you're like in states or very early state of your application that you still

00:07:13 don't really know what you're gonna do with all of the data you're collecting laying around you can introduce event sourcing save all of the states you ever ever gotten and instead of overriding it you have like a nice history lock of that whatever happened if your boss some at one point walks in and says like I want a report about this specific process well whatever happened in the past you can basically do it because you have all the data you need to make that report you can travel back in time and

00:07:41 this is really cool if you're using something like get and you want to like display the state of your application in the past at a certain point you can roll back all of all the data and display the application in exactly the state it was at certain pinpoints at the moment in time together with get this make sure like a really cool feature for other thing if you're audited and people want to know like what why something has happened at certain points in time you can really show them okay it happened because of

00:08:14 T's and these in these events real cool stuff so let's cut to the actual part where ever we came for so like I said there's gonna be a lot of code here I'm gonna go through it fairly quickly the talk is being recorded so we ever ever need to be like reflect on that you can watch the talk again first let's start off with like the traditional way how you might handle a new pull request so you might have a store method on your controller and you might want to add a polar quest to user who's making

00:08:48 progress you take like a title a description and origin branch the target branch we're your merchants emerge again against and you redirect back to a view and invent sourcing this works a little bit differently so what we're first doing is we're gonna validate whatever you this you want to do against a certain set of business rules we'll come back to that later what we're going to use is like commands Q jobs in this and this this particular example and we're going to use that to call some some classes later on to omit those events so

00:09:30 we have we have a couch up here we're using dispatch now because we want to do it in a synchronous way we want to do it now so it happens now and we first generate a UUID upfront so we can use that in the redirect to immediately redirect you to correct you when you look at that command you'll notice a couple of things fair warning I'm using a lot of type-ins and a lot of final in this talk I really hope Taylor doesn't fire me for that well I think we'll be fine so in the handle method of that Q job or

00:10:06 commands you you use like an aggregate route to pass to retrieve an aggregate a classic cars your business rules and perform the command again set this is probably the part of the talk where you're like wait what the aggro deck or what so what aggravates an aggregate routes really are as they're more of a turn like coming from the DDD community they're not eloquent models people like them to confuse them with elegant Wells think of like eloquent models like representing the state in your database

00:10:44 as is like just represents a certain records in your database a represent states from that persistent storage aggregate roots are simple PHP classes and what they do is they guard whatever this you're trying to do in your process so they will take the comment or give feeding them they will say like okay this command needs to be validated against this this and this and then when this is all of that is correct the limit events which you can save in your storage and derive data from well look at like everything of that in a bit

00:11:24 aggregate roots can exist of multiple aggregates if you're a quick example of that think of like an aggregate to two routes like polar quest and like comments being small aggregates within that pull request which have their own set of business rules so the aggregate routes is basically like says a class in event sauce you need to implement an interface implement a trait which adds new behavior will dive deeper into iterate a little bit later and this is basically our we can start with an aggregate route how to handle the

00:12:01 command is like I said like you probably have like a method on the aggregate routes taking that command and you use the data from the command to emit an event so what we're doing here is we're creating a new event polar crest was opened we're passing all the data from the command to the pole to the event and recording that event against the aggregate route will dive into the method a little bit later on but you'll notice that first says you need to validate some business rules so how you do that is you basically write some code

00:12:36 to validate that certain scenarios can't happen because that's important to you those are important to your business to your stakeholders that these things can't happen and in this particular example we want to make sure that the origin branch and the target branch aren't same because that just doesn't make sense I'm merging the same thing in the same range we throw an exception here so the process stops and you can react to the exception and to inform your user that this is a scenario that can't happen

00:13:06 something that's really cool and something my buddy Frick actually like told me is that you can also record the unhappy pets so you can you're not like ty town too ordering only events about the good things that happen in your process you are also allowed to record things that are bad so in this particular example like if you want to merge your pull request but it isn't a proof first then you can say like okay we're gonna record an unapproved Mercia was attempted and we're going to show the exception

00:13:41 afterwards and then you can like later on say like okay like how many requests were attempted that burns like a proof first pretty cool so recording in events like I said this is the aggregate true behavior traits which we apply to the area before so what it does internally it applies the event first and then adds the recorded event to its list we're gonna use that list later on to save the events in the persistent storage we'll get back to the later how we can apply offences internally it uses a method to

00:14:17 get a Getti event get a class from the event and then use a method to apply and then the event name against aggregate so why this is done is that first in first part where you execute your command your only Garlin your business rules it's a separate piece of your aggregate where you cart against every scenario that can't happen and after that after if edit events recorded it you can apply it against the pull request so in this case you're like adding the user ID origin target to the aggregate route so we can

00:14:53 reuse that data later on when you're performing new commands so for example if you had like burlock rest to us proofed it will put this is a proof which saw earlier to true so you can merge the progress later on in a different command and that's how events are applied against aggregates persisting events is done which repositories like the repository we saw earlier you can retrieve pull requests perform a command and then this is also tricked by freak which he he taught me like you can use a try finally method to

00:15:32 let's any exception that happens Cascades but still allow you to persist any events that were recorded against the aggregate so what it basically does be unseen dislike you open a pull request but an exception was strong that you still wanted to like record specific events you record the events first and then let the events cascades through the higher levels of your application and you can react on them rebuilding the aggregates if you saw the the retrieve method here what's a repository basically does is it

00:16:06 takes all of the events from the database or source whatever you're using and it reapplies them to the aggregates before you can reuse them again so it basically loops over the events and calls the apply method every single time so the stage in the aggregate this is restored and you can perform new commands against them and how those events are stores really is called an event store and in fact store can basically be anything it can be a database table a separate source like Redis whatever it is you really want to

00:16:40 store the events and in this particular example I shown you like how to create a a database table real quick and as you can see it is basically a couple of common columns you have just an incremental ID you have a specific ID for the events which you can query against you have a specific event type the name of the event basically you have the aggregate route where ID so you know against which where the event belongs to to which aggregate you have a timestamp to record it and you have the payload

00:17:10 and the payload is basically the event data that was in sight event situation see realized really easy to see I can set there a pen to read only remember the the history never changes you can't delete events you can only add to them can live outside the main system what we mean by that is that an event store really doesn't belong with all the other tails you're using to build your app you can basically take that's events or output it on separate database connection whatever it doesn't really belongs with

00:17:43 all the other ones or you can keep them together whatever you prefer and it's the only part you cannot lose and this is pretty cool as well like because you're deriving all of the data and stage from your your offense you can basically drop all of your other tables you can lose them you can lose all your backups doesn't matter like everything really and you can always rebuild that stage from the events as long as you have the events you can always do whatever you want that's pretty cool so how did the events

00:18:15 are handled in event sauce itself the wrapped and what's called in the domain message and the main messages are really like small wrappers to pass the events around they contain all of the data which we saw in the database in the database table like the event I did event payload the timestamp and aggregate route ID and that's the thing that's being serialized before it stores the event payload I meant now you might wonder like okay we saw a lot about writing now how can we do write operations but how can we do read

00:18:52 operations like how do we display the data from those events in a human readable way and this is where message dispatching and consumers come in so basically what an aggregate routes repository will do behind the scenes is it will take all of the events it has recorded and dispatching them throughout your system and this is done with skulls with like a message dispatcher it can be done asynchronous or synchronous synchronous is when you want to get things happen right away so for example you want to do update some view tables

00:19:28 which will be displayed right after you redirect to through to your view or you can do asynchronous screens in consumers as well and this is like when you want to like send an email informing the maintainer then a new public rest aside happens a notification something like that so you basically have to consumers like I said yes what's called projections projections are the things that update states which can be discarded rebuilt as many times as you want and process managers they listen to events and they

00:20:02 basically before one-time actions things you can only do one time like send an email you don't want to resend emails every single time an event has been restored from an aggregate but you do want to like restore your state from your database like how do you pull across the suit if that data gets lost for example that's right projections come in so like I said projections like some examples could be database tables PDFs files in this search indexes like I'll go Lea elastic search so stuff like that why

00:20:35 are they useful so like I said like they're super optimized you can like reconstitute them like I said you can discard them rebill rebuilt them you can have as money as much as you like the example I showed way at the beginning was a projection that optimized for just specifically the view of a pull request as is but you can basically have as many tables as many projections that I should work and fairly want and you're really optimizing for a few a few part to give you a basic example of how this is done

00:21:11 this is a projection you build at Ballou Crestview that we talked about earlier so when we get a man get a message to domain message we retrieve the event from the message we check which type it is and based on the type we're going to do certain actions and this is rare like for example like an elegant model comes back into play to like create records and and database updated state delete it whatever so rebuilding is pre is unfortunately not baked into the event source library and maybe thinking of doing it in the

00:21:47 extension I'm building I'm currently working on a larval fan sauce extension which is under the event sauce an organization as well it's almost on I hoped I could get it done by now but unfortunately I didn't make it there after conference hopefully so what I figured it was like because I know how the state is built up in the handle method I might just like add a different method to it to know how I can discard the state like delete the database table or whatever so we can really easily destroy the data rebuild it again from a

00:22:22 backup however you want I might look into Internet the different consumer we talked about earlier our process managers and these are one-time actions like I said email notifications builds recurring stuff you only want to happen one time one single time why are you useful like set or one-time actions they handle non user interactions things that users can't do do for you like call source and grids stuff like that and they're really a great way to offloading anything that you don't want your that's really time

00:23:00 consuming that you don't want a user to be worried about when they're doing a certain thing in your in your application everything that can be offloaded to the side a process manager might look like this like pull request notifier we get new polo crest was opened event and we send an email to the maintainer informing and that a new poll Crassus opens so other things that offenses can really do for you is can also like generate commands and events from a Yama file so commands and events are really like very basic things which

00:23:36 your might wasting your time on building you can basically like simply define what they are in a young file an event sauce can generate those classes for you so you don't have to worry about them in the package I'm going to build they'll be the they'll be in Derby command to generate those for you it's pretty cool you can decorate messages with metadata so you don't only ship the data you want from your events but like extra stuff which you want to add on you can have versioning because what might sometimes hapless concurrency

00:24:14 people trying to do the same thing at the same time so you might want fur in your your events um it's basically like an incremental ID in database so you don't have conflicts like saving the same thing at the same time you can use the testing tools this is a pretty cool way it's basically works like in a behavior driven design way like given when 10 and it's just a really nice way to like perform some testing against your aggregates so I basically think like this might be you after you stock let's

00:24:51 go it was a like a lot sorry sorry about it but event sourcing is like a really cool thing I I had like I took a really long time to wrap my head around it it's not forever every single scenario was something you really need to know is that event sourcing really shines in situations where you have like a really rich domain lots of business rules lots of stakeholders at play long-lived apps like short-lived apps I'm not really sure if you've been sourcing is a correct way for that but like definitely

00:25:27 give it a shot give it a chance if you if you want to look into that event sauce ducks has a lot of reading material for it it is like an architectural page which you can use to see or how the audio library was built the lifecycle of like an event source application mchugh loop here has a really cool block as well a lot of like hard core topics around event sourcing how to handle gdpr requests how to handle privacy like encryption stuff like that it's pretty cool much as for us has a really cool block about some

00:26:02 more advanced topics as well which you might might want to check out my buddy frake already built some packages of course like who would you take he built his own events or succession already which is pretty cool which is pretty much done he built his own pragmatic way of handling events even sourcing itself like with event projects breakage was getting really popular really so definitely give that rich other shout as well or you can wait until I finished my even sauce package which should be like

00:26:34 done in a couple of weeks at least that's really it for me right now check out my blog check my sir I'm doing user groups in in Belgium as well in Ghent and enter if you're ever around in Belgium I want to give dr. feel free to Mia I'm authorizing a conference in Europe with freak as well definitely check out this well we have a pretty cool lineup for you totally different conference and Lehrer calm thanks really hope you enjoyed [Applause] you


Highlights

0:01-0:19 πŸ‘” Dries introduces himself and mentions the topic of event sourcing in Laravel.
0:19-0:59 πŸ‘• Dries talks about the purpose of the unique shirt he’s wearing and the focus of his talk.
1:01-1:36 πŸ“š Dries explains the benefits of event sourcing, such as optimized read models and the ability to predict and travel back in time.
1:38-2:19 πŸ—‚οΈ Dries discusses aggregate roots and how they guard against invalid commands.
2:22-3:02 πŸ’Ύ Dries explains how events are recorded and stored in an event store.
3:04-3:37 πŸ“ Dries demonstrates the use of projections and process managers for read and one-time actions.
3:39-4:17 πŸ“¦ Dries mentions additional features of event sourcing, such as generating commands from YAML files and metadata decoration.
4:19-4:41 πŸ“š Dries recommends further reading and mentions related packages and conferences.

Key Insights

πŸ—„οΈ Event sourcing provides a pragmatic way to implement event-driven architectures in Laravel, focusing on code samples rather than theoretical concepts.
βš™οΈ Aggregate roots serve as guards for validating commands and emitting events, ensuring that business rules are enforced.
πŸ“Š Projections optimize read models by storing data in specific tables or indexes, while process managers handle one-time actions like sending emails.
🧾 Event sourcing allows for versioning, metadata decoration, and the generation of commands from YAML files, providing flexibility and extensibility.
πŸ“š Further reading, related packages, and conferences offer valuable resources for those interested in exploring event sourcing in Laravel.