 Cool. So, yeah, I'm Matteo, hi everyone. I work for AlphaSites here in London. I do mainly Rails and Ember stuff, more Rails now, but I like to do more Ember in the future. Today I'm going to talk to you about WebSockets and Ember data. What does it mean to try to get some different sources of data other than the typical, you know, rest HTTP response from the server and which pitfalls you may encounter while trying it? So, yeah, this is a little bit about me. By the way, we are hiring as well. So, okay. So, let's jump in. So, what you're used to as an Ember developer, but I mean, every client writing developer knows that when you write a, when you want to create a resource, what you typically do is you create an object, for example, in Ember. Let's say you create a task and then you post the server, you know, you're going to have your tasks route, and then the server creates the task, gives you back the JSON response, and then the client will take care of updating the object that it created before. That's how Ember data works. And this is how like the Ember data expects the data to flow. So, this is an example of the code. So, you have your create record method, and then at the beginning, the IDE is not present. Then you save it, and then in your, when your promise results, which means that the server has respond with some JSON, which will represent the task, probably. Then you will have your IDE. So, the task will have updated its attributes from what's coming from the server. So, let's say now you want to have, you want to have data coming live from the server. Why? Because maybe you want to make your application live, right? So, you have multiple clients connected to the application, and you want to have data. For example, someone creates a task, and someone else is looking at the list, and he wants to see that task coming up in the list without doing anything. So, what you're going to do, you're probably going to, all your clients are going to create a connection with the server. Then, if somebody creates a task, you're going to, the simplest thing you can do is just do your usual pause request to the server. The server creates the tasks, and then it sends to the same client, but also all the other connected clients a payload of the JSON representing that resource. So, you will have a representation of that task that you can use in your application. Now, EmberData has a handy method called push payload. So, for simplicity purposes, I've chosen pusher because it's very simple. It has a handy API, but this talk can be used for any kind of web socket connection, so live data coming from the same connection. But with pusher, the way you do it is you basically define these callbacks. So, you subscribe to channels, and then you get this data on the client, and whenever data comes, this callback is going to get called. So, you can use your push payload function, and anything that comes from the server, it will be interpreted as the same if it came from our REST HTTP response. It will be the same. So, it's the same like the idea at the beginning is not set, then you save it, and then you wait, which means like as soon as your server, sorry, as pusher sends the data, your task will have its ID. And this is true for any client connected. So, you will have your task with the ID set. Now, mixing these two approaches has some problems because EmberData is, in order to be fast and make your application for your snap is going to create immediately a record in your application, and then it will update it behind the scenes without you noticing. So, it will give it an ID, and you don't know it. And so, when then the, if pusher comes before this, it can happen that there are two records. I can show it to you. So, I have an application here. Now, whoops, sorry. So, what's going to happen? Well, if it's taking too much time, I can just, well, anyway, let's see. Let's see if it doesn't take too much. So, I have my, this is an application we use internally at AlphaSites to like track tasks and stuff like that. So, the way it works, if I, if I'm going to add something, this is test. So, okay. You saw that there is flickered. Let me try again. So, the way I did it, basically, is maybe it's, it's a bit slow with pusher. So, it's coming late. Maybe the connection is a bit slow. Anyway, I added a slip here to slow the server. But the purpose was that basically, if the client, if pusher comes before the server responds, you're going to have two records in your list because one is the record created by Ember, which will get the ID later. And then pusher will send its own record with the ID already set. So, and Ember data has no way of distinguishing these two because one of the two doesn't have an ID yet. So, the way I solved it is I created a mixing that you can use, actually two mixings, one's for models and one for controllers that you can use to make them immediately live. So, if you include your pushable, your pushable mixing in your controllers and you pass it the name of the method, sorry, of the resource, your model, the array beneath the array controller will be live. So, and you will receive immediately records from your server provided that they, like the server and the client have to obey a certain contract. And so, how does it work internally? So, the client has to generate a unique client ID which will be included in the payload and the client ID will be returned by server both in the pusher and in the HTTP response payload. And this is provided by, this is done automatically by the mixings that I've created. So, you don't have to do anything, you just include the mixings and the client will include the ID. Now, these are the channels that the client expects as a communication way. And if you're, if you're using, so this is an example of a payload, you pass to the client ID inside the task and then the server returns the same client ID. Now, if you're using Rails, you're lucky because I created also a gem which is called pushable Rails. So, you can just include the pushable model in your model and the pushable serializer in your serializer and you will get the same conventions apply. So, basically the client and the server will know how to talk because the server will include now the client ID automatically in the response and it will communicate on the right channels based on class names. So, the code is very simple. This is the code for the client. So, it uses ember pusher which is another library. So, these are the channels that get, like, the model name, create, update and destroy the channels of communication. And then there is, on the top, there is the model mixing that you can use to have this client ID attribute. And then for pusher, it's just a module that you can include and it will, as soon as it commits to the server, it will communicate to the right channels the serialized model. So, yeah, that's it. Thank you. How does it handle errors of, like, data validation errors? Okay, that's a good question. Well, I usually try to, when I'm building this kind of stuff, I usually try to optimize validating stuff on the client and the server usually should communicate just errors that are clear. It was meaning server sites. The server rejects it for some reason. How would this system, or how would you adapt the system to support that? Okay, so, if there isn't any error, it's probably not going to save the resource. So, it won't trigger the pusher update. So, what you're going to get is just the ember data model in your array controller. So, you can treat it, the usual way, which means you're probably going to show the user that some error has happened, but the task will be there immediately because the way ember data works, it will immediately say, okay, everything went okay, and then if something goes bad, you have to think about reverting it and reverting what you've done, basically. As long as pusher doesn't come after, I mean, like, the worst case is probably pusher sends the payload and something bad happens, but I don't think that's going to happen because if you've created it and if they have to commit a callback, it's safe enough, which I think it is. That shouldn't be a problem. Yeah. Yeah. So, push payload is pretty awesome in which it parses any adapter compatible payload. So, if you have, for example, if you have your active model adapter and you obey the rules that the ember data gives you, for example, you side load records and you reference them using, I don't know, link attributes or IDs, whatever you're used to with ember data, basically, it automatically works with push payload. So, you're going to have, it's pretty common that, for example, I push comments inside the task, the task payload. I don't need to push a separate comment payload and it works automatically, the way you're used to. If you're the person who's committing the information out there, do you get a callback sort of, I mean, the information straight back to you? Or is it like one person pushes, you wait a while and then everybody gets out of this? Yeah. Well, sort of, I think, like, you mean the way pusher works? Like, how does it, how does it send payloads to separate, like connected clients or or if the person sending the, like, creating the task is getting also itself back? Then you can call penalty because from that say, you're going to get a response back. Is that still the case? If you push data to the server, do you still get a response straight back to you, as well as the data being pushed down to any other client? Or is it just like, you wait for a while and then you're just one of the people who get the pushes? Yeah. Yeah. So, you still mix the approaches, which means that you still get back a response for the server. And then you also get the, like, data coming from WebSockets. You get both because you don't really have a way. Yeah, exactly. You don't really have a way to distinguish people creating stuff. When you send with pusher, you send to all the clients connected, which means you send also to the creator, which is going to get the normal response from the server. You don't have a way to distinguish. Yeah. Can I ask this different question? So, if I understood the idea here is that when you send a restful post, and at the same time you also push over a WebSocket channel? No, no. The communication happens only from the server to the client. So, you don't actually in WebSockets. So, the creation is done through a normal restful life cycle. And then you only get notified from the server. It's not the other way around. You don't communicate from the client to the server via WebSocket. Okay. So, I'm trying to understand the use cases. Obviously, WebSockets in general are performance optimization and using the network more effectively. So, what is the use case that you're trying to achieve here? So, the use case is you have multiple clients connected, and you want to have a communication channel, basically, between the server and the clients, which allows you to send live notifications to any client connected, which you cannot achieve. I mean, you can use probably server-side events, but WebSockets, if you use stuff like Pusher, Pusher is going to use automatically WebSockets, and there is a lot of ecosystem of staff behind WebSockets. So, I thought that was a good choice to send updates to clients. Do you have any metrics at all that can demonstrate the performance benefits of WebSockets versus just a more traditional one? So, what are the pulling mechanisms and whatever? It's more about sync, isn't it? It's more about sync. Yeah. It's like a Google Dock when you connect it, and everyone can see the changes in the changes. Well, one person sends them up, and then everyone else sees them. Yeah, the other alternate would be a pulling mechanism, I guess. Yeah, right. Yeah, which means, basically, the performance gain you can get is how long you're going to pull. Yeah. Okay. There's a question over here. Yeah, I was just going to say, all the points you said is that when you submit, if you get a Pusher notification back before that solutions, when you connect to Pusher, you get a session ID, and if you post that with your create posts, then when you publish your event to Pusher, you can say, send to everyone except for this session ID. It seems they don't send it back to the region either, basically. Okay, yeah. You can get rid of that problem because you know that everything you've done, you're going to get a notification for that one as well. Cool. Yeah, thank you. Yeah, I think, well, for this case, I used like a generic approach, but this is a good advice for Pusher. Yeah. Thank you. I'm sorry. Can you limit the number of connections to a channel? Like, for example, I want to update tasks for a certain group of users who are, you know, but there are other users that don't have, you know, are not scoped to that task. Yeah, in that case, probably I would create a channel named differently for that subset of users so that those users can connect to that specific task. So, when you create it, you can create a channel for that task with the ID of the task, maybe, and you can send updates on that channel. But yeah, it's just that my gems don't do that, but it's definitely doable. Yeah. This is an ignorant question, but what do you do on the server side of the WebSockets? So, the WebSockets part is handled completely by Pusher. So, Pusher provides a gem, so you can just say pusher.trigger, and then you pass the name, it's just, but it's just pusher.trigger, and then you pass the name of the channel, and then the payload, basically. But surely the HTTP server needs to support like something, or is that just baked in? No, no, because so you communicate with your server through HTTP, normal, you know, RESTful request, and then it's the server that needs to communicate to Pusher, and then, and it's the client directly that connects to Pusher through the JavaScript library, basically. So, the server doesn't need, doesn't need to talk WebSockets this way. This is like the faster, yeah, exactly. Although I think, correct me if I'm wrong, that both, you know, the browser and the WebServer do support, they have to support sockets, but that's well established. It's been around for quite some time. Pusher sits on top of that stack, and it provides a more user-usable interface on the server side to interact with it. But in fact, effectively, sockets and server side events, all those things, those do have to be supported, I think, on the server, I think. Yeah, they are, but if you were going to provide your own Pusher Benz open WebSockets, you'd have to figure out how that would scale to thousands of subscribers at once, where it's Pusher. Oh, so I'm not at all suggesting that someone should use Pusher. In fact, I mean, WebSockets, unlike server side events, strip out a lot of the details. You do need something like Pusher API. Otherwise, you're taking out a lot of work yourself. But server side events, for instance, another example is, you know, it is actually, I think it uses TCP, and it kind of, it's fairly straightforward that you can use it much more in a raw sort of fashion. True, but you still have to, if you were running more than one application, you know, you have to communicate the changes between them so that all the different subscribers could send it down to the clients who are subscribed. I mean, it's definitely, I understand it theoretically, I don't understand the patient details at all. So, this is a little bit, I'm actually quite keen on understanding more about it. I thought that was handled by the low level inside, at the server level. Well, yeah, but if you've got, if you've got several server applications running, changes happen in one of them, the other running applications are going to have to work in order to send it down to the clients connected to them. So, this is an insert route for communication you have to do, which it's kind of, that's the service that we should provide. We're not going to need to worry about that. We have a question. Sorry? No? No, I haven't heard about it. Oh, okay, no, I haven't tested it. Well, if I have any more questions, thank you.