 So thanks, everybody, for being here today. And I really like the setup of the conference. It's one of the best one I ever have been for. So kudos to the organizers. And my name is Vincenzo Cianese. I'm an Italian software developer. And during the day, I work for APR, which is a company that provides you powerful APIs designed stuck for developers. And does anybody know or use APR here? Could you please raise your hand, eventually? OK. Well, eventually, later, the presentation, I'd love to talk with you if you would like to share the experiences or any feedback about the product. And those are my references. I have a GitHub account, a Twitter one, and a blog where I usually write things I've been working on in the last days. So what we're going to do, I'm going to talk about communicating sequential processing, give you some background on the problem that it's trying to solve, what is about it, how is to work with, and as well give you some example in JavaScript using DS6, of course. However, the concept I will be explaining here can be applied in any programming language as long as they have some particular tools. And also, you can apply those things on the back end, on the front end, it doesn't really matter. So to start up with, we have a problem, sharing the memory. This is the kind of problem that usually you have when you're trying to do love level concurrency programs. You have a lot of different things going on at the same time, and you don't really know what is doing what. And in order to communicate between each other, the threads, the green fiber, whatever the way you want to call it, they use the memory as a sharing mechanism. And it all goes down to non-determinism, which can ultimately bring you to race conditions and eventually to deadlocks. And because everything about these problems is on non-determinism, it means that those things are really, really difficult to reproduce. And where those ones are really, really difficult to reproduce, it means they are difficult to debug. And ultimately, you cannot rewrite the tests, regression tests. And it all goes down that probably your software will be less reliable. And in the past, I mean, there is a lot of different solutions to try to handle those things. Mutex, semaphore, some of better than others. But ultimately, at the end of the day, they all share a common set of problems. First of all, they are complex, and there is a lot of conceptual overhead that you have to add into. Let's say you want to update a value, and it means you have to acquire the lock mechanism, open it, change the value, close the lock, and release it. And also, you should make sure that you're for handling an exception, you should always release the lock, or you will get deadlocks. Also, they are leaky. Usually, this context is stored into an opaque object that you probably might want to pass into your function chain. It means they cannot be really used. And at the end, all those mechanisms, they don't really play well together. If one function is using Mutex 6 and another is using semaphores, it doesn't guarantee you that those one are going to block each other eventually. But wait a moment. You might now ask yourself, we are using JavaScript. So what are you even talking about? The problem has been solved, which, I mean, you're right. We know that JavaScript is asynchronous, but it's not parallel. To be more precise, the runtime is asynchronous, but it's not parallel. And it means that in a particular instant of a moment, only one of your function, only one of our line of code is being executed. That might seem like a tremendous limitation, but it's actually a huge freedom, a freedom from having to deal with dread complexity, which we have seen in the above slides. But the thing that in a single instant, only one function, only one line of code is being executed, it doesn't mean that in a period of time, two high-level tasks are being executed at the same time. And one example would be the browser windows. In a single or instant, of course, it is being executed the rendering function or eventually your custom code. But if you ever look from a high-level perspective, you can see two things happening at the same time, the rendering and the logic's function. And just to make you another example, an example will probably clarify to make you understand the concept of high-level task. So let's say I want to make an Azure request and on the same time, of course, the browser window should repaint itself. If I will take the most naive scheduling algorithm which would execute the first one completely and then the second one, and here I'm using the number to give you the idea that every high-level task can be decomposed into micro tasks which cannot be blocked anymore. Taking the most naive schedule, it would lead to something like this, which would mean I'm executing all the Azure requests at first and then repainting the window, which is okay, but probably the user reaction would be something like this because I cannot repaint the window, I cannot click the button, I cannot scroll the page. On the other hand, if I try to rearrange the task, probably interleaving those ones in this way, the system is going to take exactly the same amount of time, but this time, probably the user experience will be something different because from a high-level perspective, they looks like they're happening at the same time. So ultimately, I mean, with JavaScript, you really don't really have to deal with threat complexity, but it is not a set of problem that you should remember and is about the coordination of the concurrency. And that's the hard part of our job. I mean, spawning two Azure requests to a remote server, that's the easy part. The hard part is making sure that the responses are sequenced correct. And how do we coordinate the concurrency with JavaScript? And there is a number of ways, and the most intrinsic in the language is the notion of collaboration, of course, which basically is the concept of having a clear separation between what's happening now and what's gonna happen next using a function which is being pulled out and reinserted into your queue eventually. I will not really spend much time explaining to you why, in my opinion, you should not really use the callbacks anymore, but just to give you some examples, as you can see, the error logic is being repeated every single time. After each callback, I have to check for an error and handle the error eventually. And also, of course, the part I'm gonna do that I think everybody's familiar with, there is a lot of other things why you should not use the callbacks, and it all goes down that you don't really have a stack. I won't go further on that. If you're interested, I had another presentation in the past which you might be interested in looking into. If I then, eventually, I try to reorganize to this code from the callback of callback of callback into a vertical chain of composable function using the promises, the games level up significantly. And the promises are great because the main concept is about encapsulating an asynchronous value which will happen in the future. But until that, you still have an object that can be passed as a function parameter or in the way you want to use it, and also they restore the testability in the asynchronous flow. Because with the promises, you can throw exception, you can catch exception, which is a totally different experience. The promises are great. Unfortunately, not everybody's understanding that because most of the people is just looking to the API side of the promises, which probably I might agree that actually is pretty horrible. But they are looking to the wrong side of the promises. The promises are great because they hide the time complexity, giving you an object that you can use in the way you want. And even if we level up the game with the promises, there is a nice quote from Kyle Simpson, which says, in the moment in which your brain starts to reason in a different way than the JavaScript engine, that's where the bugs start. And usually the brain reason in an asynchronous way, and the code is asynchronous. So while the generator is a new concept and it's not really related to the asynchronous flow, when you use it with the promises, they provide you a very powerful mechanism to handle those things. And I will not go into, but basically the idea is that every time I encounter a yield function, the function is going to be posted. But it's not going to block my entire application, just the function is gonna be locally posted. And then I have a runner, a function outside, which is coordinating the execution and the posting of the promises, which will be resolved for me. And as you can see, this is asynchronous code in a synchronous fashion way. And it's more and more easy to reason about in this way. The problem here is that you still have to write your runner function and it's not actually terrible code. It's 20 line, you can write it by yourself, but some people talk it was so blocking that probably we're heading to the async await keyword. And as you can see, the code is almost the same. The only thing that is changing over here is the use of the keywords. But there is a trade-off using async await. The keywords async await are resolving the promises is in the most naive schedule. While with generators, you can always provide your runner function and arrange your asynchronous flow in the way you want. And that's the problem that we were showing before in the slide of Azure Request and eventually the rendering function. So but promises still have some limitations. They cannot handle everything. And the most simple example is that the promise don't really play well with the events. If we have a look to this small snippet of code, I'm creating a promise and inside that, I'm binding on an event handler on the click. And if eventually the click, the class name of the object is going to match a particular string, I will resolve the promise and if not, I'm gonna reject it. And if we do try this thing live eventually, you can see that the first time is total locates working as expected. But if I try it one more time, it's not working anymore. And the reason for that is that by specification, the promises can be resolved only once. And it's not really a limitation. That's what the promises were meant to. There is a reason why you cannot really resolve a promise twice. I won't go into the details. You can catch me later if eventually if you're interested, but the idea that they take away here is that the promises don't work with the events. Another way to organize your code eventually will be inverting the flow. I will at first binding the event, then creating the promises and resolve it inside. But as you can see here, I'm creating and consuming the promises in the same function. So why should I even bother creating a promise? It doesn't make any sense. But at least from a user's perspective, this is working correctly because I'm creating a promise every single time. So the idea here is that we need an high-golder pattern in order to handle the events. And one way that you saw, of course, is that if you think about it from a high-level perspective, we have stream of events, stream of data, and also a single value can be seen as a stream, as a single value stream. So they ultimately all decompose to the same concept. One of those patterns, of course, we saw that for the most of the conference is the observable, which has been materialized into RxJS. And the second one is communicating sequential processes, which is the one I would like to talk with you today. And the reason why I am so in love with the CSP is that they are really declarative, and they have a super simple API. And I'm kind of dissatisfied with reactive streams. I will not shade here my opinion because I don't want to influence you. But if you're interested, make sure to catch me up so that I can explain my concerns. So how do we start with CSP? And the best way to explain this one is the concept of pipes. And by pipes, I mean the batch pipes in your terminal. A quick review on the features of the pipes is that, first of all, they are really simple. You just need one character to make the pipe mechanism work. The second one is that they are composable. You can do piping, piping, piping, piping, everything, every time you want, and you don't really care about the complexity of the chain. And they also are parallel. Once I hold off a value to the stream, I can work on the next line. And the second program is not blocked from my computation. And they are not leaky. As long as you respect the interface boundaries, that's totally OK. Those can be even wrote in different programming languages. I don't really care. And those concepts are really intrinsic into CSP, just within your same JavaScript program. So again, that's the main takeaway. And what are the primitives of CSP? Well, of course, before digging into one important thing is that the CSP is not a really intrinsic computer technology technique. It's a math. It's an algebra which has been described by Tony Hall. And there is the original paper that you might want to look into, but we will stick to the pragmatic side. And the reason why I want to point out that it's a math, it's an algebra that is an entire notation. There are two rims about the CSP, is that it's definitely more easy to reason about and it's proven to work. It works because the math is demonstrating it. It's not just happened to work, which unfortunately is the way usually sometimes the computer engineering is working. It happens to work so good for us. So we do have the processes as a first primitive. And the first thing to point it out is that those are not your operating system processes. It's an entity executing a code into your JavaScript or the program in the programming language that you prefer. And the second one is that they cannot share memory. It means that if a process has got value, no other process can access to it. And on the other hand, if you hold off a value from a process, you cannot do anything else with that. And the second one is the channels. And the channel sees the way the process communicates between them. You can pass data structure, any value that you want, as long the language will let you. Eventually, you can also pass pointers, but that's your fault. You're sharing the memory in this case. And also, they have an intrinsic configurable blocking mechanism, which is called the back pressure, which is not really, really easy to do that with observables, or at least so far. So the basic pattern to passing a message is, of course, the one-on-one. A process is producing a message, and there is another process waiting for the message. And the interesting thing is that, let's say the first process is producing a value. As long nobody is ready to receive the message, the first process is going to be blocked. I cannot even try to send a message if somebody is not ready to take it away. And also, if we have a look to one too many scenarios, another interesting thing is that, once you hold off a value from the channel, the value is lost. In this example, a process is producing a value, and the first one on the small line is taking the value, and then the value disappears from the channel. The other two processes won't be able to catch that. So the channel is not a mailbox. And of course, you can have many to one, many processes putting down messages. And if those ones, if the producing processes are floating the channel with messages, I don't really have to care about floating, because the way CSPs work is that the process will block if nobody is ready to catch the value. And of course, many to many, which follows the rules that I saw you before. But now, let's see if I can make you a live example about what I'm talking about. And here, hopefully, you should be able to see that. OK. So the first thing, of course, is requiring the libraries. I will go into that later. OK, got it. I have no idea how to do that in Visual Studio Code. One more time, which is not working. OK, there is no shortcut. That's the reason. Is that OK now? Good to know. So requiring the libraries. And here, as a library, I'm using JS, CSP. But there are plenty of them. And then, let's say, I have a producer and a consumer. So what I'm going to do here. So while two, I'm going to yield. Let's put it this way. I'm going to create a value, create a channel, and put the value here. Not on the other hand. On the consumer comes the value you'll take from the channel. And at the end, dot log value. If I did everything correctly, that's a most simple example. Basically, a process is producing a value, and the other one is waiting for it. And there are interesting here. I think this is the first time that you see while true in a JavaScript program. Because usually you say, I cannot do that. I will halt the event loop. With CSP, this is not happening anymore. Because thanks to the generators and the concept of suspending a local function, this can happen. You can again use the while true, eventually. And let's now do some more interesting thing. For example, let's say the producer is putting values as fast as he can. But for some reason, my consumer, it's slow. It's not able to take more than one value per second. And here, you can see that thanks to the intrinsic way, the CSP work, the producer function will be blocked every time. Because nobody's ready to take the value. So you get this blocking mechanism, 4.3, which is not really easy to get with RXJS. I mean, you get floating with that. And also, another interesting example, let's try to generalize this function. I'm going to put you here. And I'll take a consumer name. I have an idea how, OK, old fashioned way. I'm going to make consumer name. And then let's say I have two consumers. So consumer, one consumer, two. Line 10. Right. Good-living compiler. So now you can see I have got two consumers. And the interesting thing is that if you see that once a process is taking off a value, the other process lose the value, and it's taking the next one. This is another example of the thing that I told you before. And also, one last live example would be that the CSP can work natively with transducer. So it means that if I do that, I want to just print out the multiple of six. I will now get the multiple of six. And the interesting thing here is that thanks to the transducer, you are totally independent on the library you want to use. While on the other hand, usually with RXJS, you have to use the libraries, the function, the filtering stuff that the library is giving to you. But there is also something more interesting over here. As I said, I can close this one. As I said you before, the CSP are a high level order pattern. And how to demonstrate you that? I have this simple example over here. I guess everybody is familiar with the sync library, which is a library to help you handle the concurrency using the old callback fashion with way. And there is a particular function called parallel, which is executing all your function one after one and then waiting for all of them to complete in order to use your callback. And if you have a look into the inner implementation, of course, there is an internal queue. I mean, it's not really easy. There is a lot of smart people behind that. But ultimately, it's hard. With CSP, I can implement the same thing in less than 30 line of codes. If I go over here, it's super simple. I'm creating here a channel. Then I'm spawning all the function that the user is passing to me and put a value on a channel once the function is complete. And then I have the intrinsic blocking mechanism because I have to wait for all of them. And once that is happening, I can close the channel and call the original callback. And that's really, really easy to verify. The output is the same, which proves it works. I mean, hopefully. And another example is that, again, it's in high level order pattern. It means that just like the way I do with every XJS, I can define a from even function here, which is basically creating a channel, adding an even listener, and once I get the event, I can put a value on the channel. And then, of course, these work in the way it should. And we get also here, like in XJS, you can mix the type of the streams you want, data, or events, case strokes, mouse events. And so what's the take away over here? The first of all is that there is a mud behind that. It's not just happening to work because it should. The second one is that it's simple, at least in my opinion, it's simple and imperative API compared to a XJS. My point is that with just three functions that we saw, creating a channel, take and put, we were able to reproduce in a very easy way concurrency mechanism. On the other hand, I mean, I don't mean in a bad way there is absolutely smarter people than me, but if you ever looked at the API, there is a lot going on. It's not really that easy. I can scroll down for other six or seven seconds, but I mean, I guess you get a point. There is the built-in back pressure, which means I have this intrinsic blocking mechanism, which is not halting my haven't loop, but just my local function, which means if I cannot handle the value I'm passing me, I won't even let you pass the value. And this is interesting because every program can work in some parallel way as long they don't need to communicate. The only time you block is that when you have to synchronize. And they also have a transducer support, which is probably going to ride really high in the next couple of months. And also so far, it's the highest order pattern I ever found. I mean, with just four functions, you can re-implement most of the 19% of the concept used in RXJS, you can implement the promise behavior, you can implement asynchronous coordination for callbacks. And it's using production. I mean, this is not a concept coming from nowhere and nobody's using it. CircleCI, for example, it's a very famous website, which is actively using CSP as the only way they coordinate their concurrency. On both the front end and the back end. And by the way, the back end is totally open source on GitHub. You might be really being interested in that. But what's wrong? I mean, what is preventing us? So first of all, it's kind of an idea from a future. I mean, at least in JavaScript. You won't find really to use libraries with the most common concept. As you saw before, we had to re-implement the from event function. You won't find this one for free on the web. So if you're looking for a re-demade library, don't go for that yet. There are different opinion-mated implementation. Somebody is using the generators with the yield keyword. Somebody is using the async await. Somebody is using the old fashion at callbacks. There is no a single way where the community decided to converge. There is a lot going on. And also we are lacking the integration. A question would be how do I plug those things eventually into my Redux application, into my React application? We don't really know, which might be a problem. That's the point that it's an idea from the future. And that's why I mean, we want you. I mean, the best way to understand the way CSP work, it's play with that. And you will get familiar and hopefully you should be able to understand the power of that's so simple and it's proven to work. And that's all I have to show you. Just one last thing that probably you won't even care about. And I have a friend who has kept me explicitly to do that. He's having trouble and he's probably watching the presentation here. So, Gianluigi, please take care of you and get well very soon. And that's all I have for you. I hope you enjoyed it and you will enjoy the rest of the presentation, of the conference. Couple of questions. In the demo you used JS CSP and you said there are other libraries available. Why did you choose JS CSP? Well, that's a personal choice, but the reason why I, oh, first of all, we are using CSP in production. So I'm not just playing with that. So I have a bit of experience, but of course I'm not the master over here. And the reason why I decided to seek with RXJS, it's, as I said before, the way I sync a weight work is that it's resolving the stuff in the most naive way, just one after another. There are some edge cases where you want to really dictate the way you want to flow to go. And I can, eventually, if you catch me up later, I can make you really examples which will probably clarify why I need those special stuff. But that's my personal takeaway. You might go in the way you want. Thank you. When I first saw promises, it was like a heavenly choir started to sing and a bright light appeared on the horizon. I know a lot of advocates of CSP are pretty down on promises, but you seem less down on them. Can you talk a little bit more about that? Well, as I said before, the promises cannot really handle all the cases. The events are one of them. And the promises, the events are one of them. And also, in the example I showed you before, I'm chaining the stuff, then, then, then, but after the four or five level of chaining, you start to lose the track. That's the point. So, while with the promises, you tend to write, you tend to make your code as synchronous, behave like synchronous way, the idea behind CSP is that, hey, everybody goes his stuff. We do not talk to each other as long as we don't really have to communicate. That's the good thing. It kind of changes your mindset. Let's try to be no blocking between each other as long as possible. The takeaway is that as long as you don't really need to communicate, do not rely on each other. And once this mindset goes into your mind, it really changes the way you write the code. As I said, it's a mat. It's not a bra library. That's the best thing. Excellent. Thank you very much. Give it up for Vincenzo, ladies and gentlemen.