 Okay, thank you. Okay, thank you everyone for coming. The topic here today is called Play with Code Async. Basically, back in January, I presented a topic called Functional Microservices. One of the major complaints I heard is that I showed no clorical code at all in that talk. So this time it's all code and no slides. Who knows about code, I think, I think most of you guys, yeah, one of that. Basically this is a library in clorical that handles the asynchronous communications and this sort of stuff. So the basic building blocks of code async are what we call these goal blocks. Go blocks is essentially a lightweight thread or in other places called green thread or whatever. So basically inside the goal block when some operation blocks, so instead of putting the entire OF thread into sleep, you simply swap out the task and taking on some other things to do. This way you can have multiple green threads on a single OF thread basically. This one central concept here is called channels. So a channel is basically a kind of a message pump. You put something in one end, you take something out from the other end, that's the thing. So basically in the real world, in the day-to-day world, what I found is I think it's most useful for me is that I can nicely separate my application into several layers. The first layer is the business or the code logic and the whatever. There is that you hear the things you do, you do some real stuff. Here you see this is just a simple counter where you can receive command, you can just increase the counter and then you can ask what's the count now and if the input is unknown you can give out an error. So basically here is taking something out of this in channel and when necessarily putting something on the out channel. So this kind of business logic would say they are stream transformers. They take a stream of something coming in and produce a stream of something going out. So the benefit of organizing the business logic this way is that every piece of those are independent of each other. And every piece of this logic you can test them individually, just give them the two channels then you can just send something in and check if the things in the out channel are the expected ones. And then a layer above this are the boundaries. So you can add the boundaries handling of the input output here or just taking whatever in the standard in and putting them into a channel. In this case you don't need to think about any of the processing you need to do afterwards. So this part is simple. You just taking things from the input, put them into a channel and the same with the out one and just taking things out of the channel and just print them out. And then once you have those basic building blocks for the application, then you just connect them together to make the entire application. So here is that I'm getting this channel that is produced out of the standard in and whatever sent into this out channel will be printed to standard out. And here I'm connecting this channel putting into the counter with the one where I'm getting the input together or the use of pipe means I can just take whatever in this channel and send them over to the other one. So now everything connected together, I can just run this counter. So what we can see is just this whole application, issue a command, increase counter, increase counter again, then you just ask for the count. And if you just get some rubbish, you're going to tell me that there's an error in there. So how many of you are still following me? Questions at this point? So the best benefit I get out of this call I think is that I can use the channels as a way to first separate different processing logic into individual functions or individual processes. The third part is an individual not depending on anything else that can be coded and tested independently. Then you use the facilities to connecting all these channels together to form a whole application. If no question, I go ahead to have some closer look at those channels. So at the two end of the channel normally how it works is that you have producer on one end, you have a consumer on the other end. So the producer will put things into the channel and the consumer can take things out of the channel. This is basically just a message, if you can call it a message queue, something. So here is that those channels in the call I think. So when you create a channel, it's simple, just call this channel function. By default the channels are unbuffered. So if you put this thing in without anything taken out, the next time you're putting something in at that point it will get blocked. That means if you have a faster consumer and a faster producer, that means the producer will be slowed down. So we can have a look at how this thing works here. Yes, definitely, I'll show the things in a moment. So I'll just go for show this unbuffered channel first, so let me see if I can get something out of here. Sorry, forgot to connect to the site, forgot to start the site, just a moment, that's right. Really? Oh, sorry, those were something else in a moment. So here I'm running this, you see in the consumer it waits five seconds before taking anything out, and in the producer it's just wait one second to put anything in, and as you can see here in case of the unbuffered channel, this producer is slowed down by the consumer. The producer is still slowed down by the consumer, and we can put in a parameter called buffer. Here we can say the side of the buffer, you want to create a fixed side buffer for the channel. In this case, you can see all the things that are sent into the channel before they're consumed by the consumer. The consumer is slow, they take five seconds for, oh, is this, oh, okay, five seconds, come on, just a while, okay. So this is a fixed buffer, there are also two other kind of buffer, one is called sliding buffer. Sliding buffer means that if you can put something in, if the producer is too quick, the older elements in the buffer will get dropped, so it's called the sliding buffer. We'll see how this thing works. So the same, the things are sending to the input channel without delay, and now we can see maybe number one or two will get dropped, because the buffer only have, there are only two elements, two space in the buffer, so this is the sliding buffer. Sometimes, and also another kind of buffer you can use is called the dropping buffer. The dropping buffer means when the buffer is full and there's more elements coming in, then the new elements coming in will get dropped. See, it's continuing sending something in, okay, so good. So, in the channel, there's always one place available, at least even without the buffer. So you see, we got these two, the three and four are dropped, because there's a dropping buffer, so you can give it different implementation buffer, and the channel may behave differently. And what kind of buffer to choose, depending on the requirement for the application? Okay, this part is good. Any questions on this one? Nope, okay, cool. So instead, in addition to buffers, we can apply a transducer to the channel. That means the sum of in place transformation of the elements can happen when you put something into the channel. For example, we can say we want to increase the number by one for everything inside the channel. So let's have a look at this. Again, we're sending zero to four into the channel. Now let's receive. Okay, the first one we got is one, next one we got two. One second, come on, three, yes. So let's see, we're sending it into zero, one, two, three, four, and we got one, two, three, four, five. That's because we apply this transducer here to increase the number by one for everything we put in. The same thing can do, you can put the filter in as well. You can say just hold. I say I only want to take out the element that is odd. Let's increase the buff a little bit. Again, those things are sending. So now you can see only one and three are taken out of the channel. The other ones are dropped or eliminated by this transducer. Questions here? Okay, cool. Next, I think the most interesting part of this is that the way that how those channels can connect to each other and the way they're connecting the channels, what I see is a way of structuring the application itself. So there are quite a number of ways you can put everything together. There's no code here, just a few diagrams to show how those things can be connected. So the first thing is a simple one, just pipe. Just have two channels on the side, an element taken from one and sent to another. This is called a simple pipe. So the pipe normally looks like this. So basically you have producer putting something in, then you run the pipe that continuously pulling element from this channel to the other one, then consumed by the consumer. There are several use cases in this one. For example, sometimes this out channel may not be within your control and it's not buffered. You may want to add some buffer to it. Then you can create another channel with the buffer. Then use the pipe to connect them together, then putting things into this channel. In this case, it will appear that you're running something with the buffer rather than just the one without the buffer. Just the one simple case. Another one is called mod. Basically you can have one producer to produce something that consumed by a group of consumers. Basically the diagram is like this. So the producer putting something into the channel and this mod function I'm not sure if the right word should be a multiplexer or something. Then you can have another channel to tap into this mod to receive the things produced. To receive the things that channel through this channel. Then you got the one, two, three and this means everything produced put into this channel will be received by all these three receivers. Please. It's quite interesting. Our nation doesn't want too many. But if you will sell some big data, will they receive copy or what kind of reference? I think that depending on the data I think most of the cases because underlying everything put in here is a Java object because Clojure runs on top of a GVM. So it's more likely a reference if it's an object or something or if you put in an integer or a primitive type then probably the copy. It's very clean but I thought maybe you'll create deep copy or something like this. Not really, simply just moving things. Because the channel and those things themselves they don't care about what kind of things you put in there. They simply receive something from here and then just put it in the three things here. So I say in the GVM world it's more likely to be a reference to an object that got carried through. I don't think it cares about the deep copies of things like that. And another set of things is called Mix. Basically this means you can have multiple producers to produce things that are consumed by a single consumer. Let's go to the end. So it's like this. You have this channel that is consumed by this consumer then you can create a mix and have those channels added to the mix. So when anything produced by those producers will be received by this one consumer. So it's kind of the mirror of the previous one. And the next is called PubSub. This is kind of the most interesting one we have. Sorry. So for this one is that everything produced by this producer you can create what we call the publication supplied with a topic function. That means every element come in here will assign the topic. And then you can create the subscribers to those topics. One common usage is that here you may stream in data. Let's say every element is something related to a specific user. Then you can say those elements here are identified by their username. The username will become the topics and then you can have the subscribers subscribed to the particular users. As I said, maybe the user one is the user two and the user three. So that's basically it questions. Okay. Basically the main takeaway here is that what I got from here is the way that it helps me to structure my application. So I can have the three ladies very clearly defined in my app. The core logic, the boundaries. The boundaries is that we need to talk to the outside world. It could be the standard in-out error. It could be socket, it could be Kafka, it could be anything. And here just have everything connected together to make the whole application. And the biggest benefit is that every piece of this, those boundary connecting points or the business logic here, they can all independently test it and have their correctness very easily verified. I think that's the end of it. Thank you. Thank you.