[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:16.00,0:00:20.40,Default,,0000,0000,0000,,KAREEN KOUDDOUS: All right. Let's get started. Dialogue: 0,0:00:20.47,0:00:24.29,Default,,0000,0000,0000,,Hi, I'm Kareem Kouddous. I'm currently CTO Dialogue: 0,0:00:24.29,0:00:27.83,Default,,0000,0000,0000,,and founder at Crowdtap. I'm also a side project\Naddict. Dialogue: 0,0:00:27.83,0:00:32.02,Default,,0000,0000,0000,,You can find me on GitHub and Twitter at kareemk. Dialogue: 0,0:00:32.02,0:00:34.69,Default,,0000,0000,0000,,So Ruby is cute. And what I mean by Dialogue: 0,0:00:34.69,0:00:38.97,Default,,0000,0000,0000,,that is, you know, it's optimized for developer\Njoy. Dialogue: 0,0:00:38.97,0:00:43.15,Default,,0000,0000,0000,,I mean, anyone who attended Matz's keynote,\Nyou know, Dialogue: 0,0:00:43.15,0:00:46.29,Default,,0000,0000,0000,,can, can feel that. I personally wanted to\Ngo Dialogue: 0,0:00:46.29,0:00:48.68,Default,,0000,0000,0000,,up and hug him after the keynote. It's so Dialogue: 0,0:00:48.68,0:00:51.44,Default,,0000,0000,0000,,clear that, you know, the genesis of Ruby\Ncame Dialogue: 0,0:00:51.44,0:00:55.54,Default,,0000,0000,0000,,from a place of wanting to create joy in Dialogue: 0,0:00:55.54,0:01:00.18,Default,,0000,0000,0000,,what you do every day. Happiness in web development. Dialogue: 0,0:01:00.18,0:01:02.94,Default,,0000,0000,0000,,You know, and Rails, arguably could be cuter.\NYou Dialogue: 0,0:01:02.94,0:01:06.95,Default,,0000,0000,0000,,know, Rails took those same principles of\Nreally loving Dialogue: 0,0:01:06.95,0:01:10.04,Default,,0000,0000,0000,,what you do every day as a web developer Dialogue: 0,0:01:10.04,0:01:14.37,Default,,0000,0000,0000,,or software engineer and taking that to the\Nweb Dialogue: 0,0:01:14.37,0:01:17.33,Default,,0000,0000,0000,,stack. And, I'm sure all of you remember the, Dialogue: 0,0:01:17.33,0:01:19.36,Default,,0000,0000,0000,,you know, blog in fifteen minutes. And that\Nwas Dialogue: 0,0:01:19.36,0:01:22.12,Default,,0000,0000,0000,,magical, because it was so painful before\Nto get Dialogue: 0,0:01:22.12,0:01:24.49,Default,,0000,0000,0000,,a web application up and running. Dialogue: 0,0:01:24.49,0:01:26.64,Default,,0000,0000,0000,,And Rails changed everything. Dialogue: 0,0:01:26.64,0:01:29.24,Default,,0000,0000,0000,,But, I'm sure, as a lot of you also Dialogue: 0,0:01:29.24,0:01:34.67,Default,,0000,0000,0000,,know, over time as your team grows and you Dialogue: 0,0:01:34.67,0:01:41.67,Default,,0000,0000,0000,,start to actually build very interesting features,\Nyou, you Dialogue: 0,0:01:42.39,0:01:46.20,Default,,0000,0000,0000,,tend to, things start to get difficult. You\Nknow, Dialogue: 0,0:01:46.20,0:01:48.83,Default,,0000,0000,0000,,tests start to take a long time. You know, Dialogue: 0,0:01:48.83,0:01:52.61,Default,,0000,0000,0000,,there's great testing ethos in the Ruby community,\Nbut, Dialogue: 0,0:01:52.61,0:01:53.51,Default,,0000,0000,0000,,you know, you have a lot of tests, you Dialogue: 0,0:01:53.51,0:01:55.04,Default,,0000,0000,0000,,build a lot of features and things start to Dialogue: 0,0:01:55.04,0:01:55.70,Default,,0000,0000,0000,,get slow. Dialogue: 0,0:01:55.70,0:01:57.74,Default,,0000,0000,0000,,And what does that do, you know, instead of Dialogue: 0,0:01:57.74,0:01:59.95,Default,,0000,0000,0000,,being able to push out code into your staging Dialogue: 0,0:01:59.95,0:02:02.94,Default,,0000,0000,0000,,or production environment immediately, you\Nhave to wait, you Dialogue: 0,0:02:02.94,0:02:05.81,Default,,0000,0000,0000,,know, minutes, maybe even hours, before that\Ngets in Dialogue: 0,0:02:05.81,0:02:08.54,Default,,0000,0000,0000,,there and you lose flow. You have to context Dialogue: 0,0:02:08.54,0:02:12.61,Default,,0000,0000,0000,,switch. That's horrible. You know. Your fat\Nmodels become Dialogue: 0,0:02:12.61,0:02:14.42,Default,,0000,0000,0000,,obese. Dialogue: 0,0:02:14.42,0:02:16.74,Default,,0000,0000,0000,,You know, suddenly, you know, you have six\Nengineers Dialogue: 0,0:02:16.74,0:02:20.67,Default,,0000,0000,0000,,touching your user model and people are repeating\Nthe Dialogue: 0,0:02:20.67,0:02:22.29,Default,,0000,0000,0000,,code all over the place, because they're trying\Nto Dialogue: 0,0:02:22.29,0:02:25.41,Default,,0000,0000,0000,,do, you know, something that's the same but\Nslightly Dialogue: 0,0:02:25.41,0:02:28.70,Default,,0000,0000,0000,,different. And, you know, instead of trying\Nto refactor Dialogue: 0,0:02:28.70,0:02:30.23,Default,,0000,0000,0000,,the app, you know, you want to push features Dialogue: 0,0:02:30.23,0:02:34.98,Default,,0000,0000,0000,,out. They're duplicating code. And then these\Nthings become Dialogue: 0,0:02:34.98,0:02:40.28,Default,,0000,0000,0000,,really hard to work with and less joyful. Dialogue: 0,0:02:40.28,0:02:42.09,Default,,0000,0000,0000,,You know, you start to use a lot of Dialogue: 0,0:02:42.09,0:02:43.92,Default,,0000,0000,0000,,gems, and that's great. You know, that's one\Nof Dialogue: 0,0:02:43.92,0:02:46.69,Default,,0000,0000,0000,,the wonderful things about the Ruby community\Nis there's Dialogue: 0,0:02:46.69,0:02:48.59,Default,,0000,0000,0000,,a lot of us and we've contributed so much Dialogue: 0,0:02:48.59,0:02:51.18,Default,,0000,0000,0000,,to it. But then you, your app starts to Dialogue: 0,0:02:51.18,0:02:53.27,Default,,0000,0000,0000,,take a long time and, you know, you're building Dialogue: 0,0:02:53.27,0:02:54.91,Default,,0000,0000,0000,,an interesting application so it has a lot\Nof Dialogue: 0,0:02:54.91,0:02:56.75,Default,,0000,0000,0000,,features and you have a lot of gems and Dialogue: 0,0:02:56.75,0:02:59.83,Default,,0000,0000,0000,,that takes a long time. And you stop experimenting. Dialogue: 0,0:02:59.83,0:03:02.90,Default,,0000,0000,0000,,You stop just putting up console and trying\Nstuff. Dialogue: 0,0:03:02.90,0:03:06.24,Default,,0000,0000,0000,,That joy of, that first experience with Rails\Nor Dialogue: 0,0:03:06.24,0:03:10.23,Default,,0000,0000,0000,,Ruby, you know, starts to erode. And then\Nhugs Dialogue: 0,0:03:10.23,0:03:14.84,Default,,0000,0000,0000,,turn into yelling, right. You, you're in the,\Nyou Dialogue: 0,0:03:14.84,0:03:17.41,Default,,0000,0000,0000,,know, you're in your chat room, just trying\Nto Dialogue: 0,0:03:17.41,0:03:19.94,Default,,0000,0000,0000,,figure out what's going on, and yelling at\Neach Dialogue: 0,0:03:19.94,0:03:23.20,Default,,0000,0000,0000,,other. It's, it's, it's no longer joyful. Dialogue: 0,0:03:23.20,0:03:24.92,Default,,0000,0000,0000,,And fundamentally what that means is you've\Nlost your Dialogue: 0,0:03:24.92,0:03:26.91,Default,,0000,0000,0000,,agility. And I think that's what Matz was\Nreally Dialogue: 0,0:03:26.91,0:03:31.26,Default,,0000,0000,0000,,trying to say is, agility is about happiness,\Nright. Dialogue: 0,0:03:31.26,0:03:33.46,Default,,0000,0000,0000,,If you're happy and free to do what you Dialogue: 0,0:03:33.46,0:03:36.47,Default,,0000,0000,0000,,want with your code, you're gonna take, you're\Ngonna Dialogue: 0,0:03:36.47,0:03:38.75,Default,,0000,0000,0000,,innovate. You're gonna do interesting things.\NYou're gonna be Dialogue: 0,0:03:38.75,0:03:39.65,Default,,0000,0000,0000,,creative. Dialogue: 0,0:03:39.65,0:03:43.35,Default,,0000,0000,0000,,And, as your app, though, this, this starts\Nto Dialogue: 0,0:03:43.35,0:03:45.28,Default,,0000,0000,0000,,change, and you lose your agility, and we're\Nback Dialogue: 0,0:03:45.28,0:03:48.59,Default,,0000,0000,0000,,to, you know, waterfall, but, you know, same\Npain Dialogue: 0,0:03:48.59,0:03:51.66,Default,,0000,0000,0000,,points, but just manifested in a different\Nway. So. Dialogue: 0,0:03:51.66,0:03:57.08,Default,,0000,0000,0000,,So, you know, what was really cute, you know, Dialogue: 0,0:03:57.08,0:04:03.93,Default,,0000,0000,0000,,suddenly is this really scary, ugly thing\Nthat has Dialogue: 0,0:04:03.93,0:04:06.30,Default,,0000,0000,0000,,appeared in your life, and you don't know\Nwhat Dialogue: 0,0:04:06.30,0:04:09.52,Default,,0000,0000,0000,,to do with it. You know, you, you want Dialogue: 0,0:04:09.52,0:04:11.79,Default,,0000,0000,0000,,to figure out a way to solve this, and Dialogue: 0,0:04:11.79,0:04:13.62,Default,,0000,0000,0000,,so you need to figure out what the root Dialogue: 0,0:04:13.62,0:04:16.05,Default,,0000,0000,0000,,cause is, right. That's how you solve problems. Dialogue: 0,0:04:16.05,0:04:17.92,Default,,0000,0000,0000,,So you need to figure out the root cause Dialogue: 0,0:04:17.92,0:04:19.61,Default,,0000,0000,0000,,and solve this problem. You want this guy\Nout Dialogue: 0,0:04:19.61,0:04:21.99,Default,,0000,0000,0000,,of your life. Dialogue: 0,0:04:21.99,0:04:24.97,Default,,0000,0000,0000,,So to illustrate that, I'm gonna go through\Nhow Dialogue: 0,0:04:24.97,0:04:29.03,Default,,0000,0000,0000,,this manifested itself, this problem, this\Nbeast in, at Dialogue: 0,0:04:29.03,0:04:32.87,Default,,0000,0000,0000,,Crowdtap, and, and walk through that to show\Nhow Dialogue: 0,0:04:32.87,0:04:36.39,Default,,0000,0000,0000,,we got to where we are now. And, I'm Dialogue: 0,0:04:36.39,0:04:38.63,Default,,0000,0000,0000,,gonna start by just giving you a quick overview Dialogue: 0,0:04:38.63,0:04:41.78,Default,,0000,0000,0000,,of what Crowdtap is. You know, it's, we're\Nthe Dialogue: 0,0:04:41.78,0:04:45.30,Default,,0000,0000,0000,,leading social influence marketing platform.\NYou know we, we Dialogue: 0,0:04:45.30,0:04:48.47,Default,,0000,0000,0000,,ally with big brands, collaborate with their\Ncustomers which Dialogue: 0,0:04:48.47,0:04:52.17,Default,,0000,0000,0000,,inspires advocacy and drives unmatched social\Nactivity. Dialogue: 0,0:04:52.17,0:04:53.97,Default,,0000,0000,0000,,And what all this marketing speak boils down\Nto Dialogue: 0,0:04:53.97,0:04:59.91,Default,,0000,0000,0000,,is we create awesome tasks, engaging fun tasks,\Nfor Dialogue: 0,0:04:59.91,0:05:03.19,Default,,0000,0000,0000,,the brand's launch that users complete to\Nhelp brands Dialogue: 0,0:05:03.19,0:05:05.88,Default,,0000,0000,0000,,market. And those tasks span the full marketing\Nlife Dialogue: 0,0:05:05.88,0:05:09.63,Default,,0000,0000,0000,,cycle. Everything from completing a poll to\Ntaking a Dialogue: 0,0:05:09.63,0:05:11.52,Default,,0000,0000,0000,,photo of doing something fun and sharing that\Non Dialogue: 0,0:05:11.52,0:05:14.79,Default,,0000,0000,0000,,Facebook, to getting free product from the\Nbrand, sharing Dialogue: 0,0:05:14.79,0:05:17.05,Default,,0000,0000,0000,,that with friends, throwing a party around\Nit. And Dialogue: 0,0:05:17.05,0:05:20.34,Default,,0000,0000,0000,,we're constantly adding different tasks, engaging,\Nfun, engaging tasks, Dialogue: 0,0:05:20.34,0:05:23.68,Default,,0000,0000,0000,,so that the brands can collaborate with their\Nconsumers Dialogue: 0,0:05:23.68,0:05:26.63,Default,,0000,0000,0000,,to market, instead of just shouting at them. Dialogue: 0,0:05:26.63,0:05:29.24,Default,,0000,0000,0000,,And that's what our vision is for, for Crowdtap. Dialogue: 0,0:05:29.24,0:05:30.88,Default,,0000,0000,0000,,So let's, let's take a look at this and Dialogue: 0,0:05:30.88,0:05:33.05,Default,,0000,0000,0000,,you know, a screenshot. And this is one of Dialogue: 0,0:05:33.05,0:05:36.42,Default,,0000,0000,0000,,our more popular actions, which is a poll.\NBrands Dialogue: 0,0:05:36.42,0:05:39.51,Default,,0000,0000,0000,,can get real time feedback on whatever they\Nwant. Dialogue: 0,0:05:39.51,0:05:42.70,Default,,0000,0000,0000,,And here they're asking, specifically, you\Nknow, what Cable Dialogue: 0,0:05:42.70,0:05:47.29,Default,,0000,0000,0000,,networks do, does, do the users currently\Nwatch, or Dialogue: 0,0:05:47.29,0:05:48.12,Default,,0000,0000,0000,,receive. Dialogue: 0,0:05:48.12,0:05:51.75,Default,,0000,0000,0000,,And the really powerful thing with Crowdtap\Nis we Dialogue: 0,0:05:51.75,0:05:55.99,Default,,0000,0000,0000,,take all this data that a user, that, that Dialogue: 0,0:05:55.99,0:06:00.02,Default,,0000,0000,0000,,users generate from answering all these questions\Nand participating Dialogue: 0,0:06:00.02,0:06:03.47,Default,,0000,0000,0000,,with the brand, and we give the brands very Dialogue: 0,0:06:03.47,0:06:06.75,Default,,0000,0000,0000,,rich and deep targeting ability, so that not\Nonly Dialogue: 0,0:06:06.75,0:06:08.84,Default,,0000,0000,0000,,can they target based on all the demographic\Ndata Dialogue: 0,0:06:08.84,0:06:11.56,Default,,0000,0000,0000,,on the user: their age, income, et cetera,\Nwhich Dialogue: 0,0:06:11.56,0:06:15.50,Default,,0000,0000,0000,,we collect. We, they can also target based\Non Dialogue: 0,0:06:15.50,0:06:18.42,Default,,0000,0000,0000,,everything that user has done. The entire\Nhistory of Dialogue: 0,0:06:18.42,0:06:22.09,Default,,0000,0000,0000,,what that user has done with, with that brand. Dialogue: 0,0:06:22.09,0:06:23.27,Default,,0000,0000,0000,,And they can also target based on what they Dialogue: 0,0:06:23.27,0:06:26.72,Default,,0000,0000,0000,,haven't done. So, it's a very, very rich targeting Dialogue: 0,0:06:26.72,0:06:29.74,Default,,0000,0000,0000,,engine. But as you can imagine, this becomes\Na Dialogue: 0,0:06:29.74,0:06:34.59,Default,,0000,0000,0000,,performance bottleneck very quickly, because\Non every page load, Dialogue: 0,0:06:34.59,0:06:38.55,Default,,0000,0000,0000,,we need to know which tasks are available\Nfor Dialogue: 0,0:06:38.55,0:06:40.97,Default,,0000,0000,0000,,a user, and, if targeting, we need to - Dialogue: 0,0:06:40.97,0:06:42.49,Default,,0000,0000,0000,,you can target based on anything that user\Nhas Dialogue: 0,0:06:42.49,0:06:44.04,Default,,0000,0000,0000,,done. You have to load up the entire history Dialogue: 0,0:06:44.04,0:06:45.98,Default,,0000,0000,0000,,of that user. Dialogue: 0,0:06:45.98,0:06:48.09,Default,,0000,0000,0000,,And so, to be clear, this is a really Dialogue: 0,0:06:48.09,0:06:51.61,Default,,0000,0000,0000,,big performance bottleneck. And this was the\Nfirst painpoint Dialogue: 0,0:06:51.61,0:06:56.39,Default,,0000,0000,0000,,that we encountered. Or, or, a major painpoint\Nthat Dialogue: 0,0:06:56.39,0:06:59.63,Default,,0000,0000,0000,,we encountered, along with everything I was\Ndiscussing. So Dialogue: 0,0:06:59.63,0:07:03.26,Default,,0000,0000,0000,,we need, you know, we needed to solve this. Dialogue: 0,0:07:03.26,0:07:06.18,Default,,0000,0000,0000,,And the way to solve this is, you know, Dialogue: 0,0:07:06.18,0:07:08.91,Default,,0000,0000,0000,,we need to tailor our data structure for the Dialogue: 0,0:07:08.91,0:07:11.07,Default,,0000,0000,0000,,problem at hand. So, what I mean by that Dialogue: 0,0:07:11.07,0:07:14.26,Default,,0000,0000,0000,,is, we're generating data, everything that\Nthat user is Dialogue: 0,0:07:14.26,0:07:15.86,Default,,0000,0000,0000,,doing, and we're collecting it in a way from Dialogue: 0,0:07:15.86,0:07:19.77,Default,,0000,0000,0000,,our main application that makes sense, you\Nknow, when Dialogue: 0,0:07:19.77,0:07:21.68,Default,,0000,0000,0000,,you're doing just basic CRUD. But then we\Nwant Dialogue: 0,0:07:21.68,0:07:23.73,Default,,0000,0000,0000,,to take that data and we want to have Dialogue: 0,0:07:23.73,0:07:27.22,Default,,0000,0000,0000,,the freedom to denormalize the data. Maybe\Nput in Dialogue: 0,0:07:27.22,0:07:30.21,Default,,0000,0000,0000,,caching. Maybe use a different database technology. Dialogue: 0,0:07:30.21,0:07:34.08,Default,,0000,0000,0000,,We want the freedom to experiment and explore\Nwith Dialogue: 0,0:07:34.08,0:07:37.33,Default,,0000,0000,0000,,this data to be able to solve the problem. Dialogue: 0,0:07:37.33,0:07:39.40,Default,,0000,0000,0000,,And at the same time, we want to do Dialogue: 0,0:07:39.40,0:07:42.23,Default,,0000,0000,0000,,it in a way that takes us back to Dialogue: 0,0:07:42.23,0:07:45.46,Default,,0000,0000,0000,,the joy. Back to the little cute, fuzzy animals Dialogue: 0,0:07:45.46,0:07:47.72,Default,,0000,0000,0000,,we had in our lives and not these beasts, Dialogue: 0,0:07:47.72,0:07:48.66,Default,,0000,0000,0000,,right. Dialogue: 0,0:07:48.66,0:07:51.28,Default,,0000,0000,0000,,So how do you do this? So, you know, Dialogue: 0,0:07:51.28,0:07:53.32,Default,,0000,0000,0000,,the first thing we thought was, OK, we've\Nbeen Dialogue: 0,0:07:53.32,0:07:56.18,Default,,0000,0000,0000,,reading, people have blogged about the services.\NWhat about Dialogue: 0,0:07:56.18,0:07:58.66,Default,,0000,0000,0000,,just extracting and, you know, this functionality\Nin services? Dialogue: 0,0:07:58.66,0:08:01.27,Default,,0000,0000,0000,,But that doesn't work, right. Because even\Nif you Dialogue: 0,0:08:01.27,0:08:03.68,Default,,0000,0000,0000,,extract your functionality into services,\Nwhat you really care Dialogue: 0,0:08:03.68,0:08:06.15,Default,,0000,0000,0000,,about is your models. Right, that's your data. Dialogue: 0,0:08:06.15,0:08:09.29,Default,,0000,0000,0000,,So if you, there, we're not talking about\Nextracting Dialogue: 0,0:08:09.29,0:08:13.13,Default,,0000,0000,0000,,business logic, you know, into, you know,\Nsingle purpose Dialogue: 0,0:08:13.13,0:08:16.63,Default,,0000,0000,0000,,files. We're, we're talking about being able\Nto work Dialogue: 0,0:08:16.63,0:08:18.31,Default,,0000,0000,0000,,with our data in a flexible way. And so Dialogue: 0,0:08:18.31,0:08:22.16,Default,,0000,0000,0000,,extracting it to services doesn't really help. Dialogue: 0,0:08:22.16,0:08:24.78,Default,,0000,0000,0000,,And, you know, Rails, what about a Rails engine Dialogue: 0,0:08:24.78,0:08:27.73,Default,,0000,0000,0000,,or gem extraction. Essentially this is all\Nthe same Dialogue: 0,0:08:27.73,0:08:30.10,Default,,0000,0000,0000,,thing. It's just moving furniture around.\NWhat you really Dialogue: 0,0:08:30.10,0:08:32.63,Default,,0000,0000,0000,,want to do is be able to mutate your Dialogue: 0,0:08:32.63,0:08:34.00,Default,,0000,0000,0000,,data. You want to be able to play with Dialogue: 0,0:08:34.00,0:08:39.80,Default,,0000,0000,0000,,your, your data structure, and have freedom\Nthere. Dialogue: 0,0:08:39.80,0:08:42.56,Default,,0000,0000,0000,,And this brought us to, you know, what about Dialogue: 0,0:08:42.56,0:08:45.33,Default,,0000,0000,0000,,app extraction? Why don't we extract this\Ninto a Dialogue: 0,0:08:45.33,0:08:47.99,Default,,0000,0000,0000,,separate app? You know, we can go back to Dialogue: 0,0:08:47.99,0:08:51.39,Default,,0000,0000,0000,,the, the little cute animal because it's a\Nsmaller Dialogue: 0,0:08:51.39,0:08:53.77,Default,,0000,0000,0000,,app and solve all of those other painpoints.\NBut Dialogue: 0,0:08:53.77,0:08:55.89,Default,,0000,0000,0000,,at the same time, have, you know, some freedom Dialogue: 0,0:08:55.89,0:08:58.44,Default,,0000,0000,0000,,to solve the performance problem which was\Na very Dialogue: 0,0:08:58.44,0:09:00.08,Default,,0000,0000,0000,,big business problem for us. Dialogue: 0,0:09:00.08,0:09:02.56,Default,,0000,0000,0000,,And so the first thing we considered is, how Dialogue: 0,0:09:02.56,0:09:04.92,Default,,0000,0000,0000,,about extracting the app and sharing the database?\NWell, Dialogue: 0,0:09:04.92,0:09:08.38,Default,,0000,0000,0000,,this def, this doesn't work, right. Because\Nall, everything Dialogue: 0,0:09:08.38,0:09:09.90,Default,,0000,0000,0000,,you need to do with your data is in Dialogue: 0,0:09:09.90,0:09:12.06,Default,,0000,0000,0000,,your main app. Your main app holds that model. Dialogue: 0,0:09:12.06,0:09:13.69,Default,,0000,0000,0000,,And so if you're gonna do anything interesting\Nwith Dialogue: 0,0:09:13.69,0:09:14.63,Default,,0000,0000,0000,,your data, you're gonna have to do it in Dialogue: 0,0:09:14.63,0:09:16.46,Default,,0000,0000,0000,,your main app, so what have you done? Dialogue: 0,0:09:16.46,0:09:18.97,Default,,0000,0000,0000,,Your targeting app isn't, the splitting up\Nof the Dialogue: 0,0:09:18.97,0:09:23.89,Default,,0000,0000,0000,,app is not solving anything, right? OK. So\Nlet's Dialogue: 0,0:09:23.89,0:09:26.28,Default,,0000,0000,0000,,do this. Let's to synchronous API. And this\Nis, Dialogue: 0,0:09:26.28,0:09:28.48,Default,,0000,0000,0000,,this is probably what most people think of\Nas Dialogue: 0,0:09:28.48,0:09:32.24,Default,,0000,0000,0000,,SOA, right. SOA is some RPC mechanism between\Napps. Dialogue: 0,0:09:32.24,0:09:35.69,Default,,0000,0000,0000,,But, again, this does not solve this problem,\Nbecause, Dialogue: 0,0:09:35.69,0:09:37.20,Default,,0000,0000,0000,,if you're gonna do anything interesting with\Nyour data Dialogue: 0,0:09:37.20,0:09:38.81,Default,,0000,0000,0000,,and you want to mutate your data, you're gonna Dialogue: 0,0:09:38.81,0:09:40.90,Default,,0000,0000,0000,,have to do that in your main app. Dialogue: 0,0:09:40.90,0:09:43.06,Default,,0000,0000,0000,,And so you're, you're adding complexity to\Nyour main Dialogue: 0,0:09:43.06,0:09:45.11,Default,,0000,0000,0000,,app. We want to remove complexity from the\Nmain Dialogue: 0,0:09:45.11,0:09:47.63,Default,,0000,0000,0000,,app and put it somewhere else, right, and,\Nand Dialogue: 0,0:09:47.63,0:09:50.08,Default,,0000,0000,0000,,deal with it somewhere else. So this doesn't,\Nthis Dialogue: 0,0:09:50.08,0:09:53.87,Default,,0000,0000,0000,,doesn't solve the problem. This just adds\Nmore layers. Dialogue: 0,0:09:53.87,0:09:58.67,Default,,0000,0000,0000,,So I hope, by now, it's clear what the Dialogue: 0,0:09:58.67,0:10:01.22,Default,,0000,0000,0000,,right way to do this is. And for us, Dialogue: 0,0:10:01.22,0:10:02.05,Default,,0000,0000,0000,,it was. Dialogue: 0,0:10:02.05,0:10:05.58,Default,,0000,0000,0000,,You, we need to have a separate database for Dialogue: 0,0:10:05.58,0:10:08.09,Default,,0000,0000,0000,,this, for our targeting application, and we\Nneed to Dialogue: 0,0:10:08.09,0:10:12.90,Default,,0000,0000,0000,,replicate data from our main application into\Nthis separate Dialogue: 0,0:10:12.90,0:10:15.31,Default,,0000,0000,0000,,app, and have the freedom in our main application Dialogue: 0,0:10:15.31,0:10:18.48,Default,,0000,0000,0000,,to mutate the data as we wish, experiment\Nwith Dialogue: 0,0:10:18.48,0:10:23.36,Default,,0000,0000,0000,,different databases, really go back to being\Nagile in Dialogue: 0,0:10:23.36,0:10:25.74,Default,,0000,0000,0000,,solving, in solving the problem. Dialogue: 0,0:10:25.74,0:10:26.94,Default,,0000,0000,0000,,And that's what we did. And it's at that Dialogue: 0,0:10:26.94,0:10:29.10,Default,,0000,0000,0000,,point that the heavens parted and Nico fell\Ninto Dialogue: 0,0:10:29.10,0:10:32.86,Default,,0000,0000,0000,,our laps. And, and helped us take this architecture Dialogue: 0,0:10:32.86,0:10:34.49,Default,,0000,0000,0000,,to the next level. So I'll just, just pass Dialogue: 0,0:10:34.49,0:10:36.35,Default,,0000,0000,0000,,this onto Nico. Dialogue: 0,0:10:36.35,0:10:40.52,Default,,0000,0000,0000,,NICOLAS VIENNOT: Hello. How are you? My name\Nis Dialogue: 0,0:10:40.52,0:10:43.81,Default,,0000,0000,0000,,Nico. I'm a PhD student at Columbia University\Nin Dialogue: 0,0:10:43.81,0:10:46.33,Default,,0000,0000,0000,,the system department. I love, I love opensource,\Nand Dialogue: 0,0:10:46.33,0:10:48.59,Default,,0000,0000,0000,,you can find me on Twitter and GitHub at Dialogue: 0,0:10:48.59,0:10:50.26,Default,,0000,0000,0000,,nviennot. Dialogue: 0,0:10:50.26,0:10:52.33,Default,,0000,0000,0000,,So last year, I came at Crowdtap, and they Dialogue: 0,0:10:52.33,0:10:56.09,Default,,0000,0000,0000,,just extracted that targeting logic to its\Nown separate Dialogue: 0,0:10:56.09,0:10:58.41,Default,,0000,0000,0000,,app that we call Sniper. So that was a Dialogue: 0,0:10:58.41,0:11:01.67,Default,,0000,0000,0000,,great win, because we were able to finally\Nsee Dialogue: 0,0:11:01.67,0:11:04.46,Default,,0000,0000,0000,,the big picture of this application, of that\Nlogic, Dialogue: 0,0:11:04.46,0:11:06.82,Default,,0000,0000,0000,,and that, and so when we extracted that it Dialogue: 0,0:11:06.82,0:11:08.90,Default,,0000,0000,0000,,was like ten, I mean, five thousand, five\Nthousand Dialogue: 0,0:11:08.90,0:11:12.89,Default,,0000,0000,0000,,lines of code. And since we, we were on Dialogue: 0,0:11:12.89,0:11:15.43,Default,,0000,0000,0000,,that app, we could really refactor it quickly\Nbecause Dialogue: 0,0:11:15.43,0:11:18.27,Default,,0000,0000,0000,,the tests were running in, like, you know,\Nthirty Dialogue: 0,0:11:18.27,0:11:18.64,Default,,0000,0000,0000,,seconds. Dialogue: 0,0:11:18.64,0:11:20.74,Default,,0000,0000,0000,,And, and we, we got to a point where Dialogue: 0,0:11:20.74,0:11:22.76,Default,,0000,0000,0000,,the app was just less than a thousand lines Dialogue: 0,0:11:22.76,0:11:25.49,Default,,0000,0000,0000,,of code, because now, because it, it, it got Dialogue: 0,0:11:25.49,0:11:28.22,Default,,0000,0000,0000,,really intuitive - oh, look, we should put\Nour Dialogue: 0,0:11:28.22,0:11:30.56,Default,,0000,0000,0000,,data structure like this. What if, what if\Nwe Dialogue: 0,0:11:30.56,0:11:32.66,Default,,0000,0000,0000,,generalize this way around and all? Which\Nwe couldn't Dialogue: 0,0:11:32.66,0:11:35.35,Default,,0000,0000,0000,,do in the main application because everything\Nwas kind Dialogue: 0,0:11:35.35,0:11:37.27,Default,,0000,0000,0000,,of coupled together and it was really hard\Nto Dialogue: 0,0:11:37.27,0:11:39.30,Default,,0000,0000,0000,,see, you know, the big picture of things. Dialogue: 0,0:11:39.30,0:11:42.62,Default,,0000,0000,0000,,So, performance went really well after that.\NWe went Dialogue: 0,0:11:42.62,0:11:44.67,Default,,0000,0000,0000,,from, you know, a second or two to fifty Dialogue: 0,0:11:44.67,0:11:47.57,Default,,0000,0000,0000,,milliseconds. That was like, yay! Big win! Dialogue: 0,0:11:47.57,0:11:50.32,Default,,0000,0000,0000,,But, we came to another problem, which was\Ndata Dialogue: 0,0:11:50.32,0:11:54.45,Default,,0000,0000,0000,,replication. And it's actually hard. So, so\Nwhat we Dialogue: 0,0:11:54.45,0:11:57.98,Default,,0000,0000,0000,,did first was something pretty naive. So,\Non the Dialogue: 0,0:11:57.98,0:12:00.55,Default,,0000,0000,0000,,main application, the publisher's side, we're\Nlike, well, let's Dialogue: 0,0:12:00.55,0:12:05.33,Default,,0000,0000,0000,,just add some callbacks and post the, the\Ndata Dialogue: 0,0:12:05.33,0:12:08.04,Default,,0000,0000,0000,,to Sniper. And then Sniper, the subscribers\Ncan be Dialogue: 0,0:12:08.04,0:12:10.68,Default,,0000,0000,0000,,like, oh, I can take that data and save Dialogue: 0,0:12:10.68,0:12:13.05,Default,,0000,0000,0000,,it to its database. Dialogue: 0,0:12:13.05,0:12:15.17,Default,,0000,0000,0000,,But things started to break down in production.\NWe're Dialogue: 0,0:12:15.17,0:12:16.92,Default,,0000,0000,0000,,like, it's funny, these two databases don't\Nhave the Dialogue: 0,0:12:16.92,0:12:20.88,Default,,0000,0000,0000,,same user count. It's weird. Because, so,\Nwe realized, Dialogue: 0,0:12:20.88,0:12:22.96,Default,,0000,0000,0000,,wait, it's in a different system. Things fail\Nall Dialogue: 0,0:12:22.96,0:12:23.56,Default,,0000,0000,0000,,the time. Dialogue: 0,0:12:23.56,0:12:27.02,Default,,0000,0000,0000,,So, for example, if your web server, right\Nafter Dialogue: 0,0:12:27.02,0:12:30.62,Default,,0000,0000,0000,,writing its data to the database, dies, and\Nis Dialogue: 0,0:12:30.62,0:12:33.31,Default,,0000,0000,0000,,not able to the callback, then, oops, Sniper\Ndoesn't Dialogue: 0,0:12:33.31,0:12:36.47,Default,,0000,0000,0000,,know about it. What if Sniper is down? Well, Dialogue: 0,0:12:36.47,0:12:38.56,Default,,0000,0000,0000,,it won't receive some updates for five minutes. Dialogue: 0,0:12:38.56,0:12:40.79,Default,,0000,0000,0000,,So that's a problem. Dialogue: 0,0:12:40.79,0:12:42.90,Default,,0000,0000,0000,,So we're like, OK, so this is, this is Dialogue: 0,0:12:42.90,0:12:45.58,Default,,0000,0000,0000,,a problem. And, and at the same time, we're Dialogue: 0,0:12:45.58,0:12:47.80,Default,,0000,0000,0000,,looking at this. We're like, oh, that's funny.\NThat Dialogue: 0,0:12:47.80,0:12:50.41,Default,,0000,0000,0000,,looks really like an observer, like in the\NRails Dialogue: 0,0:12:50.41,0:12:53.65,Default,,0000,0000,0000,,sense, right, like, the Sni- the subscriber\Nis really Dialogue: 0,0:12:53.65,0:12:56.44,Default,,0000,0000,0000,,like observing the data that's changing on\Nthe other Dialogue: 0,0:12:56.44,0:12:59.23,Default,,0000,0000,0000,,app. And we're like, well, that's, that's\Na cool Dialogue: 0,0:12:59.23,0:13:01.47,Default,,0000,0000,0000,,concept. What can it do, then? And what we Dialogue: 0,0:13:01.47,0:13:03.97,Default,,0000,0000,0000,,really want to do with that is to have, Dialogue: 0,0:13:03.97,0:13:06.20,Default,,0000,0000,0000,,to split our app in a lot of different Dialogue: 0,0:13:06.20,0:13:06.73,Default,,0000,0000,0000,,services, right. Dialogue: 0,0:13:06.73,0:13:09.46,Default,,0000,0000,0000,,Like, if we could have this remote observer\Nand, Dialogue: 0,0:13:09.46,0:13:11.90,Default,,0000,0000,0000,,and rip the data around, we're like, well,\Nwhy Dialogue: 0,0:13:11.90,0:13:14.86,Default,,0000,0000,0000,,don't we apply the same thoughts to the email Dialogue: 0,0:13:14.86,0:13:18.14,Default,,0000,0000,0000,,service. But we couldn't just add callbacks\Nand see Dialogue: 0,0:13:18.14,0:13:21.08,Default,,0000,0000,0000,,the production system kind of like blowing\Naway like Dialogue: 0,0:13:21.08,0:13:22.15,Default,,0000,0000,0000,,this. Dialogue: 0,0:13:22.15,0:13:24.95,Default,,0000,0000,0000,,Which is why we introduced Promiscuous. Promiscuous\Nis a Dialogue: 0,0:13:24.95,0:13:28.58,Default,,0000,0000,0000,,transparent application level causally consistent\Ndata replication framework for Dialogue: 0,0:13:28.58,0:13:31.94,Default,,0000,0000,0000,,service-oriented architecture. And, I'm gonna\Nexplain to you what Dialogue: 0,0:13:31.94,0:13:34.30,Default,,0000,0000,0000,,it all means. Dialogue: 0,0:13:34.30,0:13:37.66,Default,,0000,0000,0000,,So Promiscuous is essentially the glue between\Nall of Dialogue: 0,0:13:37.66,0:13:40.46,Default,,0000,0000,0000,,your services. So you can think of it as Dialogue: 0,0:13:40.46,0:13:43.35,Default,,0000,0000,0000,,a message bus, where you're gonna have services\Npublishing Dialogue: 0,0:13:43.35,0:13:46.05,Default,,0000,0000,0000,,their data, and then you're gonna have subscriber\Napps Dialogue: 0,0:13:46.05,0:13:47.89,Default,,0000,0000,0000,,that are like, oh, I'm intruding that model\Nand Dialogue: 0,0:13:47.89,0:13:50.16,Default,,0000,0000,0000,,this one and that, and it's gonna do something Dialogue: 0,0:13:50.16,0:13:51.36,Default,,0000,0000,0000,,interesting. Dialogue: 0,0:13:51.36,0:13:55.15,Default,,0000,0000,0000,,And Promiscuous sits at, on your models, between\Nthe Dialogue: 0,0:13:55.15,0:13:57.80,Default,,0000,0000,0000,,models and the database layer. So everything\Nthat the Dialogue: 0,0:13:57.80,0:14:01.45,Default,,0000,0000,0000,,publisher would do, it's gonna propagate those\Nchanges down Dialogue: 0,0:14:01.45,0:14:04.02,Default,,0000,0000,0000,,to the subscriber models that have a view\Nto Dialogue: 0,0:14:04.02,0:14:05.64,Default,,0000,0000,0000,,anything. Dialogue: 0,0:14:05.64,0:14:07.87,Default,,0000,0000,0000,,So that's Promiscuous in a nutshell. Dialogue: 0,0:14:07.87,0:14:10.85,Default,,0000,0000,0000,,And, and because we are really trying to get Dialogue: 0,0:14:10.85,0:14:14.07,Default,,0000,0000,0000,,back that joy and the simplicity of Rails\Nand Dialogue: 0,0:14:14.07,0:14:17.97,Default,,0000,0000,0000,,Ruby, Promiscuous had to, like, to, to provide\Nthose Dialogue: 0,0:14:17.97,0:14:19.23,Default,,0000,0000,0000,,three key features. Dialogue: 0,0:14:19.23,0:14:22.87,Default,,0000,0000,0000,,So first, it tackles data replication in a\Nnovel Dialogue: 0,0:14:22.87,0:14:27.72,Default,,0000,0000,0000,,way, which scales and is actually consistent.\NIt provides Dialogue: 0,0:14:27.72,0:14:29.84,Default,,0000,0000,0000,,a very simple API, because as a developer,\Nlike, Dialogue: 0,0:14:29.84,0:14:31.22,Default,,0000,0000,0000,,we just want to write one line of code Dialogue: 0,0:14:31.22,0:14:33.04,Default,,0000,0000,0000,,and be done with it. And, of course, since Dialogue: 0,0:14:33.04,0:14:35.87,Default,,0000,0000,0000,,we're Rubyists, we want a good testing framework. Dialogue: 0,0:14:35.87,0:14:38.68,Default,,0000,0000,0000,,So I'm gonna go through all these three points. Dialogue: 0,0:14:38.68,0:14:43.25,Default,,0000,0000,0000,,So data replication. It's pretty hard to,\Nto get Dialogue: 0,0:14:43.25,0:14:45.32,Default,,0000,0000,0000,,your head around this. But let's go through\Nan Dialogue: 0,0:14:45.32,0:14:47.72,Default,,0000,0000,0000,,example. So say you have some sort of Facebook Dialogue: 0,0:14:47.72,0:14:50.48,Default,,0000,0000,0000,,app where you have users and they can send Dialogue: 0,0:14:50.48,0:14:52.12,Default,,0000,0000,0000,,messages to each other. Dialogue: 0,0:14:52.12,0:14:54.49,Default,,0000,0000,0000,,And, and so here, like, say I want to Dialogue: 0,0:14:54.49,0:14:57.27,Default,,0000,0000,0000,,implement an email service that sends an email\Nto Dialogue: 0,0:14:57.27,0:15:01.65,Default,,0000,0000,0000,,whoever receive a message, right. Simple.\NSo here, if, Dialogue: 0,0:15:01.65,0:15:04.13,Default,,0000,0000,0000,,if you would to subscribe to the data that Dialogue: 0,0:15:04.13,0:15:06.35,Default,,0000,0000,0000,,is interesting, you would see, oh, our user\Njust Dialogue: 0,0:15:06.35,0:15:08.16,Default,,0000,0000,0000,,signed up. So create user. Dialogue: 0,0:15:08.16,0:15:09.73,Default,,0000,0000,0000,,And then, that guy just sent a message to Dialogue: 0,0:15:09.73,0:15:12.44,Default,,0000,0000,0000,,another guy. OK. Create message, great. So\Nwhen you Dialogue: 0,0:15:12.44,0:15:14.78,Default,,0000,0000,0000,,create message, you're gonna be like, oh,\Nfetch from Dialogue: 0,0:15:14.78,0:15:17.19,Default,,0000,0000,0000,,my database. Oh, OK, I have that user, I Dialogue: 0,0:15:17.19,0:15:20.92,Default,,0000,0000,0000,,can send random a email. OK, hi, whoever,\Noh Dialogue: 0,0:15:20.92,0:15:22.69,Default,,0000,0000,0000,,hi and all that. Dialogue: 0,0:15:22.69,0:15:25.01,Default,,0000,0000,0000,,But since we need to scale, because, you know, Dialogue: 0,0:15:25.01,0:15:26.89,Default,,0000,0000,0000,,we have a lot of users, we're gonna add Dialogue: 0,0:15:26.89,0:15:29.37,Default,,0000,0000,0000,,some more curves. So that's what's gonna happen.\NOn Dialogue: 0,0:15:29.37,0:15:33.62,Default,,0000,0000,0000,,your email service, we can have, say, two\Nworkers, Dialogue: 0,0:15:33.62,0:15:35.99,Default,,0000,0000,0000,,and now, since we need to process this message Dialogue: 0,0:15:35.99,0:15:39.17,Default,,0000,0000,0000,,in parallel, what's gonna happen? Well, if\Nworker one Dialogue: 0,0:15:39.17,0:15:42.95,Default,,0000,0000,0000,,is a bit slow sometimes, maybe it's not gonna Dialogue: 0,0:15:42.95,0:15:45.64,Default,,0000,0000,0000,,process that create user quick enough to put\Nin Dialogue: 0,0:15:45.64,0:15:47.89,Default,,0000,0000,0000,,database, and so the worker two is gonna be Dialogue: 0,0:15:47.89,0:15:49.94,Default,,0000,0000,0000,,like, oh, who is, who is that user? Oh, Dialogue: 0,0:15:49.94,0:15:51.50,Default,,0000,0000,0000,,well I don't find it in my database. Boom Dialogue: 0,0:15:51.50,0:15:53.09,Default,,0000,0000,0000,,exception. So that's a problem. Dialogue: 0,0:15:53.09,0:15:55.100,Default,,0000,0000,0000,,And that's, that's a consistency problem. Dialogue: 0,0:15:55.100,0:15:59.20,Default,,0000,0000,0000,,But promiscuous, it is going to solve this\Nproblem Dialogue: 0,0:15:59.20,0:16:02.52,Default,,0000,0000,0000,,for you, under, transparently, without you\Nhaving to do Dialogue: 0,0:16:02.52,0:16:05.100,Default,,0000,0000,0000,,anything. And so it's going to try to paralyze Dialogue: 0,0:16:05.100,0:16:09.80,Default,,0000,0000,0000,,as much as, messages that it can, but still Dialogue: 0,0:16:09.80,0:16:11.85,Default,,0000,0000,0000,,serialize the messages that are important. Dialogue: 0,0:16:11.85,0:16:16.24,Default,,0000,0000,0000,,For example, the create user happens before\Nthe create Dialogue: 0,0:16:16.24,0:16:20.30,Default,,0000,0000,0000,,message. And that's what we mean by causal\Nconsistency. Dialogue: 0,0:16:20.30,0:16:22.69,Default,,0000,0000,0000,,So as in cause and effect. Dialogue: 0,0:16:22.69,0:16:25.15,Default,,0000,0000,0000,,So let's see how that kind of works. So Dialogue: 0,0:16:25.15,0:16:29.56,Default,,0000,0000,0000,,why, how is the, is doing this transparently? Dialogue: 0,0:16:29.56,0:16:31.06,Default,,0000,0000,0000,,So when you send, so when you have a Dialogue: 0,0:16:31.06,0:16:32.97,Default,,0000,0000,0000,,user that wants to send a message to another Dialogue: 0,0:16:32.97,0:16:35.31,Default,,0000,0000,0000,,user, it's gonna hit your controller in some\Nways. Dialogue: 0,0:16:35.31,0:16:36.89,Default,,0000,0000,0000,,In your controller, what you're gonna do,\Nyou're gonna Dialogue: 0,0:16:36.89,0:16:39.05,Default,,0000,0000,0000,,interact with your models. So what you gonna\Ndo? Dialogue: 0,0:16:39.05,0:16:41.74,Default,,0000,0000,0000,,You're gonna fetch, first of all the current\Nuser, Dialogue: 0,0:16:41.74,0:16:44.14,Default,,0000,0000,0000,,from his cookie, and then you're gonna do\Nuser Dialogue: 0,0:16:44.14,0:16:46.77,Default,,0000,0000,0000,,find on his friend, and then you're gonna\Nfinally Dialogue: 0,0:16:46.77,0:16:50.38,Default,,0000,0000,0000,,create the message with the frame keys that\Ngo Dialogue: 0,0:16:50.38,0:16:51.02,Default,,0000,0000,0000,,by. Dialogue: 0,0:16:51.02,0:16:53.98,Default,,0000,0000,0000,,And, since Promiscuous sits at your model,\Non your Dialogue: 0,0:16:53.98,0:16:55.76,Default,,0000,0000,0000,,models, it can be like, oh, that's what you Dialogue: 0,0:16:55.76,0:16:58.70,Default,,0000,0000,0000,,did. So he going to infer that the message Dialogue: 0,0:16:58.70,0:17:01.71,Default,,0000,0000,0000,,create depends on those two piece of data.\NAnd Dialogue: 0,0:17:01.71,0:17:04.69,Default,,0000,0000,0000,,that's how it's able to serialize the messages\Nthat Dialogue: 0,0:17:04.69,0:17:08.92,Default,,0000,0000,0000,,are important and paralyze the ones that are\Nnot. Dialogue: 0,0:17:08.92,0:17:10.90,Default,,0000,0000,0000,,So you could say, well, that's a bit overkill. Dialogue: 0,0:17:10.90,0:17:14.37,Default,,0000,0000,0000,,Because why don't I just retry until, you\Nknow, Dialogue: 0,0:17:14.37,0:17:16.63,Default,,0000,0000,0000,,the user is in my database because it would Dialogue: 0,0:17:16.63,0:17:19.70,Default,,0000,0000,0000,,have an exception, right? But it's, it's actually\Nmoreso Dialogue: 0,0:17:19.70,0:17:22.65,Default,,0000,0000,0000,,than that. SO let's take another example to\Nillustrate Dialogue: 0,0:17:22.65,0:17:23.28,Default,,0000,0000,0000,,this. Dialogue: 0,0:17:23.28,0:17:26.44,Default,,0000,0000,0000,,SO say you're on Facebook and you have people Dialogue: 0,0:17:26.44,0:17:28.54,Default,,0000,0000,0000,,posting pictures and you want to provide an\Nemail Dialogue: 0,0:17:28.54,0:17:31.26,Default,,0000,0000,0000,,service that send an email of the picture\Nto Dialogue: 0,0:17:31.26,0:17:34.35,Default,,0000,0000,0000,,your, all of your friends. So say you have Dialogue: 0,0:17:34.35,0:17:36.10,Default,,0000,0000,0000,,a user, consider that scenario where you have\Na Dialogue: 0,0:17:36.10,0:17:38.29,Default,,0000,0000,0000,,user coming back from spring break, and he\Ndeletes Dialogue: 0,0:17:38.29,0:17:40.69,Default,,0000,0000,0000,,his parents from his friends list and then\Nhe Dialogue: 0,0:17:40.69,0:17:43.00,Default,,0000,0000,0000,,posts a compromising picture, K. Dialogue: 0,0:17:43.00,0:17:46.72,Default,,0000,0000,0000,,So what happens if you reverse the processing\Nof Dialogue: 0,0:17:46.72,0:17:49.55,Default,,0000,0000,0000,,the two messages? Well you're gonna send the\Npicture Dialogue: 0,0:17:49.55,0:17:51.97,Default,,0000,0000,0000,,before having to remove the parents. And you're\Nnot Dialogue: 0,0:17:51.97,0:17:53.62,Default,,0000,0000,0000,,gonna have an exception, you're gonna have\Na funk Dialogue: 0,0:17:53.62,0:17:55.56,Default,,0000,0000,0000,,up. Dialogue: 0,0:17:55.56,0:18:00.68,Default,,0000,0000,0000,,So, so this is how, so, Promiscuous has you Dialogue: 0,0:18:00.68,0:18:03.37,Default,,0000,0000,0000,,covered. And you don't want to, when you're\Ndeveloping Dialogue: 0,0:18:03.37,0:18:06.92,Default,,0000,0000,0000,,event-driven services, you, you don't want\Nto, to think Dialogue: 0,0:18:06.92,0:18:08.82,Default,,0000,0000,0000,,about all the races you could have and all Dialogue: 0,0:18:08.82,0:18:12.56,Default,,0000,0000,0000,,that. Like, it's way too complicated. But\Nwe still Dialogue: 0,0:18:12.56,0:18:17.44,Default,,0000,0000,0000,,want a very simple API. So. Dialogue: 0,0:18:17.44,0:18:22.05,Default,,0000,0000,0000,,So essentially, Promiscuous is, is your main\Ndatabus, right. Dialogue: 0,0:18:22.05,0:18:25.97,Default,,0000,0000,0000,,And it does, so, so under the cover you Dialogue: 0,0:18:25.97,0:18:27.78,Default,,0000,0000,0000,,have, you have RabiitMQ which is, which is\Na Dialogue: 0,0:18:27.78,0:18:31.07,Default,,0000,0000,0000,,message broker, so you're gonna have publisher\Napplications that Dialogue: 0,0:18:31.07,0:18:35.71,Default,,0000,0000,0000,,are gonna send their messages on RabbitMQ,\Nand then Dialogue: 0,0:18:35.71,0:18:38.57,Default,,0000,0000,0000,,you're gonna have subscriber applications\Nthat are gonna connect Dialogue: 0,0:18:38.57,0:18:40.88,Default,,0000,0000,0000,,to RabbitMQ and each of the services can have Dialogue: 0,0:18:40.88,0:18:43.45,Default,,0000,0000,0000,,their own queue, I think, going to, to receive Dialogue: 0,0:18:43.45,0:18:45.18,Default,,0000,0000,0000,,those messages through RabbitMQ. Dialogue: 0,0:18:45.18,0:18:47.49,Default,,0000,0000,0000,,So no subscriber actually talk to the publisher\Napp Dialogue: 0,0:18:47.49,0:18:51.57,Default,,0000,0000,0000,,directly. So you're gonna have some good decoupling\Nmechanism. Dialogue: 0,0:18:51.57,0:18:54.92,Default,,0000,0000,0000,,And because we need to synchronize all the\Nworkers Dialogue: 0,0:18:54.92,0:18:58.83,Default,,0000,0000,0000,,together, we use Reddis. So for example, that\Nworker's Dialogue: 0,0:18:58.83,0:19:00.84,Default,,0000,0000,0000,,like, oh wait, so before I can create that Dialogue: 0,0:19:00.84,0:19:02.77,Default,,0000,0000,0000,,message I need for you to wait to create Dialogue: 0,0:19:02.77,0:19:04.34,Default,,0000,0000,0000,,the user, OK. I'm gonna wait for you a Dialogue: 0,0:19:04.34,0:19:06.77,Default,,0000,0000,0000,,little bit. Oh, you died. Well, in that case Dialogue: 0,0:19:06.77,0:19:08.95,Default,,0000,0000,0000,,I'm going to process that message. So all\Nof Dialogue: 0,0:19:08.95,0:19:12.33,Default,,0000,0000,0000,,that is done through Reddis. Dialogue: 0,0:19:12.33,0:19:14.40,Default,,0000,0000,0000,,So let's, let's see a bit of the API Dialogue: 0,0:19:14.40,0:19:16.54,Default,,0000,0000,0000,,of Promiscuous. So on the top, I have a Dialogue: 0,0:19:16.54,0:19:20.70,Default,,0000,0000,0000,,publisher application running with ActiveRecord\Non PosGres, for example, Dialogue: 0,0:19:20.70,0:19:22.70,Default,,0000,0000,0000,,and on the bottom I have a subscriber application Dialogue: 0,0:19:22.70,0:19:24.54,Default,,0000,0000,0000,,running on MongoDB. Dialogue: 0,0:19:24.54,0:19:26.20,Default,,0000,0000,0000,,So all I need to do as a developer Dialogue: 0,0:19:26.20,0:19:29.78,Default,,0000,0000,0000,,is to include the Promiscuous publisher mixin\Nand publish Dialogue: 0,0:19:29.78,0:19:32.62,Default,,0000,0000,0000,,the field that I'm, I'm interested in, for\Nexample, Dialogue: 0,0:19:32.62,0:19:33.51,Default,,0000,0000,0000,,email and name. Dialogue: 0,0:19:33.51,0:19:36.09,Default,,0000,0000,0000,,On the subscriber's side, I'm going to include\Nthe Dialogue: 0,0:19:36.09,0:19:40.13,Default,,0000,0000,0000,,Promiscuous subscriber mixin and, and, in\Nmy subscribe block, Dialogue: 0,0:19:40.13,0:19:41.69,Default,,0000,0000,0000,,I'm going to put the fields I'm interested\Nin, Dialogue: 0,0:19:41.69,0:19:42.75,Default,,0000,0000,0000,,too. And that's it. Dialogue: 0,0:19:42.75,0:19:44.33,Default,,0000,0000,0000,,That's all you need to do. That's the entire Dialogue: 0,0:19:44.33,0:19:45.74,Default,,0000,0000,0000,,API. That's it. Dialogue: 0,0:19:45.74,0:19:50.65,Default,,0000,0000,0000,,So, of course, once you start developing this,\Nyou Dialogue: 0,0:19:50.65,0:19:53.49,Default,,0000,0000,0000,,want to start testing that. And Promiscuous\Nprovides you Dialogue: 0,0:19:53.49,0:19:56.65,Default,,0000,0000,0000,,with a testing framework. So, for us, we leave Dialogue: 0,0:19:56.65,0:19:59.58,Default,,0000,0000,0000,,that interpretation tests are extremely important,\Nand we, we Dialogue: 0,0:19:59.58,0:20:01.94,Default,,0000,0000,0000,,have to, to test our subscribers in a way Dialogue: 0,0:20:01.94,0:20:04.76,Default,,0000,0000,0000,,that is decoupled from the publishers. Dialogue: 0,0:20:04.76,0:20:08.97,Default,,0000,0000,0000,,So the publishers actually, so Promiscuous\Nallows publishers to, Dialogue: 0,0:20:08.97,0:20:11.17,Default,,0000,0000,0000,,to create a gem to publish a gem with Dialogue: 0,0:20:11.17,0:20:15.01,Default,,0000,0000,0000,,factories that represent the kind of data\Nthat, if Dialogue: 0,0:20:15.01,0:20:17.28,Default,,0000,0000,0000,,you were to subscribe to their model, you,\Nthe Dialogue: 0,0:20:17.28,0:20:19.13,Default,,0000,0000,0000,,kind of data that you would get. Dialogue: 0,0:20:19.13,0:20:22.77,Default,,0000,0000,0000,,So to illustrate this, I'm going to show you, Dialogue: 0,0:20:22.77,0:20:25.97,Default,,0000,0000,0000,,an, a real test of Sniper, and you can Dialogue: 0,0:20:25.97,0:20:28.80,Default,,0000,0000,0000,,see, on the top, like, we just do create Dialogue: 0,0:20:28.80,0:20:33.06,Default,,0000,0000,0000,,Crowdtap member instead of the regular Crowdtap\Ncreate member. Dialogue: 0,0:20:33.06,0:20:36.16,Default,,0000,0000,0000,,And so by doing this, Promiscuous is going\Nto Dialogue: 0,0:20:36.16,0:20:39.77,Default,,0000,0000,0000,,take the factory of Crowdtap and, and package\Nthe Dialogue: 0,0:20:39.77,0:20:43.02,Default,,0000,0000,0000,,payload that you have received for real in\Nproduction Dialogue: 0,0:20:43.02,0:20:45.41,Default,,0000,0000,0000,,and send it through your, your cloud client.\NAnd Dialogue: 0,0:20:45.41,0:20:48.90,Default,,0000,0000,0000,,so you're gonna be able to test a really Dialogue: 0,0:20:48.90,0:20:53.50,Default,,0000,0000,0000,,well your application as if it was in production. Dialogue: 0,0:20:53.50,0:20:57.61,Default,,0000,0000,0000,,So to really demonstrate how easy it is to Dialogue: 0,0:20:57.61,0:21:01.49,Default,,0000,0000,0000,,use Promiscuous, Kareem is going to show you\Na Dialogue: 0,0:21:01.49,0:21:04.30,Default,,0000,0000,0000,,live demonstration. Dialogue: 0,0:21:04.30,0:21:11.30,Default,,0000,0000,0000,,K.K.: Hello. Thanks Nico. All right. Let's,\Nlet's show Dialogue: 0,0:21:21.19,0:21:23.21,Default,,0000,0000,0000,,you guys how awesome this is. Dialogue: 0,0:21:23.21,0:21:27.07,Default,,0000,0000,0000,,OK, so what I'm gonna do is I'm gonna Dialogue: 0,0:21:27.07,0:21:31.46,Default,,0000,0000,0000,,show, show you guys adding, taking one of\Nour Dialogue: 0,0:21:31.46,0:21:35.30,Default,,0000,0000,0000,,existing models on our, on, on one of our Dialogue: 0,0:21:35.30,0:21:37.74,Default,,0000,0000,0000,,apps, and subscribing to it in another. So\Non Dialogue: 0,0:21:37.74,0:21:41.27,Default,,0000,0000,0000,,the, on the left side, we've got Crowdtap.\NAnd Dialogue: 0,0:21:41.27,0:21:43.43,Default,,0000,0000,0000,,I've got the, one of our models that we're Dialogue: 0,0:21:43.43,0:21:47.11,Default,,0000,0000,0000,,actually not publishing yet, which is Package,\Nand so Dialogue: 0,0:21:47.11,0:21:49.33,Default,,0000,0000,0000,,we're gonna take this and we're going to publish Dialogue: 0,0:21:49.33,0:21:51.69,Default,,0000,0000,0000,,this model, and then, on the, on the other Dialogue: 0,0:21:51.69,0:21:54.19,Default,,0000,0000,0000,,side, which is Sniper on the right side, which Dialogue: 0,0:21:54.19,0:21:57.22,Default,,0000,0000,0000,,is the targeting app we were discussing, I'm\Ngoing Dialogue: 0,0:21:57.22,0:22:00.73,Default,,0000,0000,0000,,to subscribe to that model so that any changes Dialogue: 0,0:22:00.73,0:22:03.87,Default,,0000,0000,0000,,to the publisher app are reflected to the,\Nto, Dialogue: 0,0:22:03.87,0:22:06.03,Default,,0000,0000,0000,,on the subscriber app. And I'm also gonna\Nput Dialogue: 0,0:22:06.03,0:22:08.61,Default,,0000,0000,0000,,some callbacks in there to bind to any changes Dialogue: 0,0:22:08.61,0:22:10.27,Default,,0000,0000,0000,,that are happening. Dialogue: 0,0:22:10.27,0:22:13.50,Default,,0000,0000,0000,,So let's, let's go ahead and do that. So, Dialogue: 0,0:22:13.50,0:22:15.57,Default,,0000,0000,0000,,all you need to do first is just include, Dialogue: 0,0:22:15.57,0:22:18.91,Default,,0000,0000,0000,,you know, the Promiscuous publisher, which\NNico showed you Dialogue: 0,0:22:18.91,0:22:23.17,Default,,0000,0000,0000,,in that API example. And then just wrap, you Dialogue: 0,0:22:23.17,0:22:26.50,Default,,0000,0000,0000,,know, whatever fields you want to publish\Nin a Dialogue: 0,0:22:26.50,0:22:28.07,Default,,0000,0000,0000,,publish block. And so this case, you don't\Nneed Dialogue: 0,0:22:28.07,0:22:31.27,Default,,0000,0000,0000,,to publish everything. And, and that's important,\Nyou want Dialogue: 0,0:22:31.27,0:22:33.77,Default,,0000,0000,0000,,to figure out what's your public, what's your\NAPI, Dialogue: 0,0:22:33.77,0:22:36.23,Default,,0000,0000,0000,,right, and doesn't need to be the entire model. Dialogue: 0,0:22:36.23,0:22:37.90,Default,,0000,0000,0000,,So you publish what you want, so in this Dialogue: 0,0:22:37.90,0:22:42.55,Default,,0000,0000,0000,,case, let's publish name and features. And\Nthat's it Dialogue: 0,0:22:42.55,0:22:45.24,Default,,0000,0000,0000,,on the publisher's side, and so let's go ahead Dialogue: 0,0:22:45.24,0:22:48.46,Default,,0000,0000,0000,,and do the, or, write the subscriber. So the Dialogue: 0,0:22:48.46,0:22:49.45,Default,,0000,0000,0000,,only thing you need to do is create a Dialogue: 0,0:22:49.45,0:22:52.55,Default,,0000,0000,0000,,model with exactly the same name - so, Package. Dialogue: 0,0:22:52.55,0:22:57.04,Default,,0000,0000,0000,,You know, we're gonna store it in Mongo. Dialogue: 0,0:22:57.04,0:22:59.25,Default,,0000,0000,0000,,Include the Promiscuous subscriber, so we're,\Nyou know, reflection Dialogue: 0,0:22:59.25,0:23:04.47,Default,,0000,0000,0000,,of the Promiscuous publisher. And then mirror,\Nagain, the Dialogue: 0,0:23:04.47,0:23:07.50,Default,,0000,0000,0000,,publish block with the subscribe block. And\Nlet's only Dialogue: 0,0:23:07.50,0:23:12.23,Default,,0000,0000,0000,,subscribe to the, the name. Just for this\Nexample. Dialogue: 0,0:23:12.23,0:23:13.72,Default,,0000,0000,0000,,And then let's print out the name every time Dialogue: 0,0:23:13.72,0:23:18.18,Default,,0000,0000,0000,,the name changes. OK. Dialogue: 0,0:23:18.18,0:23:19.95,Default,,0000,0000,0000,,So that's it. So that's all the code you Dialogue: 0,0:23:19.95,0:23:24.28,Default,,0000,0000,0000,,have to write. So let's start up the Promiscuous Dialogue: 0,0:23:24.28,0:23:31.28,Default,,0000,0000,0000,,subscriber \Nand take a look at RabbitMQ. Dialogue: 0,0:23:31.64,0:23:36.25,Default,,0000,0000,0000,,So RabbitMQ, it's an awesome admin AP- UI,\Nand Dialogue: 0,0:23:36.25,0:23:38.09,Default,,0000,0000,0000,,we just started the subscriber. There are\Nno queues Dialogue: 0,0:23:38.09,0:23:43.22,Default,,0000,0000,0000,,here. We should see a queue any second now. Dialogue: 0,0:23:43.22,0:23:50.22,Default,,0000,0000,0000,,I type bad. Dialogue: 0,0:23:50.49,0:23:57.49,Default,,0000,0000,0000,,There we go. Dialogue: 0,0:23:57.75,0:24:00.95,Default,,0000,0000,0000,,So we have a queue in, in Rabbit. We're Dialogue: 0,0:24:00.95,0:24:04.70,Default,,0000,0000,0000,,gonna kill the worker. Let's go back to Rabbit, Dialogue: 0,0:24:04.70,0:24:07.41,Default,,0000,0000,0000,,and this is a reason that we, we, we Dialogue: 0,0:24:07.41,0:24:09.79,Default,,0000,0000,0000,,chose Rabbit is it supports persistent queues.\NAnd what Dialogue: 0,0:24:09.79,0:24:12.33,Default,,0000,0000,0000,,that means is, even if a worker dies, your Dialogue: 0,0:24:12.33,0:24:16.45,Default,,0000,0000,0000,,queue is still there. It's pers- it's durable.\NAnd Dialogue: 0,0:24:16.45,0:24:19.73,Default,,0000,0000,0000,,any messages that would be consumed or buffered\Nby Dialogue: 0,0:24:19.73,0:24:21.02,Default,,0000,0000,0000,,Rabbit, and when you start the worker up again Dialogue: 0,0:24:21.02,0:24:21.94,Default,,0000,0000,0000,,you get those messages. Dialogue: 0,0:24:21.94,0:24:23.50,Default,,0000,0000,0000,,So you guarantee that those messages are gonna\Nbe Dialogue: 0,0:24:23.50,0:24:23.92,Default,,0000,0000,0000,,delivered. Dialogue: 0,0:24:23.92,0:24:26.88,Default,,0000,0000,0000,,And that's a property that Rabbit gives you.\NIt's Dialogue: 0,0:24:26.88,0:24:31.74,Default,,0000,0000,0000,,awesome. So let's go back and let's, let's\Npublish Dialogue: 0,0:24:31.74,0:24:34.08,Default,,0000,0000,0000,,some of these. So first let's make sure we Dialogue: 0,0:24:34.08,0:24:39.34,Default,,0000,0000,0000,,save this. Let's reload. Just to get those\Nchanges. Dialogue: 0,0:24:39.34,0:24:42.80,Default,,0000,0000,0000,,And then I want to also illustrate how dependencies Dialogue: 0,0:24:42.80,0:24:44.41,Default,,0000,0000,0000,,are tracked, so let's do a read, so I'm Dialogue: 0,0:24:44.41,0:24:46.78,Default,,0000,0000,0000,,just gonna read the last member that we have Dialogue: 0,0:24:46.78,0:24:49.54,Default,,0000,0000,0000,,in our database, and then let's actually create\Na Dialogue: 0,0:24:49.54,0:24:56.54,Default,,0000,0000,0000,,package. Dialogue: 0,0:24:57.55,0:25:04.55,Default,,0000,0000,0000,,Ok. So there we go. We've created that package Dialogue: 0,0:25:08.38,0:25:11.77,Default,,0000,0000,0000,,on Crowdtap. Let's, let's pop over back to\NRabbit Dialogue: 0,0:25:11.77,0:25:15.27,Default,,0000,0000,0000,,and take a look at the payload of that Dialogue: 0,0:25:15.27,0:25:17.70,Default,,0000,0000,0000,,message. Dialogue: 0,0:25:17.70,0:25:20.39,Default,,0000,0000,0000,,And so here it is. So you can see Dialogue: 0,0:25:20.39,0:25:23.19,Default,,0000,0000,0000,,a lot of metadata here. Types is, you know, Dialogue: 0,0:25:23.19,0:25:25.94,Default,,0000,0000,0000,,the class we support inheritance, so you can,\Nyou Dialogue: 0,0:25:25.94,0:25:28.19,Default,,0000,0000,0000,,can publish an entire inheritance tree. You\Ncan publish Dialogue: 0,0:25:28.19,0:25:32.07,Default,,0000,0000,0000,,embedded documents. If you're using Mongoid,\Nthat's all supported. Dialogue: 0,0:25:32.07,0:25:35.18,Default,,0000,0000,0000,,Which, you know, is very powerful. Obviously,\Nthe ID, Dialogue: 0,0:25:35.18,0:25:38.94,Default,,0000,0000,0000,,the attributes that changed, the operation,\Nhere's some more Dialogue: 0,0:25:38.94,0:25:41.24,Default,,0000,0000,0000,,metadata. Importantly in the namespace so\Nit's the name Dialogue: 0,0:25:41.24,0:25:45.53,Default,,0000,0000,0000,,of the app. Crowdtap. Some more information\Nhelps debugging, Dialogue: 0,0:25:45.53,0:25:48.09,Default,,0000,0000,0000,,like the host that was published from. Current\Nuser Dialogue: 0,0:25:48.09,0:25:50.87,Default,,0000,0000,0000,,if you're in a controller and you're, you're\Nlogged Dialogue: 0,0:25:50.87,0:25:54.06,Default,,0000,0000,0000,,in. Publish that. That's really useful for\Ndebugging, and Dialogue: 0,0:25:54.06,0:25:56.57,Default,,0000,0000,0000,,then, the most interesting part is the dependencies. Dialogue: 0,0:25:56.57,0:25:58.77,Default,,0000,0000,0000,,So we did a read in, in console, and Dialogue: 0,0:25:58.77,0:26:01.82,Default,,0000,0000,0000,,here's the associated dependency on that user.\NSo here's Dialogue: 0,0:26:01.82,0:26:04.51,Default,,0000,0000,0000,,the ID and the version. WE use versioning\Nto Dialogue: 0,0:26:04.51,0:26:07.03,Default,,0000,0000,0000,,make sure that when this message is consumed\Non Dialogue: 0,0:26:07.03,0:26:10.68,Default,,0000,0000,0000,,the subscriber's side, that user exists in\Nthat exact Dialogue: 0,0:26:10.68,0:26:10.99,Default,,0000,0000,0000,,state. Dialogue: 0,0:26:10.99,0:26:13.21,Default,,0000,0000,0000,,So that's how we manage all the dependencies\Nand Dialogue: 0,0:26:13.21,0:26:17.02,Default,,0000,0000,0000,,do causal consistencies, and here's the right\Ndependency which Dialogue: 0,0:26:17.02,0:26:19.83,Default,,0000,0000,0000,,is the, the creation, the object that we just Dialogue: 0,0:26:19.83,0:26:20.60,Default,,0000,0000,0000,,created. Dialogue: 0,0:26:20.60,0:26:22.47,Default,,0000,0000,0000,,So that's it. That's the payload. So let's,\Nlet's Dialogue: 0,0:26:22.47,0:26:23.98,Default,,0000,0000,0000,,go ahead and subscribe. And so what we should Dialogue: 0,0:26:23.98,0:26:28.58,Default,,0000,0000,0000,,see here is you know, hello world being printed Dialogue: 0,0:26:28.58,0:26:33.66,Default,,0000,0000,0000,,out. Drum roll. Dialogue: 0,0:26:33.66,0:26:35.35,Default,,0000,0000,0000,,Magic! Dialogue: 0,0:26:35.35,0:26:40.35,Default,,0000,0000,0000,,OK, so let's, you know, let's show that, let's Dialogue: 0,0:26:40.35,0:26:47.35,Default,,0000,0000,0000,,show update. OK. Much easier to type when\Nyou're Dialogue: 0,0:26:50.50,0:26:57.50,Default,,0000,0000,0000,,in your room than in front of people. OK. Dialogue: 0,0:27:01.09,0:27:05.09,Default,,0000,0000,0000,,OK. Dialogue: 0,0:27:05.09,0:27:12.09,Default,,0000,0000,0000,,All right. Sorry guys. Dialogue: 0,0:27:21.08,0:27:28.08,Default,,0000,0000,0000,,OK. Well. For some reason this isn't working.\NBut, Dialogue: 0,0:27:32.58,0:27:39.58,Default,,0000,0000,0000,,we, let me try once more. Dialogue: 0,0:27:40.02,0:27:47.02,Default,,0000,0000,0000,,OK.That's weird. I'm like typing. OK. Let's,\Nif, if, Dialogue: 0,0:27:51.19,0:27:52.98,Default,,0000,0000,0000,,if I had typed any change, it would be Dialogue: 0,0:27:52.98,0:27:56.97,Default,,0000,0000,0000,,immediate propogated over to the publisher's\Nside and trust Dialogue: 0,0:27:56.97,0:28:00.69,Default,,0000,0000,0000,,me, it works. I can show you after. Dialogue: 0,0:28:00.69,0:28:06.52,Default,,0000,0000,0000,,So let's, you know, so, so, let's, you know, Dialogue: 0,0:28:06.52,0:28:08.01,Default,,0000,0000,0000,,what did this to us? So we started, you Dialogue: 0,0:28:08.01,0:28:10.78,Default,,0000,0000,0000,,know, with these two applications. The main\Napp, which Dialogue: 0,0:28:10.78,0:28:14.14,Default,,0000,0000,0000,,is Crowdtap, and the targeting app, which\Nis, you Dialogue: 0,0:28:14.14,0:28:18.31,Default,,0000,0000,0000,,know, Sniper, because it's targeting. And\Nthen we pulled Dialogue: 0,0:28:18.31,0:28:21.10,Default,,0000,0000,0000,,out all of our analytics in fiancé. You now Dialogue: 0,0:28:21.10,0:28:25.29,Default,,0000,0000,0000,,fiancé because it's tracks engagements, obviously. Dialogue: 0,0:28:25.29,0:28:27.24,Default,,0000,0000,0000,,And Bobby, you know, because he's the policeman\Nthat Dialogue: 0,0:28:27.24,0:28:29.63,Default,,0000,0000,0000,,makes sure that, you know, when people are\Nposting Dialogue: 0,0:28:29.63,0:28:32.86,Default,,0000,0000,0000,,stuff, that you know, it's not spam or, and Dialogue: 0,0:28:32.86,0:28:35.36,Default,,0000,0000,0000,,if it's awesome, that it gets starred. So,\Nyou Dialogue: 0,0:28:35.36,0:28:38.22,Default,,0000,0000,0000,,know, we can iterate on using, you know, AEI Dialogue: 0,0:28:38.22,0:28:42.92,Default,,0000,0000,0000,,techniques here to, to moderate our, our,\Nour posts. Dialogue: 0,0:28:42.92,0:28:45.91,Default,,0000,0000,0000,,And then Paparazzi, you know, is out there\Nscraping Dialogue: 0,0:28:45.91,0:28:48.29,Default,,0000,0000,0000,,Facebook and Twitter and gathering, you know,\Ndata, so Dialogue: 0,0:28:48.29,0:28:52.72,Default,,0000,0000,0000,,that we can report on that for our clients. Dialogue: 0,0:28:52.72,0:28:56.01,Default,,0000,0000,0000,,And then Casanova, you know, generates CSVs\Nand it's Dialogue: 0,0:28:56.01,0:29:02.03,Default,,0000,0000,0000,,Casanova because, because it works, because\Nit spreads the Dialogue: 0,0:29:02.03,0:29:04.94,Default,,0000,0000,0000,,love. I still don't, I still don't get that Dialogue: 0,0:29:04.94,0:29:06.34,Default,,0000,0000,0000,,name. Dialogue: 0,0:29:06.34,0:29:11.75,Default,,0000,0000,0000,,But. You know. WE have creative developers.\NAnd then Dialogue: 0,0:29:11.75,0:29:15.52,Default,,0000,0000,0000,,email service, Iris, which is the, the, the\Nnor, Dialogue: 0,0:29:15.52,0:29:22.52,Default,,0000,0000,0000,,the notification God, and then most interestingly\Nis, at Dialogue: 0,0:29:22.57,0:29:24.91,Default,,0000,0000,0000,,least in my perspective is Captain Planet.\NAnd Captain Dialogue: 0,0:29:24.91,0:29:27.28,Default,,0000,0000,0000,,Planet came out of a two day hack-a-thon that Dialogue: 0,0:29:27.28,0:29:32.04,Default,,0000,0000,0000,,we recently had, where a developer was able\Nto, Dialogue: 0,0:29:32.04,0:29:35.34,Default,,0000,0000,0000,,on his, on his laptop, subscribe to the production Dialogue: 0,0:29:35.34,0:29:39.30,Default,,0000,0000,0000,,database, production Rabbit, and generate\Nten reports off of Dialogue: 0,0:29:39.30,0:29:41.46,Default,,0000,0000,0000,,that data to solve a really big pain point Dialogue: 0,0:29:41.46,0:29:43.91,Default,,0000,0000,0000,,that we have that our account team has, and Dialogue: 0,0:29:43.91,0:29:47.27,Default,,0000,0000,0000,,actually do that in a completely isolated\Nway that Dialogue: 0,0:29:47.27,0:29:49.92,Default,,0000,0000,0000,,didn't impact the production system at all. Dialogue: 0,0:29:49.92,0:29:51.89,Default,,0000,0000,0000,,And was actually running that on his laptop,\Njust Dialogue: 0,0:29:51.89,0:29:54.58,Default,,0000,0000,0000,,like the fire hose of production data, on\Nhis Dialogue: 0,0:29:54.58,0:29:56.82,Default,,0000,0000,0000,,laptop, and did that in a couple of days Dialogue: 0,0:29:56.82,0:29:59.83,Default,,0000,0000,0000,,and worked with it. That is, that's joy, right. Dialogue: 0,0:29:59.83,0:30:01.71,Default,,0000,0000,0000,,That's back to the joy of the fifteen minute Dialogue: 0,0:30:01.71,0:30:05.70,Default,,0000,0000,0000,,blog. That's taking a really complex system\Nand making Dialogue: 0,0:30:05.70,0:30:08.15,Default,,0000,0000,0000,,it, you know, easy to use, and it took, Dialogue: 0,0:30:08.15,0:30:11.56,Default,,0000,0000,0000,,you know, this, and went back to something\Nugly Dialogue: 0,0:30:11.56,0:30:15.57,Default,,0000,0000,0000,,to a lot of little cute fun cuddly apps Dialogue: 0,0:30:15.57,0:30:18.23,Default,,0000,0000,0000,,that we, that we now have. Dialogue: 0,0:30:18.23,0:30:19.65,Default,,0000,0000,0000,,And with that, I'm gonna pass it back to Dialogue: 0,0:30:19.65,0:30:22.74,Default,,0000,0000,0000,,Nico to wrap things up. Dialogue: 0,0:30:22.74,0:30:26.73,Default,,0000,0000,0000,,N.V.: So to wrap things up, we've seen that Dialogue: 0,0:30:26.73,0:30:31.25,Default,,0000,0000,0000,,Promiscuous is very useful to do event-driven\Nservices. So Dialogue: 0,0:30:31.25,0:30:33.28,Default,,0000,0000,0000,,you can trigger callbacks realtime. For example,\Nyou want Dialogue: 0,0:30:33.28,0:30:35.64,Default,,0000,0000,0000,,to send emails when some piece of data is Dialogue: 0,0:30:35.64,0:30:39.21,Default,,0000,0000,0000,,changing. You want to keep your caches warm.\NWhenever, Dialogue: 0,0:30:39.21,0:30:42.03,Default,,0000,0000,0000,,or, say, you know, whenever some piece of\Ndata Dialogue: 0,0:30:42.03,0:30:44.59,Default,,0000,0000,0000,,changes, you wanna is, instead of invalidating\Nyour caches, Dialogue: 0,0:30:44.59,0:30:46.96,Default,,0000,0000,0000,,you can actually reconfig the, the right thing. Dialogue: 0,0:30:46.96,0:30:50.13,Default,,0000,0000,0000,,You could push data asynchronously to your\Nbrowsers to Dialogue: 0,0:30:50.13,0:30:52.78,Default,,0000,0000,0000,,improve the user experience. And we want to\Ndo Dialogue: 0,0:30:52.78,0:30:57.99,Default,,0000,0000,0000,,all that also by, and also doing database\Nreplication, Dialogue: 0,0:30:57.99,0:31:00.03,Default,,0000,0000,0000,,but different kind of databases, right. So\NI want Dialogue: 0,0:31:00.03,0:31:02.39,Default,,0000,0000,0000,,to be able to replicate my PosGres database\Nto Dialogue: 0,0:31:02.39,0:31:06.64,Default,,0000,0000,0000,,ElasticSearch and maybe MongoDB and maybe\NRiot - whatever Dialogue: 0,0:31:06.64,0:31:09.40,Default,,0000,0000,0000,,it is. And I want this to be decoupled, Dialogue: 0,0:31:09.40,0:31:11.11,Default,,0000,0000,0000,,and I want this to be, do this at Dialogue: 0,0:31:11.11,0:31:13.87,Default,,0000,0000,0000,,scale and with good consistency. Dialogue: 0,0:31:13.87,0:31:16.47,Default,,0000,0000,0000,,So that was gonna allow you to, to really Dialogue: 0,0:31:16.47,0:31:19.43,Default,,0000,0000,0000,,see the data that you want for the feature Dialogue: 0,0:31:19.43,0:31:22.03,Default,,0000,0000,0000,,that you need to implement. And so real time Dialogue: 0,0:31:22.03,0:31:25.19,Default,,0000,0000,0000,,is really, really important these days. And,\Nand if Dialogue: 0,0:31:25.19,0:31:29.53,Default,,0000,0000,0000,,you can embrace the arch, the, the asynchronous\Nlayer Dialogue: 0,0:31:29.53,0:31:32.93,Default,,0000,0000,0000,,of your application and to really, to really\Nunleash Dialogue: 0,0:31:32.93,0:31:36.77,Default,,0000,0000,0000,,the power of your data, right. So you can Dialogue: 0,0:31:36.77,0:31:40.31,Default,,0000,0000,0000,,really innovate now. You can hire some interns\Nfor Dialogue: 0,0:31:40.31,0:31:43.13,Default,,0000,0000,0000,,a summer and get them to do some matching Dialogue: 0,0:31:43.13,0:31:46.96,Default,,0000,0000,0000,,learning project directly in production without\Nhaving you to Dialogue: 0,0:31:46.96,0:31:49.44,Default,,0000,0000,0000,,be worrying about, oh my god, they're gonna\Ndrop Dialogue: 0,0:31:49.44,0:31:52.10,Default,,0000,0000,0000,,my system and they're gonna pollute the code\Nand Dialogue: 0,0:31:52.10,0:31:52.68,Default,,0000,0000,0000,,all that. Dialogue: 0,0:31:52.68,0:31:54.98,Default,,0000,0000,0000,,Like, if you don't like their stuff, eventually\Nyou Dialogue: 0,0:31:54.98,0:31:57.93,Default,,0000,0000,0000,,just delete their app and you're done, right.\NSo, Dialogue: 0,0:31:57.93,0:31:59.72,Default,,0000,0000,0000,,so you can really go back to being agile Dialogue: 0,0:31:59.72,0:32:02.22,Default,,0000,0000,0000,,and try things really with, without having,\Noh my Dialogue: 0,0:32:02.22,0:32:04.28,Default,,0000,0000,0000,,god it's, I need to change so much things. Dialogue: 0,0:32:04.28,0:32:07.74,Default,,0000,0000,0000,,Like, you, you get back to, to really the, Dialogue: 0,0:32:07.74,0:32:11.18,Default,,0000,0000,0000,,to the agility of, of, of your team. Dialogue: 0,0:32:11.18,0:32:13.46,Default,,0000,0000,0000,,So that's, that's about it. So we invite you Dialogue: 0,0:32:13.46,0:32:17.30,Default,,0000,0000,0000,,to try it out. It's on GitHub, on Promiscuous Dialogue: 0,0:32:17.30,0:32:19.89,Default,,0000,0000,0000,,dash io slash Promiscuous. So we've been using\Nit Dialogue: 0,0:32:19.89,0:32:22.02,Default,,0000,0000,0000,,in production for a year now and we're very Dialogue: 0,0:32:22.02,0:32:23.79,Default,,0000,0000,0000,,happy with it. But it requires a bit of Dialogue: 0,0:32:23.79,0:32:25.64,Default,,0000,0000,0000,,babysitting for now. Dialogue: 0,0:32:25.64,0:32:28.44,Default,,0000,0000,0000,,So we're still working on it, and we're trying Dialogue: 0,0:32:28.44,0:32:30.95,Default,,0000,0000,0000,,to make it really a hands-free experience.\NSo that Dialogue: 0,0:32:30.95,0:32:32.76,Default,,0000,0000,0000,,you can just plug it in and you have Dialogue: 0,0:32:32.76,0:32:34.67,Default,,0000,0000,0000,,nothing to worry about and you have all the Dialogue: 0,0:32:34.67,0:32:38.04,Default,,0000,0000,0000,,different recovery mechanism that kicks in\Nat the right Dialogue: 0,0:32:38.04,0:32:40.29,Default,,0000,0000,0000,,time and everything. Dialogue: 0,0:32:40.29,0:32:42.36,Default,,0000,0000,0000,,So if you feel adventurous, you can try to Dialogue: 0,0:32:42.36,0:32:45.23,Default,,0000,0000,0000,,extract your email logic out of your main\Napplication Dialogue: 0,0:32:45.23,0:32:47.98,Default,,0000,0000,0000,,because that's, like, the obvious, like, you\Nhave no, Dialogue: 0,0:32:47.98,0:32:49.62,Default,,0000,0000,0000,,it's an observer, really. Dialogue: 0,0:32:49.62,0:32:52.77,Default,,0000,0000,0000,,And, and perhaps build some reporting service,\Nalso, for Dialogue: 0,0:32:52.77,0:32:56.69,Default,,0000,0000,0000,,some, some of your fancy clients. So, if you Dialogue: 0,0:32:56.69,0:32:58.96,Default,,0000,0000,0000,,try it out, we'll be super happy to help Dialogue: 0,0:32:58.96,0:33:03.32,Default,,0000,0000,0000,,you with the, to go, with Promiscuous. And\Nwe, Dialogue: 0,0:33:03.32,0:33:06.32,Default,,0000,0000,0000,,you can find us on Twitter and GitHub, kareemk Dialogue: 0,0:33:06.32,0:33:06.78,Default,,0000,0000,0000,,and nviennot. Dialogue: 0,0:33:06.78,0:33:10.16,Default,,0000,0000,0000,,Thank you. And now we'll take questions.