 Okay, thanks for the great introduction Harish Does anybody here not know what scrollbacks about because I have a slide on that which I can skip if you guys don't know Raise your hands if you don't know what scrollback does. Okay. A lot of people don't know what scrollback does So you might have seen like a Screen like this come up in between talks, you know out out here on the On the projector on the screen. So this is a chat room that we build. We are a small startup Based out of Bangalore. I think like 50% of our team is here right now This is This okay, we basically provide chat rooms that serve as a meeting place for communities. All right, so has geek is a community So we provide Chatroom for has geek which they use at all their events All right. So before I talk about you know the so this talk is basically about the architectural choices that we've made at Scrollback We didn't go out and like, you know make a big top-down decision like read all the literature and then decide all right This is what we're gonna do. Okay. So we started something and then we gradually evolved Into a pattern that we are pretty proud of now the scrollback code base has been evolving for more than a year now So it's reasonably mature and one of the cool things I mean and this is in great contrast to all the other big applications. I've worked within my career One of the cool things is that as we've evolved the code base has actually you know gone simpler and shrunk and Definitely lost a lot of concepts. Usually, you know, when your code base gets older you it adds on craft right? It adds concepts. It adds new kind, you know new classes and whatnot But scrollback has gone in the other direction where we've continuously lost concepts until we have like a very very small core API right now So this is this is what scrollback looks like. Okay. Did I did I make that clear? I hope I did So scrollback is a chat room, but it's also a forum and it has like a chat chat archives and whatnot. So In a very, you know, high-level look at what it does, right? It takes it takes messages from all of these places and You know from the web browser or from all of these places and it comes into scrollback, right? Scrollback needs to respond to events from all of these places and what sorts of events happen I mean, yeah, it's a chat room. So people send messages clearly, but they also come online and go offline They log in log out whatever a lot of things so That's a brief overview of what we do and this talk is really about software architecture, right? so I'm gonna take a little bit of time and Just ask you guys like what's the first thing that comes to your head when you hear the word software architecture Anyway, all right Burning subject from college. I heard I heard something over there So I was I was sort of expecting that nobody would give the answer. I was thinking of politics. Yes So I made this slide just in case All right, so it's sort of like the default, you know Approach when you come to you know software architecture is to build MVC or some variant of MVC Basically, I would call it building in layers building your application in layers So just to take a step back. Why why do we do this? I mean why you know your computer definitely does not care if your Application is poorly architected. I mean it will still run unless it has got a you know an actual correctness error It'll just run. So why do you need, you know, good architecture? Good architecture is actually because You know your brain Can't hold your entire program at one shot Right, I mean it's basically you're architecting your application is about splitting it up into small chunks So that you can hold all of the moving parts in one chunk in your brain at one time, you know What variables they have what functions they have and it's external API and stuff like that So building things in layers is a great way to do it. So, you know, it's it's You know, when I looked at MVC, right, it's always been very obvious to me what M is I mean, it's clearly your database layers You make your classes for things and you it's very obvious to me how to scale that also as your application gets larger and more complex You'll build more classes. You might build classes and put them in sort of a hierarchy, you know parent child animal cat whatever You've got views right views are what the user sees and this is also pretty obvious how you scale I mean as your application gets larger it gets more screens if it's Android you get more Activities if it's a web page you get more pages or routes or whatever So it's it's fairly obvious like how you scale that how you keep that organized you might have a navigation tree on your view All right, this controller is sort of you know, it was never very clear to me what the controller does Honestly, I mean except for the fact that the controller is what sort of puts these things together and there is no sort of Well known common pattern for scaling your controller how to organize your controller so, you know when you have an MVC application and it scales or you have any application that's built in layers and it scales it scales by Expanding the layers the layers grow horizontally So your view which was earlier five pages is now five hundred pages and your model which might have had a few classes Is now a whole lot more classes How do you scale the controller? So this is the problem that we fail faced at scroll back, you know, when we started off we started off with some sort of a variant of MVC so I'm gonna show you some code samples right now Which I will tell you if this is how the scroll back code looked a long time ago But this is not really true. I'm I mean this is sort of illustrative of what our code was and The reason I'm not willing to admit that this is what a code was like is because it's very embarrassing So I'm just gonna go on to the code samples, but remember, please don't come come to me afterwards and say hey How are you so stupid? I mean this is no, all right So, you know initially We wrote a controller which was called whenever a message came in, right and You know, we saved the message somewhere and we wanted to send that message out to IRC How many guys here don't know what IRC is? Okay, all right IRC is a chat network Okay, and it's a really ancient sort of old chat network, but it works well with like large communities So the open source communities use it has geek uses it So that's that's sort of what it is But it's a it's a network that is outside of web interfaces and all of it Okay, so you send the message out into IRC you send the message out to people who are using your web interface Okay, so this is this is you know our initial controller, right? But like I said, I mean we just don't deal with messages we deal with a whole bunch more, right? Oh, by the way I mean, I just realized that You know when you get a message from the web you want to send it to IRC, you know It's you want to send it to the IRC channel But when you get a message from the IRC channel, you don't want to send it back there You want to send it to all the other guys on the web, but You don't want to send it back to channel. So the controllers for IRC and for web are kind of slightly different right now But we are not even just dealing with messages. I mean we're dealing with a whole bunch more Right, we're dealing with messages. We have we're dealing with people who are entering and leaving the chat at any point in time. So So you end up with like all of these controller functions, all right in our first You know in our first iteration of the product and we built all of that and we launched it and then this guy we showed show it to a few people and Some guy comes opens the console types a message and our server goes down We forgot to validate inputs We forgot to do any sort of authentication and we didn't we didn't you know There's a whole bunch of other things that you need to do to build a regular web application, right? So you we didn't do logging for instance. So we needed to now add these things on our existing code base, right? We had 10 or 20 controller functions already written and we needed to now add validation All right, so validating a message validating other things are somewhat similar There are a lot of things that are common to validating many things. So clearly you'd write a single validate.js and Write a function inside that that says validate message. Okay, so You know I with me so far. So what you do is like, you know, here's here's your validate message function that does the actual work of validating and you've got you've got the Call to validate message that you need to add to on web message But if you remember there are all of these other Functions and you need to go and insert this, you know, this line that's highlighted in red Validate message. Okay, you need to now go and edit all of these other functions and insert that line right and That's where the you know sort of lack of scalability comes in because you end up having to make a change in many parts of your system Then one thing one new feature needs to be added. All right, so that is that is Kind of goes against the whole idea that you know goes against the goals of Architecting our product well So what we really need is something like that where I don't go and change it up there In the controller, I write my validator and then is that visible is the green line visible at the back folks All right Yeah, all right, so So this is what it does You know, this is not a real JavaScript API But what I really want is to put all of the code related to validation in one place and that includes the instruction to tell You know dear JavaScript Here's my function validate message call this function when you know the other thing the on-web message gets called right now this is This is the solution sort of to our controller scalability problem And so this is you know if you look at the on-web message function, right? It basically has a list of things to do Right, it has a list of things to do and it just needs to do them So let's see if we can structure in a different way. I mean you have the publish publisher subscriber model So let's try and do that. I mean so you've got the on-web message Event and that should trigger a bunch of listeners Okay, so this is this is that's the solution that we came up with so I am sure that many most of you have written event code Right, I mean you've had attached event listeners you've emitted events To sort of structure your code whether it's like UI or whatever so So the API I mean we gave it the name the bus yesterday Okay earlier, we just didn't have a name for this we call it event emitter now the bus has a very simple API I mean just does on which is used to attach an event handler and you do emit which emits an event That's cool And it's very obvious So let's just take a quick look at how you how that solves your problem, right? So earlier You had like save message message message IRC or whatnot You put that all into separate, you know separate modules separate files and your on-web message function just Emits the event and then all of these other things just have to listen for that event and then act on it. All right now the If you have written event code, I mean this this 500 over here would sort of stick out I mean why why do you need that? That's that's not the that's not part of the regular node event emitter or backbone events or whatever So let's go back to the API that you might see the two Highlighted Highlighted words I mean the highlighted arguments over there See we started with an event emitter a regular event emitter like the node event emitter and we saw that it wasn't giving us sufficient control And we needed to make two changes to it to really make our application grow And so it's no longer a proper event driven architecture. It's more a event bus architecture All right, so the two The two additions that we made to the API a priority and payload All right, the priority. I'm sure some of you might have guessed already the priority basically says Here's a here's an event. It has got 10 listeners and in what order should these listeners be called Right. So a priority is just a number so you can imagine an event listeners all of the listeners being placed on a number line from one zero to a thousand and By the while you attach event listener, you can say, all right fine put this listener at number 350 or something of that sort This is not, you know, this is not the most Elegant way to solve this problem. I suppose but it gets the work done, right? And Then you've got payload So every event, you know, if you've written event at code, right? If you've written code on the DOM which responds to a click Right, your event listener gets an object an event object which contains Properties of the click I mean where the user click was the shift button down or whatever so This is similar, but instead of calling it an event object. We're calling it a payload and the Main difference over here is that while listeners Are invoked because of the event the listeners also get the option of actually going back and altering the payload Okay, your click listener. I mean you might have five click listeners on a button All right, all five of them will get exactly the same event object when they're involved right, but You know on The bus architecture that we are building That's not the case. So the the there's very strict control over the order in which listeners get involved and because of that We can actually do this. So here's an example, right? Here's a message that came, right from the from the web So the when the message came it just had like type from to and text, okay, and then like a couple of couple of listeners down the Listener might add a couple of properties. I mean this is how it works, right? I mean the listeners further downstream Need to know the user object need to have a copy of the user object in order to apply some logic onto this Maybe send a notification or whatever. So there's there's a listener There's an upstream listener which loads a user object from the database and attaches it and then so that the downstream listeners can then use it so that's user and room and Then we might have another listener which kind of Uses a bunch of heuristics to figure out whether this message is likely spam or not. I mean we have a spam filter automated one So Does this sound familiar? I mean have Okay, you know, do you know about any very popular common library for which this is true Where you've got a bunch of listeners being involved sequentially and then There's a payload that goes through Express express Express is the right answer, right? I mean express you apply set up your roots or you set up your middleware And then you've got like the body parser which comes and does something and then you've got like No, it it modifies the request object and adds the past data from the body So yeah, I mean express is one of the you know, one of the things we refer to while building this Architecture so there's not much code, you know in this architecture as you can see this it's it's basically two functions These functions are really easy. So I went in like, you know, I was I put it on a GitHub repository yesterday and it was like really I had to make a choice between putting it as a Gist or just start up making a repository because it's just 80 lines of code or something like all right so that's you know, this is the basic framework with which we build out, you know, we have our code organized and so Stepping up a level we basically build, you know, we organize our code and we organize our files as plugins All right, so there's a very simple core of the application It's just an event dispatcher the bus that you saw and then all of the functionality of scroll back is built as plugins All right, and roughly one plug-in corresponds to one feature the way You as a product person or as a as an engineer on the project would understand the word feature So for our, you know, our application sending messages to the web is a feature sending messages to IRC is a different feature Sending, you know, tweets out is the third feature So, you know each plug-in contains some initialization code It contains a bunch of event listeners that listen on the bus. Okay These are basically to handle outgoing events. It's basically for the Core of scroll back to say or I find do this thing in the outside world. Okay, so I'll show you a few examples and then there are You know, there are event listeners that listen to external events So for the, you know, for the web thing, right, you might be listening on you might be waiting for people to connect to you so that's the external event listeners and Sometimes you might need a model and a view and all within your plug-in So what we've done is broken down Scroll back and instead of having like one huge model layer and a huge view layer. We said that you know We've basically broken it vertically into different plugins and each plug-in might have its own model and so on view So this is a few examples of the plugins we have in the application, right? I mean so The word plug-in involves this impression that it's some sort of external little thing that Enhances the product, but it's not core part of product But this is all core parts of the product and they're all built as plugins All right, so the way, you know, this is this is now getting into the style that we use So the way we've done is that the entry point into our application is a simple plug-in loader Okay, it creates a bus. So the library is called ebus. It's on npm. I believe so it creates a bus and it Loads up plugins from a bunch of places and instantiates them. I mean it the plugins are Just functions like that, right the plugins just do modular exports equal function bus It takes a bus and then it attaches So here's this is how this is an example, right? This is how our IRC plug-in works Very roughly so when it's initialized it takes a bus a bus is its sort of communication with the rest of scroll back and It creates, you know, it initializes all its IRC connections to the various IRC networks out there and Then on those client objects, it'll attach an event listener for messages When a message comes in it emits that message into the bus right and And that's that's messages coming inwards and then you've got the messages going outwards Which is like, you know, you've got a bus and on the you know When when a message is going outwards you just send it out on the client I mean, this is really Strip-down version of what we do in practice So this is a list of all the sort of server side events That we handle I mean because we have an event listener and I showed you right in the beginning a slide with all the things that we do I mean all the things that users can do on scroll back. So corresponding to all of them we've got a bunch of events on the server side and All of all of the functionality in scroll back is basically done by listening to these events and This is again like the same list that I showed you a little while ago This is the list of plugins on on scroll back on the server side. Why do I keep saying server side? It's because we actually use browser if I To bring the same API and the same interface onto the client. All right, so I'm gonna Yeah, so I'm gonna quickly go over how this architecture has helped us You know organize our client side code as well I mean we earlier had a sort of client side which was built in angular and We ran into a significant number of issues with this the infinite scroll. It seems you know I mean it looks like a thing that it needs to have right scroll upwards and load more messages It is incredibly painful to do And it wasn't possible in angular Right, so you've got you've got a client side and we've got a sort of React inspired we are building this but again the infinite scroll was not possible to do in react So we just use this use similar ideas All of our client side code is divided into components and each component is really a plug-in I mean it uses exactly the same API as a plug-in and we just use browser if I to get it out there So what do you see over there? I did the name and the picture. That's one component the chat Scrawling area is one component the send box is one component each of the tabs over here on the left side of one component So you've got like basically a whole bunch of components and they do not talk to each other except by emitting and listening to events, right? so Scrollback is completely open source and I mean everything we do is open source All right, all the code we write is open source and it's all on github The scrollback application itself is up there the library that we wrote for doing this event driven architecture is up on github and That's me That's it. Thank you any questions when you are talking about the client side architecture using How to verify and using components so each of these components has a view and control look controller of its own Absolutely, absolutely it Now these are small enough that it's really not necessary for instance the little thing on the right top right, you know This one is just One file or so so it doesn't really need a lot of division, but some of the larger Client side components are divided into a view and a controller of its own. Yes, so the controller part So we just want to separate out the DOM manipulation from the part that communicates through the bus API You write in line HTML with the JavaScript or you do you load them? Okay, so how browser if I works is you write you write it like you write node code Okay, so you've got one entry point for running the node application, right? I mean to run the server you type node server.js Okay, and that runs a server and you've got another file over them Which does client.js and which looks exactly like this. All right. I might have shown you this plug-in loader All right, this is sort of how our server.js looks Okay, it requires one plug-in after another and calls initialize on them Okay, our client side code is written exactly the same way So there are some plugins and if you look at our code base If you look at our code base, we haven't even really divided them up into like all right here are the client side Plug-ins and here are the server side plugins. They're all mixed up together. That's because some plugins Surprisingly have both client side and server side components. So for instance, I can sign into phase I can sign in using Facebook. Okay, so there's a little Facebook sign-in button that comes on the client side There's a lot of clients at code which calls the Facebook API is and whatnot Okay, but then there's also server side code for that which you know communicates with the Facebook servers And we didn't want to put these as two separate things which we had to update separately We made it into a single app. So coming back to your point about browser if I okay, so you've got Hi. All right. So Before this went all blank on me You might have like seen that seen the server side code you offer browser if I you write exactly the same file Miss you call it client or JS and you do browser if I client or JS it goes out and fetches all of them all of its require statements It goes through require statements takes all the required dependencies packs it up into one file called bundle.js And on your client side, right? We've got a client HTML which includes the bundle.js as one shot. So all of our code is kind of minified and Put inside bundle.js Okay, so we do not use inline JavaScript what we do Have right now is sort of in line I wouldn't call it in line. We use partials. Okay, so each of these each piece of this crawlback User interface right So each piece of this crawlback interface You know it has some DOM elements, you know to make it so visible. So those DOM elements are defined in a separate Static HTML file sort of but we've internally maintained this idea that This bunch of DOM elements are all you know owned by a certain component. So you have these DOM elements Which are only touched by one component at a time Does that answer your question? Yeah, I had a question. Okay. It's the same Could you raise your hand? Yeah here here Yeah, okay. You're here here this side. Oh All right. Sorry, man. Okay. Sorry. I'm in the Class so I had two questions. So So as I can see there will be a lot of eventing because you have eventing on messages You have eventing on failover some login and logout. So I just want to know I have two Aspects that I'm looking at the first is How about Performance because there's a lot of eventing happening on the bus and the second is how about failover? So let's say event happened, but it doesn't reach the bus due to some reason So how do you handle these two scenarios? All right. So failover is not handled right now. Okay, so I mean I'm not entirely sure So we are not running each Each plug-in as a different process, right? I mean, they're all running as part of the same process the same node process. So The normal and the event You know calling event listeners for instance is just is basically function calls I mean function calls wrapped in a process dot next stick so that the stack doesn't grow too large But it's basically simple function calls. So all of the stability issues. I mean that you've said are basically general stability issues with Node.js Your question was I could you could repeat the first part of the question So from failover from the perspective that let's say we have a stack and there are a lot of messages which come in So that's going to affect the performance because now there are so many So many listeners to a particular event and then you have to go ahead and iterate over those particular Internal it's going to iterate over those and find the correct listener That is one so performance is going to be affected. The second part of it is the stack was huge Then at some point of time, you know, probably you might have like an explorer crashing or at some point of time An event is missed because Whatever payload you're sending might have some kind of a negative character. So those kind of scenarios So how do you handle events which have been missed? All right Okay, so coming to your first point about performance, right? I mean basically you all of the plugins are asynchronous, okay? So all of the plugins are written asynchronously. So in that you get one plug-in gets invoked and Like just because it's running or it's waiting on the event loop for like, you know, some I would happen doesn't mean that another event is not processed. Okay. They're asynchronous So the order in which event handlers get fired for different events, you know For different when when multiple events are being fired They will all get processed together in parallel sort of so we've I mean, I'll give you a performance Numbers, I guess. I mean, I think I think we have easily seen more than a thousand simultaneous connections in you know, including web sockets and IRC in One instance. All right So I'm not very sure what we haven't done load testing to the to sort of destructive load testing to figure out To what you know at what point it will fail That's because our code is iterating too fast and we're not very sure if we do a test right now and we get some results It's not gonna be valid for much longer The second question about failure. I don't really think that is likely I mean, certainly you slow down when the server's under heavy load. It's gonna slow down. Okay But ultimately these events are being fed from IO either. It's a network connection with the through web sockets or it's, you know So it's basically node streams, right? So when the server's under load will stop stop, you know reading from those streams Okay, so it will stop reading from those streams. Those streams will buffer and maybe it under extremely heavy load those buffers will like You know fill up and the server would crash, but we haven't really seen that yet. All right So I we evaluated the same thing. That's the reason I asked it We have very similar product and then we went with the concept of channels So we have multiple channels which we have used postal by the way And we have multiple channels and then every event is broadcast on the same kind of channel So that makes performance better theoretically, but then I didn't find any data or numbers as you said, okay I would love to talk to you outside. Sure. Thank you Okay, so that's a lot of questions Wow, this is this is a really tough question, okay So the the reason this is tough is not because it's hard to explain but it really it's really painful that you know nobody gets it Because it's it's you know It's one of my favorite parts of the UI, but nobody gets it. So, you know that that tells you that I'm terrible at designing UI So the dots mean that we have Okay, this is called back product feature right we we try to figure out from this flat chat log What topics are being discussed and we try to separate each discussion out into a separate? Into a separate what we call a conversation, right? So you've got you saw here the conversation titles and all of these things are being automatically generated using an LP Okay, so when when every message comes in there's a Classifier which tries to figure out this message belongs to which conversation and whatnot And then we you know, we put we put them into sort of these conversations so that For SEO for instance, it's great. So you guys have been talking about lunch at you know at JS4 so Five days later if somebody wants to Google. Hey, how's the lunch at JS4? Maybe this would come up in the Google search All right, so if it were a simple flat chat log then it's you know, Google doesn't like that So we we does that does that make sense? Did I answer it in a way that was comprehensible? Okay, so the dots basically indicate that these are part of the same conversation so the algorithm thinks that the messages by Rikov and Iliac are in our part of one conversation While as well the others are not so the dots and the lines basically say these are part of the same conversation And then you can maybe click on click on one of these messages and then you can Reply and Rikov you can just hit the at the top right you got your name over there I mean just click on that and sign in using Facebook or Mozilla persona. Sorry about that Yes, right so I'd like to know what issues you faced on a very high level, I mean the The biggest issue was getting the infinite scroll work. The infinite scroll is not possible without very Fine grained control over the over DOM elements. You need to directly manipulate DOM elements Set the scroll top and that sort of thing without which you can do it So we tried to do it by writing a directive And then we saw that like we weren't really following angular patterns at all I mean, we were just directly manipulating the DOM all over the place So there are various things that happen which need us to you know touch the infinite scrolling thing So it's basically problems around infinite scroll Thank you. So you were showing that diagram of Messages and your plug-ins mutating and Different messages, so I there's this framework called Rx. Yes. Have you heard of yes? I I've just heard the name I haven't really had a chance to look at it. So I guess so what you can do with that is Treat your stream itself as a value and then apply transformations on the on the stream So I guess your plug-ins Quite similar to what I think I think we'll definitely you know Okay, so your plug-ins will basically become a function, right? Okay. Okay. Yeah