 Welcome to my presentation on Dapper, which we used at iHomer for a product that we developed for customer of ours. Yeah, thank you for having me. Yeah, I'm Michiel. And again, I'm passionate about Microsoft since 2004. I'm 43 years old, working in .NET Core, .NET framework before that since 2004. Worked as a developer architect for multiple companies, larger companies within Netherlands. And I was mainly responsible for a couple of big companies that for their public facing websites, or some insurance companies and an energy company. I love tech. I not only programming, also other stuff like taking things apart, working on servers, working on cars, whatever. I'm very busy with my family life. I have two beautiful daughters, Kate and Olivia. And I like to ride a bike when I have some time off to get my head clear, etc. And I'm passionate about helping students with getting into an academy program that we have at iHomer. And before iHomer, iHomer was, I was a teacher at a bachelor's university, or an higher school in the Netherlands, in Breida. And since two years, I'm working for iHomer as a consultant. So who is iHomer? Yeah, we are with 50 plus consultants within our company in the Netherlands. Mainly only software engineers and UX designers. And what we are, we are all participants in our company. So we don't have any directors or managers or each department or whatever. We're just driving this company with 50 people. And as a basic, that's what iHomer stands for. We had a home shoring approach. And that means that we only work from home, or at least most of the time we work from home. And that's before the corona crisis. So we had a standard like 15 years ago, that we have an opinion that we can always work from a place that is nearest to us. And that's how we try to work in short teams with short lines. And we try to prioritize our humans as first. And also very close contact with our customers. So it's not about money and driving profit. It's about getting the correct project done for our customers with our customers. Today, I'm going to talk to you about a customer case that we built for a customer of ours. Unfortunately, I cannot tell you about the name of the company, but I can tell you what the solution is that we have built. It's because of NDA reasons that we cannot mention the customer. It's a customer which operates in a small to medium business market. And when another company needs money or investment for their business, this company will help you to realize your financing. And after when the financing is realized through a crowdfunding kind of way, the funding is realized. Then investors who have a sort of stake or share or certificate or whatever you call it in a company, they can trade with those stakes and those shares. And that's special about this company because it's not standard that you can trade afterwards after you did a crowdfunding kind of thing. So we built a trading platform for them. And what's important for them is that everything is in the right order and it's all correct and consistent. So you can realize that if you do a trading, like when I'm trading for a certain share or another person is also trading for the same share, it's important that the timing of these shares is correct and that there's no gap between having money or don't have money or having shares or shares are gone or whatever. It needs to be correct and consistent. And it needs to be traceable and auditable. One of the requirements is that it should be in Azure and it should be in .NET or at least not fully in .NET, but it should be in a Microsoft technology stack because the company is working with Microsoft systems and they want to keep the stack as close to their other systems as possible. So we chose for .NET Core because it's the latest .NET stack, of course, and we chose for Azure Container Apps. When we start a new project for our customers, we always try to define a sort of new mission statement, ambition, what this product does and what this product is meant for. And together with our UX designers, we try to come up with a plan which is iterative with designing a product and then developing it so that we get the best result for our customers. Because it's a trading system, we figured out that we can use domain-driven design, so DDD. And we use the processes called event storming to determine which actors are in the system, which domains are there, and eventually which microservices exist within the solution. So based on that, we can define actors, aggregates, commands like creating an account or deposit cache or having an instrument. And from there, we can create views or projections that the user or the actor can see and can interact with. So why Dapper? Yeah, that's interesting. We started with a team of about five people, five developers, and I started with two colleagues of mine who are very majestic Java developers or Node.NET developers. And in Spin Zero, we defined, okay, we need to build an event-driven system also in the design phase with the event storming. We figured out it need to be event-driven. And those two Java developers had experience with Axon. And Axon is an event-driven system. So we were on the hunt in .NET to have an event-driven system or framework which we can use for building the solution. And at first glance, we couldn't find something that was similar to Axon, or at least we couldn't find something that is very similar and behaves like Axon. So the two Java developers were like, okay, we can create ourselves and we create a .NET framework and we try to build one like an open source framework or something and build something new. On the other hand, me is like, okay, I have 20 years of development experience in .NET. I heard about Dapper and I said, okay, I will set up the infrastructure and we'll use Dapper for the infrastructure because I thought it was cool and I wanted to work with this framework because of the microservices and the service costs, etc. But I wasn't that experienced with Dapper at all. And after a couple of sprints of them developing a framework, and me developing the infrastructure, we figured out that the active framework within Dapper might be a perfect fit for our event-driven event-based system. So after a couple of sprints, we figured out, okay, this finally is the best way forward. So we stopped developing a framework and we created everything on the active framework of Dapper. Next, I want to talk to you about the architecture that we built and designed during building. And we use IcePanel for a sort of overview of that architecture. And next slide, I will show you a video of our architecture. So what you hear here is the first level of architecture, and you see the two actors, investor and employee, and some external systems like Dynamics 365 and our step frame, step system, which complies of a lot of microservices which you see in the background. And when you zoom in on a microservice, you see the dependencies that they have on the other components that we have. So in key vaults, service bus, events, et cetera, and some external events that they need to question. We also have a blueprint, which is a sort of what can happen if all is implemented, kind of standard thingy. And what you hear here is our CQRS mutation stuff running through the system. So from a mutation, we call the position servers and mutation calls an aggregate. And it's routed to the event bus and to an event dispatcher. And this dispatcher can send to multiple subscribers like event handler or a Saga manager and can send those events to the database. And that database saves the projection and that can be queried via the query of the Kafka well into our back office. And of course, every event that is created is stored in an event database. So that's just a flat table of events. Next up, I want to, I recorded a demo for you guys to see how the system, some functionality is implemented and see what our system does at least. We have two actors in here. That is an investor, which is Bob. And we have Alice, which is an employee of the company and has the back office. So I will start now the demo. Now you see all the services that have health checks on them and see if they're healthy. And the interesting, the last one is the gateway. And the gateway is a stitch up of all our microservices into one GraphQL service at the front. Next slide, I will talk to you about how stitching works, etc. When I get my password right, we log in as Alice as a back office employee. And in this back office, you can manage all of our issuers, so companies who have shares. Next I will log in as a portal, sign up Alice and log in with Bob. Alice and Bob, the traditional users within the... Okay, so first we go into the back office. What you will see is all the different screens that we have. And every screen is just an overview of items that you can manage. So financial instruments are like shares. Offerings are like new openings to issue a new share. Trading is of course something that you can do afterwards. You have an offering created. As shares can be sold, etc. On working days, so which days are closed. And this is also important trading hours, because you can always trade between 10 o'clock and 4 o'clock in the evening. Account information. These are actually our position accounts. And this is the ZJCN that's the company itself. It's not actually that name, but we renamed it of course. And this has a cash position or an instrument position. So how much cash is in your account and how much... It's like a bank account, but then in a soft virtual way. MCCon contains issues and cash. Okay, I'm going to create an offering now. And we'll show you that there's no position yet available. Oh, okay. I forgot about this. I wanted to show you what the initial state is between the services and how they communicate. Just with SIPKIN, this is a standard thing that we implemented in our solution just to see the overview of all of the services that are interconnected with each other. So you see a lot of lines. It's mainly health checks because there's no actual events happening yet. And we'll just now add an instrument to this conference company. And we'll add 100 items. Okay, after refresh, you don't see anything, but after refresh you see the position, that's the 100. And you see one mutation that something is added to this position account. Position account of conference. So our conference is creating a new offering and it has no subscriptions yet. So what we do now is Bob will create a subscription on this. We'll see in his position account that he has 100,000 euros, but no instruments yet. So he now will subscribe on this offering and he will get 30 items, 30 shares. Okay, he subscribed. And what you see now is that there's only one subscription now, which is just created, have a state of created. And we'll now just confirm the subscription. So Bob actually really wants this and he confirms that he has 30 subscriptions. But there's no reservation yet. There's only subscription. There's nothing closed yet. So we'll move on now in the back office again. And we go to the offering and we'll close the offering now because it's now open. So everything is done and all of the shares are subscribed and we can now close the offer. And what you now see is that there is a reservation of 30. And we confirm it. There are a couple of steps in between the process of confirming and having the subscription. It's not fully confirmed yet of closed process yet. So it's only reserved now that the money is reserved and there's no instruments yet traded or changed accounts. It's only 3000 euros is reserved. Now we process it and this means that the actual money is transferred from the one account to the other account and that the instrument is also being transferred. So this is now done, completed. And what you see now at Bob's side, I think, oh maybe I will show the transaction. So you see the different position count from and to. And what you see here is that there is now nothing reserved anymore, but there is 3000 euros deducted from my position, but also 30 euros. 3000 euros goes to the conference company and 30 euros goes to the company itself, which I cannot say the name of. In this case it's ZGACM. So we get 30 euros. And the conference company has 3000 euros and 30 stocks less because it had a hundred as a base and 30 was deducted from it. But that was our demo. I'll show you the Zipkin again because, at 11 o'clock of course, very strange to see my demo again. And you see now that there are a lot of actors created within the process of everything. So every time a position account is starched or an offering is starched, then there is an actor created to manage the state of that thing. So a position account is an aggregate in our system, position account of pop in this case, but that keeps alive until whenever in time. So every time a pop buys something or sells something, then this position account is being modified. So that's the interesting thing about this actor framework. Okay, I'll go to the next slide for you. So which type of components did we use? So a lot of things that we did is actors. So all of our aggregates and we also have SAGAs and SAGAM managers are all actors in our system. They have state. So they use a state store. Locally we use Redis and in Azure also Redis. But for instance, Popsup is locally on RevitonQ and in Azure Container Apps it's Azure Service Bus. We heavily rely on the, of course, on the Popsup and configuration. So all the configuration settings are stored in AppConfig within Azure and within Redis on the local site. And we also use reminders to, for instance, to, we call it, to, to get a sort of, for instance, that offering has a, as an expiration of 30 days. So we need to set a reminder that after 30 days the state is changed from open to closed because the reminders pushes it to close. Distributed log is also one thing that we not implemented yet, but we need to implement it because of the, the locking mechanisms that we need for our solution. So, my head is again in the way. CQRS and GraphQL are a perfect fit for us. So we use GraphQL for our commands and queries. And that's a direct match to mutations and projections in our CQRS framework. And we use Hot Chocolate as a GraphQL solution in our system. And now I'll just start the demo, or at least a video about our solution and how, how our solution is built up. So you see API gateways, which is, contains really an envoy and a stitching API of GraphQL. We have building blocks, services and a front end, which is contained in the web project. Yeah. We will now zoom into the, to the services and we go to the position accounts. And I will show you the CQRS steps that, that we follow when a mutation is created. We go to the mutation and we add a cache deposit. And what you see is that there, there is a, the first we get the current aggregate. So Bob's aggregate is getting from the state management and, and read into the memory of this service. And we handle the cache command. And then cache command is handled within the aggregate. And in this case, we get a command inside of our methods. And we check if the, the state is, if the, the aggregate is still created or open. And we send an event to our event service, to our event source aggregate. And this event source aggregate is a, is a building block within our, so every, every service uses this. And this will assist our event into the database of all the events, just the flat table of events, which is stored in, in JSON, et cetera. And we publish the event to our event bus. And the topic name is actually the, the name of the aggregate that the event is published to. Yeah. And the, the Pub sub name, that's the, the name within Dapper that knows which event bus we use. Then we have a, on the controller side, we have an event dispatcher, which gets all of the events that are coming from the events Pub sub. So we subscribe to this Pub sub and we have an event listener. And in this case, we only have one event listener, you can have multiple. And we handle this event to just write to the database into the position account table. And I think we also write our limitation. What's important to, to realize is that on the publish event dispatcher, you can only subscribe once on a topic within Dapper. In this case, we only have one event handler listening to this, to this event from the, from the Pub sub mechanism. But in our secret system, we need sometimes multiple listeners to, to listen to certain events. So we created this component, this event dispatcher to dispatch events to different sources. Okay. In this case, I will show you one that has, that has multiple. So in this case, the confirm subscription. So we go to the handle subscription of the offering aggregate. And we check if it's still a valid subscription and if it's still created and not closed. And we create an event for that, just a subscription confirmed event. Oh, no, this is the standard created event stuff. So it's the center of the event service, et cetera. And then the event dispatcher for this case is, is called. So the subscription confirmed event dispatcher. And we have a offering subscription event handler, which is just written to the database. And the other one is the reserve cash position Saga manager, which handles our position accounts. So we go to the implementation and we see here that we are getting the event itself get it from the state because we need that to get some values like the position account ID and some other stuff that we need. And based on that position account, we get the position aggregate. So in this case, maybe pop with that ID. And we handle the reserve. And this reserve, this handling, this checks if there's sufficient cash cash in this account. And if it's not closed it again, and if it succeeded, then it's confirmed and it will stop with the method and will stop. If it's not, if it doesn't have enough cash, it will continue and send out a rejection. As talked about in our previous video that I showed you, we have a gateway API, which acts as a sort of proxy in between our front-end and our services, our microservices. That stitches up all of our microservices into one big API towards the front-end. And in this case, we can stitch up two services that have a sort of connection to each other, like an order has a, an order service has a financial instrument ID. And I want the name of that financial instrument also in that schema of that order service. And that's, that's doable with this, this stitching solution. And that helps us in preventing having multiple interservice calls between services and keep the services isolated from each other. What I want to tell you about is that we also added some things to the actors. We created a sort of generic class stop actor, which is based on the actor framework, but something extra. And in this way, we can create unit tests, which are very, very important for event-based system, because we need to be certain that all of our commands and events are handled well. And for this one, we needed to add some mocked state manager to, to mock the state manager before we do a test. And in that way, we can create small tests for all of our commands to be handled correctly. So that's an interesting thing that we can, that I can mention. Now we're reaching the end now. Yeah, this platform is now underway for about a year now. And in the first year, we did a lot of sort of proof of concepts. And the solution that you just saw was already like multiple proof of concepts together. So the offering, the trading, all of these, these mechanisms we needed to try out with our solution. And we're actually now building upon this solution, actually creating a new solution and moving all of those parts that we just created into our new solution. And we're finalizing a MVP for this year for this company. But we see at IOMA, we see other opportunities also for these kind of frameworks, because of course, DAPRO is not only .NET, but can also be used for other languages and other frameworks. So we need to see a lot of potential in that. And I'd like to thank you for your time and your attention for this presentation. So if any questions arrived and the future me will answer them. Thank you. Bye bye.