 Hi everyone Hi Wayne Okay my name is Konstantin and I'm gonna talk to you about real-time rec But first I want to thank engineered They're sponsoring my trip here and Yeah, really grateful for that. Otherwise, I couldn't be here and talk to you guys Yeah a bit about me I'm on github and on Twitter and I have a blog like probably most of you have and Back in Germany where I'm originally from I'm a student at the Hasselblattner Institute of IT Systems Engineering Which is in Potsdam close to Berlin in case you ever want to visit I'd be happy to show you around In my free time, I'm also maintaining Sinatra. I know if you've heard of it. It's Yeah, quite popular I'm also maintaining a fork or a clone called almost Sinatra, which is probably going to be more popular than Sinatra really soon because it's only eight lines and I recently also know I'm also working on a book about Sinatra, which is supposed to land next month If I'll continue writing in time So if you want to learn more about Sinatra, please get that book. It's at O'Reilly Sinatra up and running and I'm also a member of the rec core team I'm going to talk a bit more about what REC is in case you're not fully aware of that and I'm currently doing an internship in Portland also sponsored by Engine Yard working full-time on Robinius Alternative Ruby implementation in case you haven't heard of that Okay, this talk is about breaking the laws of REC but Why do we want to break the laws of REC? So back in the day the web work like this you put in an URL You request a page you get a response back from the site and your fancy web browser displays it and But that's pretty boring. So along came Ajax doing all those fancy Requests you don't really notice getting data while you're on the page and so on but Ajax is really the client requesting data from the server but in some cases you want just to have the server push out data to the client and people came up with something something called and Comet which basically is Ajax, but this polling to the server to get Messages from the server, but this isn't what I mean when I talk about it real time real time is Streaming from the server to the client and pushing data at any time you feel like that the basic idea is to decide what to send while streaming not upfront and This is useful for Streaming APIs as Twitter does that. I know if you've written a Twitter client. You probably come across that Or server-send events. I go into detail about that in a bit Or you've probably all heard about web sockets, which is basically this is basically the foundations for Implementing web sockets over rec But I'll start with the demo You've all probably seen this prompt before can calculate stuff or write out code so this is basically a clone of IRB and the sweet thing is It's running in my web browser and It's also non-blocking so Yes, and which is really fancy is it's sending the data to the server The the string to evaluate and then the server just that doesn't eval and returns the results to the client Using server-send events, which is insecure, but well for a demo. It's fine, but the real fun thing is when I fire up a Second browser. This could be another on another machine, right? so Let me just do that and when I run some code here It's actually sent out to both Both clients or all clients a few if you'd connect to that port. I have a firewall on so don't even try and Yeah, this is basically what I'm talking about when I'm talking about real-time web And I'm gonna show you how to do this But first let's make sure you all we're all on the same page You all understand how rack is working internally rack is basically Ruby to HTTP to Ruby bridge. So it's mainly a specification how to translate HTTP requests into Ruby objects and then Translate that back into HTTP responses and it's also a Middleware API and it's the foundation for basically every Ruby web framework a library out there Including rails in our draw and so on And the basic structure is this you have the HTTP client, which is normally your browser could be anything else Which is talking to a thing we call the rack handler, which is basically your web server like Then a mongrel or passenger or whatever and Descender is the one doing the translation from and to HTTP and then using the rack protocol to talk to any middleware and then the so-called endpoint so what you usually do when you're writing your rails application or your Sinatra application is you define the endpoint and then Sinatra and rails set up some middleware in front of that for all the routing and filtering and whatnot and The handlers talking to that so a basic rack application if you're not using any framework looks like this It's it's it can be a proc that takes An ant hash, which is basically a hash of the past HTTP headers and a bit more of environment information And then it has to return an array with three elements The first one is the status code the second one is a hash of the of the headers And the last one is an object that loops through strings that will be sent to the client So but it doesn't have to be a proc it can actually be any object that Response to call and text and and hash or you know just this line I'm going to use a bit of Sinatra during my talk just to cut down the boilerplate But Sinatra really embraces rec and you could just return the rec response in here But so you can see what I'm talking about. I will cut out some of the rec code by that and What the handler is doing now is? Something like this is actually parsing the HTTP response into an ant hash and then it calls call on that and After that it sends out the headers and then calls each on the body object and after that closes the connection this is Basically the code you'll find in about any rec handler out there and Yeah Before I talk about streaming, let's take a look at middleware This is a stupid middleware that will take the body of Your rec endpoint your ads application or whatever and turn everything into uppercase. I mean who doesn't want that, right? So What it does it actually stores the endpoint or the next middleware in the middleware chain because you could use more than one middleware Obviously and then when it gets a call call it will send that call to to the application of course it could Modify the end-fash or keep a list of applications or whatever to do other nice things but that really doesn't matter for streaming and Then it calls each on the body object and Yeah, uppercase is everything and returns that I'm not using map in here because that would violate the rec specification since It's not guaranteed that the body object responds to map Okay, and this is how you would set that up. You would write a config dot are you file Your rec graph you have a rec application. It's usually there already or you could use some rec or some rails interfaces At a middleware. Yeah, and what the server is doing is instead of this line, which we had in the in the Rec handler code. I showed you It's doing this. It's calling new on the middleware passing the end point to it and then calls Call on that one Okay If you have any questions about that, please ask now I want to make sure we're all on the same page. So I didn't I gave this target Scottish RubyConf and people said I lost them like call for in Okay So let's talk about streaming as I said already the body object has to respond to each and Apart from that it can be basically anything so we can use that to implement some streaming This simple application would Send the Send the current time 20 times and always waits one second in between sending that out Which you could see if you would yeah, use the browser or just use curl. That's coming in bit for bit with one second delays and I'm using Sinatra again fancy, right Um, okay, but let's do something more fancy with that Let's do a messaging service where you have a list of clients like in my IRB example and can send data out to them So this is the interface we would like to have would like to keep a list of subscribers and then for everyone opening a connection to The slash there should be connection should be kept open and whenever you post To the application It should send a message to it so yeah adding the subscriber sending the messages down here and How would we implement that with just each? Well, we could do something like this The subscriber Obviously has to wait somehow for new messages to come in we do that with a sleep Which blocks the current threat and then or whenever we send out data We just wake up that threat which we stored when each was called and and send out the data This works fine on Some service, but there are some issues with that mainly it blocks the current threat with the sleep which Is an issue if you don't have a separate threat for every request which you do usually don't if you have a like server using a thread pool It will be able to handle as many requests simultaneously as the size of your thread pool is Which is typical for some service And it does not work well with some middle where imagine we take that application and change the uppercase middle We're in front of it that wouldn't work because the uppercase middle where it's calling each on that and And it waits until each finish until it tends to result on to the handle so we would never see any result and It does not work well or not at all with evented servers like thin or liar up or rainbows So yeah, let's see what we can do about that. My presentation is actually running in thin so it has to work somehow The solution is to do evented streaming where we don't have a threat per request But what is evented evented in this case means we have an event loop which is Usually run by event machine app is the only server not using event machine for this and this is basically a huge wild true loop which on on every loop through it checks for register callbacks or where callback is Triggered whenever whenever data comes in or a new connection comes in and it sends out data that is Registers for sending out and then it yeah You basically do all the stuff in the callbacks and register new callbacks and so on so That's web scale. Yeah And if you take this non evented application You probably every one of you sees that it will wait 10 seconds and only after that it will fire the request to Redis And if you would do that with event machine, it would look something like this It would start the event loop with event machine don't run and You can add a timer to trigger this callback After 10 seconds and you can add another callback to trigger this code whenever Redis responds and then the the event loop will take care of triggering that in the right moment so the Redis request is completely independent from the From the timer and this is what all the evented servers are basically using internally to handle a huge amount of connections and Yeah, so Putting that into our application We can use a nifty trick called the async callback where we basically Send out our rec response which is back here, you know the status code the headers and the body whenever the timer callback is fired and then we have to do some magic down there to tell the Rec handler that we are going to trigger the response later and it it should just go on with the event loop without caring about us for now and There are two ways to do that the first one is to use throw which was discussed shortly in the exception talk yesterday by and and this basically skips all the middle where it goes right through the to the rec handler which does a catch throw somewhere and catch async somewhere and then just Keeps on doing whatever it's doing or you could alternatively return a status code of minus one which is usually nicer because you don't use throw which will unroll the stack and Your middle where will handle that easier, but if you're running in development mode Rec will complain about this being an invalid status code So but what is the handler doing No, I'm sorry And there's also Nice library called async Sinatra Which adds for all the get post methods and so on an async version where you don't have to care about telling the direct handler to do this asynchronously and And yeah, of course instead of a timer. This could also be a request to Redis or Whatever Redis isn't that good an example because Redis is pretty fast But you could like query Google and there will take a couple of time and you want to go on to others stuff why why that's happening and The rec handler is something doing something like this Again, it's parsing the request then it sets up the asynchronous callback Where it basically does all this stuff it would usually be doing just after the request it sends out the the headers and then Uses each again to send out the data are you send data here because that's an event machine method and then it closes the connection and And then it stores the callback in the nFesh so the application can access it and and yeah After that it's just going on to call the the n but the the application and checks the status code if it's Minus one it will skip the callback for now Otherwise, it will just call the callback and send out the data and and the catch async is Here to allow the app leaving it with throw, which is basically behaving like an exception Okay, so far so good But that's postponing that's sending at some later point That's not really streaming. Of course We could do now do our each streaming where we're plugging blocking the threat again But then no other request would be dealt with and during that time since event machine is basically single threaded so There's an ifty trick to use event machine deferrable or Anything that behaves like event machine bit deferrable, which all the evented servers implement a deferrable is basically three states state machine Which has these states of not done yet Succeeded and failed and you can turn anything into a deferrable by just including event machine deferrable and then this adds a callback method that will be triggered whenever the Deferrable succeeds and an airbag method that will be triggered whenever the deferrable fails And then you have a succeed method and similarly you do have a fail method on that object and What it basically does is if it's a deferrable It will not close the connection until the deferrable fails or succeeds So this code you've seen previously setting up the callback It's changed to This code very check if it has a callback method. Actually the handler checks also if it has a airbag method, but I just wanted to save some code here and Then it closes the connection whenever one of those is triggered and if it's not a deferrable it just closes the connection right away and It's still using each up here So what we have to do is to get to send the data whenever we want like we would like to Okay, let's try to Make this example from I showed you previously make that event so it runs with him This is the changed API We are using a get now to have an asynchronous request and the the return value no longer matters Since we're going to send out the response later on Okay, but This is our new subscriber objects less code even so the trick here really is to when each is called Not to yield that block to that block but instead store that block for later on So whenever we call that the rack handler will actually call send data and of course we have to Include the deferrable to set up the callback methods And then all we have to do is whenever we want to send data is trigger that callback And if we want to close the connection later on Okay, yeah, I have to code again. Sorry We close the connection later on we just call succeed on that and Yeah, so my simple API is if you do a delete request close all the connections And That's basically the foundation for Evented streaming now you can use that to implement them service and events Which is a new standard for age from the W3c And It's kind of a one-way web socket So whenever you want to use web sockets, but you use it only to send data from the server to the client Just do yourself a favor and go for service and events instead. It's way easier on all the levels Yeah, super simple it they are the resumable if the connection is lost the web browser will automatically Open the connection again and knows where to continue in the stream and so on. It's no brainer and The client can be implemented just in JS for Browsers that don't support it with the full streaming support. This is possible including for Internet Explorer 7 I think and even if your client is using Internet Explorer 6 or Whatever else It's degrades to polling Which is really nice, which is not that possible if you want to run web sockets you have to include some flesh or something else to get that working and This is the client API you can use in JavaScript. It's available on Firefox Chrome I probably Safari. I don't know but you can use a JavaScript implementation as I said and You basically set up a callback that is triggered Whenever the server feels like sending data to you and The stream from the server looks like this first the HTTP headers So this is the real HTTP response you're getting from the server and then this just stays open and whenever the server feels like sending data, it's Sending the data or prefix with data to show that the Messages over it leaves a new line and you can use that to have multi-line messages Yes, and To ease resumability You can also add an ID for tracking and whenever the browser Opens a request again. It tells you which was the which the last idea was that it saw So you can actually track what happened there Do whatever you want with that and the ID doesn't have to be an integer. It can basically be any strings. It could be check some or anything Tweet ID whatever and This is the complete implementation. This is actually the code. I'm using for the example for the demo. I showed you Where it's basically the same as our subscriber with a more fancy Fancy send since you know, we have to split up the lines And and then send up an ID if we added an ID. I'm using the line number I'm checking line numbers, and I'm using that as an ID if the connection is lost to resume at the right point and Then alas desk web sockets, which is kind of an two-way event source This is the client interface You think probably oh, I've seen that. Yeah, that's correct. It's basically the same interface as the Event source interface with one exception. It also has a send method where you can send back methods messages Now the thing is this is way harder to To implement in rec. So I'm just showing you this little Jam there are a few others out there. This is I think the most popular It's called event machine web sockets where you start a separate server on the port and then you basically have exactly the same interface you have on the client also on the server and There are some issues with with web sockets So this is why I said if if you're just sending to the client go for go for service and events the client needs patching Not every browser supports that and you have to use flesh or something to to add that but also the server needs patching Rec does not support Sending data from the client later on while you're already streaming data back to the client So you basically have to Patrick there are projects out there doing this But it's not possible with vanilla rec and the proxies need patching h a proxy used to have huge issues Due to there being a protocol upgrade because basically it's not part of the HPT to be Specification that you can send data to the server after the service started sending data and as I said rec needs patching And the last thing I want to mention is there's this new speedy protocol Which wraps HTTP? S it's by Google and it also it opens one SSL connection for For a multiple request and that SSI connection can also be used to send back data to the client at any time Yeah, okay, that's it. Thanks My slides are up on guitar