0:00:18.160,0:00:22.539 JASON CLARK: All righty. I think, by my clock, 0:00:22.539,0:00:25.239 it's about 1:40. A couple more people 0:00:25.239,0:00:29.250 are coming on in, but we'll get things started. 0:00:29.250,0:00:32.860 My name's Jason Clark. I'm an engineer at[br]New 0:00:32.860,0:00:35.890 Relic. I work specifically on the New Relic[br]RPM 0:00:35.890,0:00:38.090 gem, which some of you may have installed[br]in 0:00:38.090,0:00:41.640 your applications. So that's actually gonna[br]play in a 0:00:41.640,0:00:43.109 little bit in some of the examples that I'm 0:00:43.109,0:00:45.510 gonna use later on. But you don't need to 0:00:45.510,0:00:47.250 know too much about how that works. 0:00:47.250,0:00:50.210 The first, so, I, I've got to start off 0:00:50.210,0:00:53.510 with a, an admission to something that I've[br]always 0:00:53.510,0:00:56.149 wanted to do when presenting in front of a 0:00:56.149,0:00:58.559 group of people, and I figured that RailsConf[br]is 0:00:58.559,0:01:02.260 probably just about the best opportunity.[br]So, if you'll 0:01:02.260,0:01:09.159 just bear with me for a second. Just hang[br]on. 0:01:09.159,0:01:14.610 So at New Relic, we have a support hero 0:01:14.610,0:01:18.590 who is responsible for handling the escalations.[br]So any 0:01:18.590,0:01:22.429 time that something gets too complicated for[br]support, they 0:01:22.429,0:01:24.450 send it to the support hero. And my wife 0:01:24.450,0:01:27.880 heard that, and she went, if you're a hero, 0:01:27.880,0:01:31.270 you need a cape. And so she made me 0:01:31.270,0:01:36.349 this lovely hand-embroidered Ruby emblem cape.[br]And I've always 0:01:36.349,0:01:40.340 wanted to give a presentation wearing this.[br]So, if 0:01:40.340,0:01:45.289 that's OK. Little unprofessional, maybe, but,[br]you know. I'm 0:01:45.289,0:01:47.679 just gonna go for it, so. 0:01:47.679,0:01:51.799 AUDIENCE: Look in the sky! It's a bird! 0:01:51.799,0:01:55.060 J.C.: All right. That feels good. Thank you.[br]Thank 0:01:55.060,0:01:56.869 you for humoring me. All right. 0:01:56.869,0:01:58.429 So what we're here for, here to talk about 0:01:58.429,0:02:01.209 today is about something that I call evented[br]patterns 0:02:01.209,0:02:04.079 in Ruby. So let's start off with a little 0:02:04.079,0:02:05.819 bit of a story. This is a little bit 0:02:05.819,0:02:08.508 of a fabrication, but it might be something[br]that 0:02:08.508,0:02:10.750 some of you have experienced before. 0:02:10.750,0:02:14.069 So, imagine that you have created an application.[br]Maybe 0:02:14.069,0:02:17.310 it's something like, something basic, for[br]doing tracking of 0:02:17.310,0:02:22.099 your cycling statistics. And all of a sudden,[br]your 0:02:22.099,0:02:24.969 application really takes off. It gets on the[br]social 0:02:24.969,0:02:27.760 media. People find out about it and, you know, 0:02:27.760,0:02:30.290 you, you start getting this influx of users[br]that 0:02:30.290,0:02:33.110 you've got to deal with. As your traffic scales, 0:02:33.110,0:02:35.000 you've got to do things like tuning your web 0:02:35.000,0:02:38.599 server, right. You, you pick your, your Unicorn[br]or 0:02:38.599,0:02:40.180 your Puma and you get that set up. You 0:02:40.180,0:02:44.849 tune your system. And while your traffic is[br]growing, 0:02:44.849,0:02:47.280 there's a similar sort of growth that goes[br]on 0:02:47.280,0:02:49.560 in your code. 0:02:49.560,0:02:53.340 Your controllers start out life kind of like[br]this. 0:02:53.340,0:02:55.680 They start out pretty simple, you know. We[br]just 0:02:55.680,0:02:59.450 create our user when somebody signs up. But[br]then, 0:02:59.450,0:03:01.280 as your application grows and you get more[br]stake 0:03:01.280,0:03:04.019 holders and your company's, you know, doubling[br]every two 0:03:04.019,0:03:05.989 months, all of a sudden, you've got other[br]things 0:03:05.989,0:03:08.439 that you need to add in there, right. You, 0:03:08.439,0:03:10.489 maybe you want to send welcome emails, so[br]you, 0:03:10.489,0:03:12.930 you end up, you know, getting your action[br]mailer 0:03:12.930,0:03:15.530 going there, and cram that into, into your[br]action 0:03:15.530,0:03:17.090 when someone signs up. 0:03:17.090,0:03:19.469 Oh, and then maybe it's really important that[br]our 0:03:19.469,0:03:21.599 business people be able to do analytics. They[br]want 0:03:21.599,0:03:23.739 to know about who's signing up and track data, 0:03:23.739,0:03:25.319 and there's some other place that we want[br]to 0:03:25.319,0:03:29.170 push that data. Oh, and then the sales people, 0:03:29.170,0:03:30.749 they really want this to be integrated to[br]their 0:03:30.749,0:03:32.810 sales system, and so they want stuff to get 0:03:32.810,0:03:36.870 pushed over to their CRM. And maybe, oh, we 0:03:36.870,0:03:38.379 want to do some sort of posting out to 0:03:38.379,0:03:40.689 the social networks. So we have a background[br]job 0:03:40.689,0:03:43.480 that takes care of that. You know, this sort 0:03:43.480,0:03:46.340 of growth happens in some of those critical[br]points 0:03:46.340,0:03:50.510 in your infrastructure. The spots where interesting[br]things happen 0:03:50.510,0:03:52.840 in the domain of your application. 0:03:52.840,0:03:56.980 Now, that's kind of, can get to be a 0:03:56.980,0:03:59.510 mess, you know. This, over time, I mean this 0:03:59.510,0:04:02.230 is a short example and slightly fabricated,[br]but I'm 0:04:02.230,0:04:04.060 sure you all have, you know, I'm sure all 0:04:04.060,0:04:06.260 of your controllers are, like, twelve lines[br]or less 0:04:06.260,0:04:09.939 for an action, right? Nobody has these long[br]methods 0:04:09.939,0:04:11.659 that go on and do tons and tons of 0:04:11.659,0:04:13.069 things. 0:04:13.069,0:04:15.810 You can end up with a massive snarl. You 0:04:15.810,0:04:17.660 can end up with controllers that are very[br]difficult 0:04:17.660,0:04:20.470 to test, difficult to reason about, and they[br]go 0:04:20.470,0:04:23.930 on and on handling all of these different[br]things. 0:04:23.930,0:04:26.060 So what we're gonna talk about is a pattern 0:04:26.060,0:04:29.330 of using events to handle that and to take 0:04:29.330,0:04:33.430 those key parts of your infrastructure and[br]break them 0:04:33.430,0:04:35.160 apart into smaller bits. 0:04:35.160,0:04:37.830 So, first off, we're gonna talk about what[br]I 0:04:37.830,0:04:40.180 actually mean when I say events, the pattern[br]that 0:04:40.180,0:04:43.130 we're talking about. We'll talk about how[br]that can 0:04:43.130,0:04:46.340 be used in the coupling of your application,[br]both 0:04:46.340,0:04:48.690 internally within your app and as it relates[br]to 0:04:48.690,0:04:51.160 other libraries that you might be using. 0:04:51.160,0:04:53.479 We'll take a look at a couple of mechanisms 0:04:53.479,0:04:55.430 that you can use to institute this sort of 0:04:55.430,0:04:58.539 system. And then we'll talk about some of[br]the 0:04:58.539,0:05:00.740 responsibilities and sort of how you should[br]think about 0:05:00.740,0:05:04.620 this type of evented system within your app.[br]And 0:05:04.620,0:05:07.440 keep things flexible and performant. 0:05:07.440,0:05:12.440 So, first up, the pattern. So, when I say 0:05:12.440,0:05:14.190 events, you know, there's lots of different[br]people that 0:05:14.190,0:05:17.020 think lots of different things when I say[br]that. 0:05:17.020,0:05:19.060 Like, some folks that this was gonna be about 0:05:19.060,0:05:22.720 event machine. It's not about event machine.[br]So what, 0:05:22.720,0:05:24.229 what sort of things pop to mind when I 0:05:24.229,0:05:25.900 say evented programming? 0:05:25.900,0:05:27.169 AUDIENCE: Asynchronous. 0:05:27.169,0:05:28.440 J.C.: K. 0:05:28.440,0:05:30.340 AUDIENCE: ActiveSupport notifications. 0:05:30.340,0:05:33.340 J.C.: Visual Basic event handlers? Anybody? 0:05:33.340,0:05:34.560 AUDIENCE: Nice! 0:05:34.560,0:05:37.090 J.C.: I'm sorry to, no. I shouldn't do that. 0:05:37.090,0:05:37.259 No. 0:05:37.259,0:05:40.819 A lot of people probably think node. Think[br]asynchronous 0:05:40.819,0:05:44.389 sorts of callbacks. But that's not necessarily[br]the core 0:05:44.389,0:05:46.180 of the type of event that I'm gonna describe 0:05:46.180,0:05:49.919 here today. This, these events are not necessarily[br]asynchronous. 0:05:49.919,0:05:53.530 They're not necessarily about IO or about[br]distributing things. 0:05:53.530,0:05:56.370 They're just a basic pattern to decoupled[br]pieces of 0:05:56.370,0:05:58.240 your application. 0:05:58.240,0:05:59.740 So it starts off, the main term that I'll 0:05:59.740,0:06:02.699 use. Somebody knows that something interesting[br]happens in your 0:06:02.699,0:06:05.599 system, I'm going to refer to it as a 0:06:05.599,0:06:08.259 notifier. There's a set of subscribers that[br]also exist. 0:06:08.259,0:06:10.400 And those are the pieces of your application[br]that 0:06:10.400,0:06:13.740 care about that event that just happened.[br]And then 0:06:13.740,0:06:16.169 there's some sort of eventing in the middle.[br]Something 0:06:16.169,0:06:20.300 that dispatches those events from the notifier[br]to all 0:06:20.300,0:06:21.690 of the subscribers. 0:06:21.690,0:06:24.770 Now, this is really pretty basic, and you[br]might 0:06:24.770,0:06:29.889 wonder, like, why aren't these just method[br]calls? Well, 0:06:29.889,0:06:31.759 it's because of that eventing system that[br]we can 0:06:31.759,0:06:34.520 get the decoupling. It allows for the notifier[br]and 0:06:34.520,0:06:37.620 the subscriber to not necessarily know directly[br]about each 0:06:37.620,0:06:41.449 other. Those classes don't have to interact,[br]directly, without 0:06:41.449,0:06:44.789 that intermediary between them. 0:06:44.789,0:06:47.009 What's the relationship to the, to callbacks,[br]you might 0:06:47.009,0:06:50.520 say as well. There's, you know, at ActiveRecord,[br]we 0:06:50.520,0:06:52.979 have before and after hooks and around hooks[br]to 0:06:52.979,0:06:55.750 do all sorts of different things. Well, this[br]is 0:06:55.750,0:06:57.740 similar, but it's a little different from[br]what we're 0:06:57.740,0:07:00.870 gonna describe, because of that line, where[br]we have 0:07:00.870,0:07:04.759 to derive from ActiveRecord::Base. That's[br]a really tight coupling. 0:07:04.759,0:07:07.639 And what I'm gonna describe doesn't put any[br]requirements 0:07:07.639,0:07:11.280 on your class, except that it interacts with[br]the 0:07:11.280,0:07:15.280 event dispatcher as a collaborator. 0:07:15.280,0:07:17.430 So that's the basics of what I mean by 0:07:17.430,0:07:19.990 evented patterns. So let's take a look, now,[br]at 0:07:19.990,0:07:23.879 how it can influence coupling. So the first[br]example 0:07:23.879,0:07:26.479 that I'm gonna draw is about internal coupling.[br]So 0:07:26.479,0:07:28.050 when I say that, I mean, things that are 0:07:28.050,0:07:30.430 within the scope of your application, the[br]code that 0:07:30.430,0:07:32.979 you own and that you've written. 0:07:32.979,0:07:36.490 So, working for New Relic, the gem that I 0:07:36.490,0:07:39.740 work on, you install it in your application[br]and 0:07:39.740,0:07:43.720 it spins up, starts monitoring performance[br]information, and then 0:07:43.720,0:07:46.099 sends it back every minute to New Relic so 0:07:46.099,0:07:48.060 we can give you pretty graphs and alerting[br]and 0:07:48.060,0:07:50.889 all sorts of insight into what's going on[br]in 0:07:50.889,0:07:52.490 your app. 0:07:52.490,0:07:55.669 When this gem was originally created, we would[br]load 0:07:55.669,0:07:57.490 things up when the app starts and we read 0:07:57.490,0:07:59.550 a little config file to say what types of 0:07:59.550,0:08:01.479 things we want to be doing. You know, there's 0:08:01.479,0:08:03.310 features that you can turn on and turn off 0:08:03.310,0:08:06.710 and configure. And we knew the story about[br]what 0:08:06.710,0:08:10.419 this configuration was when the application[br]had successfully gotten 0:08:10.419,0:08:11.099 run. 0:08:11.099,0:08:14.770 Well, later on, we added a feature. And that 0:08:14.770,0:08:19.729 feature was server-side configuration. So[br]the application now connects 0:08:19.729,0:08:22.860 to our server and gets back some additional[br]set 0:08:22.860,0:08:26.939 of configuration values. And what this means[br]is that 0:08:26.939,0:08:29.039 the point in time at which we could assume 0:08:29.039,0:08:33.260 that the application was actually configured[br]changed. If we 0:08:33.260,0:08:35.610 had put a bunch of logic directly into our 0:08:35.610,0:08:37.729 app start up, like right there in the initialize 0:08:37.729,0:08:40.659 where things start running, we now didn't[br]have the 0:08:40.659,0:08:43.700 right answer for what the configuration was.[br]We have 0:08:43.700,0:08:46.920 to wait until that connect happens in the[br]background 0:08:46.920,0:08:48.890 before we can do that. 0:08:48.890,0:08:50.330 So let's take a look at what happened with 0:08:50.330,0:08:53.590 that connect method. So we make a call out 0:08:53.590,0:08:56.830 to the server and, you know, this is obviously 0:08:56.830,0:08:59.090 a little stripped down. There's error handling[br]in real 0:08:59.090,0:09:01.160 life. But we get back some sort of configuration 0:09:01.160,0:09:03.690 from the server. It tells us what those settings 0:09:03.690,0:09:06.160 are supposed to be. We pass that along to 0:09:06.160,0:09:10.400 finish set up and then finish set up starts 0:09:10.400,0:09:12.670 looking like a little bit of a mess. There's 0:09:12.670,0:09:15.160 a whole bunch of different concerns here,[br]right. We've 0:09:15.160,0:09:19.970 got something about naming rules. Something[br]about cross-application tracing. 0:09:19.970,0:09:23.380 Javascript. Some sort of beacon, like. It's[br]not important 0:09:23.380,0:09:25.080 what all of the inner details of all of 0:09:25.080,0:09:27.330 these pieces are. But none of them are really 0:09:27.330,0:09:29.450 related. The only thing about them is that[br]they 0:09:29.450,0:09:32.980 care that the configuration is ready. They're[br]wanting to 0:09:32.980,0:09:35.870 respond to that event that happened, that[br]the config 0:09:35.870,0:09:37.380 is set. 0:09:37.380,0:09:41.560 Now, one of the outgrowths of the code being 0:09:41.560,0:09:43.220 laid out like this is that we would like 0:09:43.220,0:09:45.660 to be able to write some simple tests. Some 0:09:45.660,0:09:49.060 unit tests, like DHH tells us we shouldn't,[br]that 0:09:49.060,0:09:50.810 look kind of like this. We run our given 0:09:50.810,0:09:52.480 set up against a chosen config and then we 0:09:52.480,0:09:54.440 can see the results of what came out of 0:09:54.440,0:09:55.010 that. 0:09:55.010,0:09:57.490 But, in practice, what we end up having to 0:09:57.490,0:09:59.510 do is we end up having to stub out 0:09:59.510,0:10:02.050 things. Like those different collaborators[br]that were in there. 0:10:02.050,0:10:04.780 The cross application tracing. If we don't[br]care about 0:10:04.780,0:10:06.220 it in this test, but we still need to 0:10:06.220,0:10:09.900 make sure that that code path can run without 0:10:09.900,0:10:12.610 tripping anything up or crashing because things[br]aren't filled 0:10:12.610,0:10:16.040 out the way that it needs it to be. 0:10:16.040,0:10:18.400 Things can get even worse than this. Now that 0:10:18.400,0:10:22.100 beacon line down on the bottom, you know,[br]we're 0:10:22.100,0:10:23.910 constructing a brand new object. Who, who[br]knows what 0:10:23.910,0:10:26.950 that thing might be doing internally. You[br]know? I 0:10:26.950,0:10:29.940 mean, nobody's ever written code like this,[br]right, that 0:10:29.940,0:10:32.650 does something bad like that from a constructor[br]for 0:10:32.650,0:10:35.710 an object. That doesn't happen. But, you know,[br]we 0:10:35.710,0:10:37.870 end up having to do things like stubbing out 0:10:37.870,0:10:41.570 new. Make it so that objects don't do interactions 0:10:41.570,0:10:43.570 and things that we don't really want. 0:10:43.570,0:10:47.310 Well, what if we could take this whole method 0:10:47.310,0:10:49.580 and just get rid of it in the form 0:10:49.580,0:10:53.290 that it's in and instead we notify that an 0:10:53.290,0:10:56.810 event has happened. We tell our event system[br]that 0:10:56.810,0:10:59.840 the system is now fully configured. We are[br]ready 0:10:59.840,0:11:04.110 to go. Everything's logged. We can head on. 0:11:04.110,0:11:07.080 Now this has some really nice side-effects.[br]One of 0:11:07.080,0:11:10.860 them is that beacon code. Now, in initialize,[br]you 0:11:10.860,0:11:13.430 still see the code where we're making this[br]HTTP 0:11:13.430,0:11:16.780 callout. But it's not wrapped in this subscribe[br]block. 0:11:16.780,0:11:19.490 So it means that that call is only going 0:11:19.490,0:11:22.420 to happen when the event system lets us know 0:11:22.420,0:11:25.640 that this configuration event has occurred.[br]That provides a 0:11:25.640,0:11:29.110 buffer. You can safely create a beacon now[br]and 0:11:29.110,0:11:33.230 it's not going to immediately go hit the network. 0:11:33.230,0:11:35.190 The tests surround the finished set up method[br]become 0:11:35.190,0:11:38.440 very slim and very straightforward as well.[br]All the 0:11:38.440,0:11:41.610 finish set up is responsible for is firing[br]that 0:11:41.610,0:11:43.880 event. And we check that that event gets dispatched 0:11:43.880,0:11:46.710 correctly and that's all that we need to unit 0:11:46.710,0:11:50.160 test at this level. And unit testing for the 0:11:50.160,0:11:53.750 individual effects that occur, moves over[br]and gets done 0:11:53.750,0:11:56.190 in the place that responds to that event.[br]The 0:11:56.190,0:11:59.330 thing that is gonna subscribe to the event[br]now 0:11:59.330,0:12:01.370 takes the responsibility for testing that. 0:12:01.370,0:12:04.070 Now, this doesn't cover everything. There[br]is a need 0:12:04.070,0:12:06.300 for an integration test. You do want something[br]that 0:12:06.300,0:12:08.590 sees that we wire up to the right events. 0:12:08.590,0:12:10.810 But you probably have tests that are gonna[br]exercise 0:12:10.810,0:12:13.730 those things anyways, if this isn't a critical[br]path 0:12:13.730,0:12:16.570 of your application. 0:12:16.570,0:12:18.990 So events allow us, within our own code, to 0:12:18.990,0:12:23.860 have more focused tests around those individual[br]pieces, more 0:12:23.860,0:12:27.910 independence between the classes. The configuration[br]in the finished 0:12:27.910,0:12:30.980 set up no longer has to know anything about 0:12:30.980,0:12:34.850 the Javascript instrumentor, the cross-application[br]tracer, the beacon. All 0:12:34.850,0:12:37.770 of that is pried apart. 0:12:37.770,0:12:39.970 And we found that this also starts to kind 0:12:39.970,0:12:43.020 of create a language within your application.[br]A domain 0:12:43.020,0:12:45.530 language, if you will. Because these are the[br]important 0:12:45.530,0:12:48.960 events that happen for us. We care, as the 0:12:48.960,0:12:51.180 New Relic gem, that we are configured. That[br]is 0:12:51.180,0:12:53.180 a critical thing for us. And there's now a 0:12:53.180,0:12:55.150 name for that. It's not just a bunch of 0:12:55.150,0:12:57.160 stuff that's tacked on to the end of one 0:12:57.160,0:12:59.470 of our methods. 0:12:59.470,0:13:03.020 It's not all roses, though. There is an issue 0:13:03.020,0:13:05.720 if you have some sort of ordering that's required 0:13:05.720,0:13:08.420 in the things that respond to those events.[br]And 0:13:08.420,0:13:10.340 actually we've had a couple of situations[br]where we've 0:13:10.340,0:13:13.050 been refactoring code and trying to pull it[br]into 0:13:13.050,0:13:16.460 event handlers and discovered that there were[br]dependencies between 0:13:16.460,0:13:20.290 different subscribers that aren't really handled[br]by a really 0:13:20.290,0:13:22.830 simple event system like this. 0:13:22.830,0:13:24.920 So, that's something that you have to watch[br]out 0:13:24.920,0:13:26.370 for. If there's a lot of that sort of 0:13:26.370,0:13:29.080 ordering, you're gonna have to deal with that[br]somewhere 0:13:29.080,0:13:31.110 in your code. 0:13:31.110,0:13:33.770 It can also make debugging and reasoning about[br]things 0:13:33.770,0:13:37.080 a little harder. It does spread some of those 0:13:37.080,0:13:40.130 responsibilities out. Now you don't see one[br]method that 0:13:40.130,0:13:41.760 lists all of the things that we do on 0:13:41.760,0:13:43.910 connect. You have to go search for things[br]that 0:13:43.910,0:13:46.560 subscribe to those events. But in the right[br]cases 0:13:46.560,0:13:48.810 I feel like it can buy you things with 0:13:48.810,0:13:51.700 the other benefits it brings along that outweigh[br]that. 0:13:51.700,0:13:55.810 Lastly, it is a performance consideration.[br]You know, I 0:13:55.810,0:13:58.190 would not use this sort of structure in a 0:13:58.190,0:14:00.860 tight loop that's gonna get called a million[br]times 0:14:00.860,0:14:03.170 a second. You know. If it's something like[br]we're 0:14:03.170,0:14:08.180 responding to a configuration event, like,[br]that we are 0:14:08.180,0:14:10.680 now ready to go or somebody just signed up. 0:14:10.680,0:14:12.200 I mean, it'd be great if you had a 0:14:12.200,0:14:14.930 million people signing up a minute, but reality[br]is 0:14:14.930,0:14:19.140 it's not happening as frequently as that.[br]So, being 0:14:19.140,0:14:21.440 aware of how this will impact your performance[br]is 0:14:21.440,0:14:25.240 really critical. 0:14:25.240,0:14:27.300 Internal coupling, like within the code that[br]you write 0:14:27.300,0:14:29.570 yourself, though, is not the only place where[br]you 0:14:29.570,0:14:33.320 can get bound to different things. So in,[br]in 0:14:33.320,0:14:34.940 the New Relic gem, we have a lot of 0:14:34.940,0:14:38.700 different functionality that we instrument[br]that work through middleware. 0:14:38.700,0:14:42.370 So we do Javascript insertion for doing end[br]user 0:14:42.370,0:14:44.640 timings. So as your request is going back[br]out, 0:14:44.640,0:14:48.640 we'll modify your html and put things in there. 0:14:48.640,0:14:51.120 We have error collection. So if there are[br]unhandled 0:14:51.120,0:14:54.870 exceptions that occur during your call, at[br]the rack 0:14:54.870,0:14:57.050 level, we will actually gather those up and[br]see 0:14:57.050,0:14:59.420 that those happened and report them back. 0:14:59.420,0:15:02.440 And we do things with HTTP requests between[br]the 0:15:02.440,0:15:04.760 applications if both ends of them are running[br]New 0:15:04.760,0:15:07.920 Relic. And we need to modify headers, HTTP[br]headers 0:15:07.920,0:15:10.180 that are on those requests. And all of these 0:15:10.180,0:15:13.990 separate things fit for us very well within[br]middlewares. 0:15:13.990,0:15:16.880 But, that makes kind of an assumption that[br]everything 0:15:16.880,0:15:19.780 that we want to apply that functionality to[br]is 0:15:19.780,0:15:22.180 built on top of rack. And while that's a 0:15:22.180,0:15:23.960 pretty good assumption for a lot of things[br]in 0:15:23.960,0:15:26.270 the Ruby space, we do support things that[br]aren't 0:15:26.270,0:15:29.210 necessarily configured that way. 0:15:29.210,0:15:31.070 We also want to avoid people having to set 0:15:31.070,0:15:34.130 things up. There are certain cases where maybe[br]you 0:15:34.130,0:15:36.530 have to manually add the things that we've[br]created, 0:15:36.530,0:15:38.770 and if we have seven different middlewares[br]that you 0:15:38.770,0:15:41.540 need to add for all this different functionality,[br]that's 0:15:41.540,0:15:46.350 kind of problematic from a configuration view[br]point. 0:15:46.350,0:15:48.510 So our solution to this was that we standardized 0:15:48.510,0:15:53.930 on having one middleware that we commonly[br]will install. 0:15:53.930,0:15:56.220 And we use events to actually do the dispatch 0:15:56.220,0:15:58.430 from there. So you'll see this is just a 0:15:58.430,0:16:00.940 very basic middleware. When a request comes[br]in and 0:16:00.940,0:16:04.230 hits call, we notify on the before and pass 0:16:04.230,0:16:06.700 along the environment that we got. We call[br]through 0:16:06.700,0:16:09.450 to the app inside and notify after and then 0:16:09.450,0:16:11.270 return the results. 0:16:11.270,0:16:13.610 So this allows us to be able to plug 0:16:13.610,0:16:16.480 things in that maybe are not shaped like rack. 0:16:16.480,0:16:18.870 We could use some of that code, like in 0:16:18.870,0:16:21.760 the cross application tracing. If we had some[br]web 0:16:21.760,0:16:24.300 server that was not rack-based or some configuration[br]that 0:16:24.300,0:16:26.920 was not gonna run through middleware, we could[br]still 0:16:26.920,0:16:29.470 have it generate a before call from the right 0:16:29.470,0:16:33.410 point and handle that with this same code,[br]without 0:16:33.410,0:16:36.940 having to deal with trying to create middlewares[br]or 0:16:36.940,0:16:39.610 insert something at a point that doesn't really[br]fit. 0:16:39.610,0:16:42.380 Now, just for the middleware case, you know,[br]this 0:16:42.380,0:16:44.200 probably could have been solved with some[br]sort of 0:16:44.200,0:16:46.970 composition. But, for us, it was actually[br]a really 0:16:46.970,0:16:50.570 powerful technique for keeping our code decoupled[br]from the 0:16:50.570,0:16:53.490 library that we were building on top of. That 0:16:53.490,0:16:56.480 looser coupling depends a lot on what sort[br]of 0:16:56.480,0:16:59.010 library and what your interactions with it[br]are, you 0:16:59.010,0:17:02.940 know. You're maintaining, basically, kind[br]of a compatibility layer. 0:17:02.940,0:17:04.760 And the more code that you have to put 0:17:04.760,0:17:07.500 into that layer, the more you should probably[br]think 0:17:07.500,0:17:10.299 about whether you're approaching it correctly.[br]Obviously you can't 0:17:10.299,0:17:13.220 do something like this with ActiveRecord,[br]it's just not 0:17:13.220,0:17:15.539 gonna be plausible. But if you have a small 0:17:15.539,0:17:18.819 number of points where you interact with another[br]third-party 0:17:18.819,0:17:21.419 library, applying events at those boundaries[br]can be a 0:17:21.419,0:17:24.059 way that you can keep some separation between[br]your 0:17:24.059,0:17:27.809 code and the library that you're dealing with. 0:17:27.809,0:17:30.779 So that's coupling. That's sort of the primary[br]motivator 0:17:30.779,0:17:33.590 behind using an evented pattern is to decouple[br]the 0:17:33.590,0:17:36.580 pieces of your application and allow for those[br]to 0:17:36.580,0:17:39.960 be looser and not as away of what's on 0:17:39.960,0:17:42.659 the other end of either firing or responding[br]to 0:17:42.659,0:17:44.580 an event. 0:17:44.580,0:17:47.840 So, let's talk about what it actually takes[br]to 0:17:47.840,0:17:51.620 implement this. What does this look like in[br]practice? 0:17:51.620,0:17:53.960 So I have created a small gem. This is 0:17:53.960,0:17:56.110 sort of an abstraction from what we do in 0:17:56.110,0:17:58.669 the New Relic gem. We don't use it directly 0:17:58.669,0:18:01.720 and I am not suggesting this for production[br]use. 0:18:01.720,0:18:03.840 But it's a really good example of how simple 0:18:03.840,0:18:07.940 it is to implement something like this in[br]Ruby. 0:18:07.940,0:18:12.169 So there's one primary class. The SimpleEvents::Notifier.[br]When we 0:18:12.169,0:18:14.980 initialize that, it's gonna be the central[br]thing that 0:18:14.980,0:18:17.309 keeps track of all the events. And everybody's[br]gonna 0:18:17.309,0:18:20.580 talk to this notifier object. So we hold onto 0:18:20.580,0:18:23.070 a hash, which is where we're gonna store those 0:18:23.070,0:18:28.230 handlers from the people that subscribe to[br]us. 0:18:28.230,0:18:31.629 Subscribing gets done. Passing in just a key[br]for 0:18:31.629,0:18:34.320 what the event is. We typically use symbols[br]within 0:18:34.320,0:18:37.009 our application. Some similar things that[br]we'll see later 0:18:37.009,0:18:39.809 use strings. And then hands in a block, which 0:18:39.809,0:18:41.980 is the code for it to run at that 0:18:41.980,0:18:44.620 point that that event gets fired. 0:18:44.620,0:18:46.149 And then it's just a simple matter of keeping 0:18:46.149,0:18:48.360 track of that list of handlers. Each event[br]may 0:18:48.360,0:18:50.480 have multiple handlers, so we make sure the[br]array 0:18:50.480,0:18:53.509 is there and add that handler onto the list. 0:18:53.509,0:18:56.029 Now there's one other line here that we're[br]dealing 0:18:56.029,0:18:58.980 with and that's checking for runaway subscriptions. 0:18:58.980,0:19:00.429 That has to do with the fact that for 0:19:00.429,0:19:03.990 our usage, there is a limited number of things 0:19:03.990,0:19:06.779 that should be subscribing to events. This[br]is not 0:19:06.779,0:19:09.740 something where every single web request that[br]comes through 0:19:09.740,0:19:11.879 subscribes and hooks itself in. And we'll[br]talk a 0:19:11.879,0:19:14.490 little bit later on about some of the negative 0:19:14.490,0:19:16.610 side effects you can have if it's happening. 0:19:16.610,0:19:19.269 So, for us, if more than a hundred event 0:19:19.269,0:19:22.009 subscribers have subscribed to a given event,[br]we actually 0:19:22.009,0:19:24.179 have a bug. And so we check for that 0:19:24.179,0:19:27.639 and make sure to warn that that's going on. 0:19:27.639,0:19:29.769 Your mileage may vary depending on the structure[br]that 0:19:29.769,0:19:32.799 you choose to use. 0:19:32.799,0:19:35.000 Notifying is a little more complicated than[br]subscribing, but 0:19:35.000,0:19:37.370 not too much more. And we'll step through[br]it 0:19:37.370,0:19:40.120 here. So first off, we check whether the events 0:19:40.120,0:19:44.620 collection has any handlers for the particular[br]key that 0:19:44.620,0:19:46.500 we just passed in. And this is one of 0:19:46.500,0:19:50.080 the really nice aspects of taking this simple[br]approach. 0:19:50.080,0:19:53.350 There's no central registry. There's nothing[br]to set up. 0:19:53.350,0:19:55.870 And event, I can create a handler for an 0:19:55.870,0:19:57.830 event that doesn't exist or I can start firing 0:19:57.830,0:20:00.360 and event that nobody handles, and it all[br]just 0:20:00.360,0:20:03.419 gracefully falls out. It doesn't cause any[br]problems if 0:20:03.419,0:20:07.220 there aren't handlers wired up for things. 0:20:07.220,0:20:09.870 If we do find that there are event handlers, 0:20:09.870,0:20:13.480 we simply iterate across those and call passing[br]along 0:20:13.480,0:20:17.480 the arguments that we received on the event.[br]For 0:20:17.480,0:20:20.649 our particular use in New Relic, we trap errors 0:20:20.649,0:20:24.379 and will log and swallow any exceptions that[br]happen 0:20:24.379,0:20:28.100 as a result of our direct event handlers.[br]Now, 0:20:28.100,0:20:29.730 this is kind of an artifact of the sort 0:20:29.730,0:20:31.230 of gem that we are. We're there in the 0:20:31.230,0:20:33.830 background and these events are things for[br]the agent 0:20:33.830,0:20:35.929 and for us sending our data back. 0:20:35.929,0:20:37.679 And the worst possible thing that we could[br]do 0:20:37.679,0:20:40.360 is crash an application. So we trap everything[br]that 0:20:40.360,0:20:42.320 goes through. If you were doing this in an 0:20:42.320,0:20:44.600 application setting, you may want to log.[br]You may 0:20:44.600,0:20:47.409 also want to raise those errors and fail quickly 0:20:47.409,0:20:49.149 in the case that one of your notifiers has 0:20:49.149,0:20:52.470 something go wrong. But your mileage, you[br]know, you 0:20:52.470,0:20:54.340 can choose what the right policy is for how 0:20:54.340,0:20:56.509 you're using events and what setting you're[br]putting those 0:20:56.509,0:20:58.379 in. 0:20:58.379,0:21:01.570 So that's it. Like, that's an entire eventing[br]system 0:21:01.570,0:21:04.309 is about fifty lines of Ruby, which allows[br]you 0:21:04.309,0:21:07.730 to decouple those different pieces of your[br]application. But 0:21:07.730,0:21:09.009 the fact of the matter is that you might 0:21:09.009,0:21:12.159 not have to even write that system yourself[br]if 0:21:12.159,0:21:16.570 you're using Rails. ActiveSupport::Notifications[br]have been baked in from 0:21:16.570,0:21:19.259 I think about the 3.0 version of Rails. And 0:21:19.259,0:21:21.210 it's a system that's very much like what we've 0:21:21.210,0:21:22.749 described here. 0:21:22.749,0:21:27.149 I'll abbreviate in the slides a little because[br]ActiveSupport::Notifications 0:21:27.149,0:21:29.749 gets really, really long in the code, so,[br]we'll 0:21:29.749,0:21:32.389 scrunch that down a little bit. But all sorts 0:21:32.389,0:21:35.009 of things flow through this evented system[br]any time 0:21:35.009,0:21:37.679 a Rails request is occurring. So we get things 0:21:37.679,0:21:40.389 about the dispatch at the top level. We get 0:21:40.389,0:21:42.820 things about the controller and what it's[br]doing. We 0:21:42.820,0:21:47.460 get notifications about SQL calls. We get[br]notifications about 0:21:47.460,0:21:50.940 view and template rendering. Like, tons and[br]tons of 0:21:50.940,0:21:54.830 events are streaming through this ActiveSupport::Notification[br]system all of 0:21:54.830,0:21:55.669 the time. 0:21:55.669,0:21:58.240 Some common things that you might be familiar[br]with, 0:21:58.240,0:22:00.149 like the log, the debug log that you get 0:22:00.149,0:22:04.279 of your queries, that's running through ActiveSupport::Notifications[br]that are 0:22:04.279,0:22:08.779 fired by ActiveRecord. So what's this look[br]like? 0:22:08.779,0:22:11.659 It looks very similar to what we've seen before. 0:22:11.659,0:22:14.039 So subscribing to an event, you give it the 0:22:14.039,0:22:16.480 name, you give it a block, and then you 0:22:16.480,0:22:18.389 can see the form of what one of these 0:22:18.389,0:22:20.710 events was that came through. It'll hand it[br]to 0:22:20.710,0:22:23.940 us. It's got a name. It's got an identifier. 0:22:23.940,0:22:25.440 And then it's got this hash that's sort of 0:22:25.440,0:22:30.399 a payload of data that comes along with it. 0:22:30.399,0:22:34.259 ActiveSupport also provides a simple wrapper[br]for handling that 0:22:34.259,0:22:36.710 payload and handling those events when they're[br]in a 0:22:36.710,0:22:39.299 very common form. So most of the things that 0:22:39.299,0:22:41.749 Rails sends out, they're gonna have a name.[br]They're 0:22:41.749,0:22:44.279 gonna have a duration and a payload in a 0:22:44.279,0:22:46.840 standard format. So this class kind of wraps[br]up 0:22:46.840,0:22:51.370 that access and makes it a little neater. 0:22:51.370,0:22:54.240 On the notifying side, the method that you[br]call 0:22:54.240,0:22:57.259 is instrument. So if you want to fire an 0:22:57.259,0:22:59.259 event and have that be sent out to the 0:22:59.259,0:23:01.789 system, you just give it the string for the 0:23:01.789,0:23:04.330 name, give it whatever payload for the data,[br]and 0:23:04.330,0:23:07.009 you're off and running. 0:23:07.009,0:23:08.450 There's also a nice form of it that it 0:23:08.450,0:23:11.690 has that will wrap your code in a block, 0:23:11.690,0:23:13.759 so you can do something in there, and what 0:23:13.759,0:23:16.259 that'll do is that'll tack a duration on.[br]So 0:23:16.259,0:23:18.460 it'll time what's going on. And this is one 0:23:18.460,0:23:21.179 of the key things that ActiveSupport::Notifications[br]are used for 0:23:21.179,0:23:23.840 within Rails is timing how long those different[br]things 0:23:23.840,0:23:25.889 take. Those timings that you see in your debug 0:23:25.889,0:23:28.809 output are all coming from things being wrapped[br]by 0:23:28.809,0:23:32.509 this sort of instrument call. 0:23:32.509,0:23:34.110 As with all things Rails, there's a lot more 0:23:34.110,0:23:36.889 richness as well under the surface. You can[br]do 0:23:36.889,0:23:42.129 subscriptions by regular expressions. If events[br]are nested, the 0:23:42.129,0:23:45.730 ActiveSupport::Notifications system keeps[br]track of that and will take 0:23:45.730,0:23:47.909 care of letting you know so you could look 0:23:47.909,0:23:50.499 and see whether an event was occurring within[br]another 0:23:50.499,0:23:53.919 event, and you can go crazy if that's happening 0:23:53.919,0:23:55.289 too much, but. 0:23:55.289,0:23:58.669 There are temporary subscriptions and unsubscribe,[br]which is useful 0:23:58.669,0:24:00.990 in certain scenarios where, maybe you do want[br]to 0:24:00.990,0:24:04.629 have something hook into the ActiveSupport::Notifications[br]for the course 0:24:04.629,0:24:06.749 of a request. But you don't want to have 0:24:06.749,0:24:09.509 that handler hanging around and responding[br]for the rest 0:24:09.509,0:24:12.490 of the lifetime of your application. 0:24:12.490,0:24:13.990 And there's some really great examples that[br]you can 0:24:13.990,0:24:17.249 find in Rails itself. So the log subscriber[br]class, 0:24:17.249,0:24:18.679 which is the thing that spits out a lot 0:24:18.679,0:24:20.990 of your development log, is a great example[br]of 0:24:20.990,0:24:26.119 how you can hook into that underlying infrastructure. 0:24:26.119,0:24:28.090 So that's the mechanism. That's how you can[br]build 0:24:28.090,0:24:30.909 events in or use a library that you're probably 0:24:30.909,0:24:33.019 already using to get a lot of these things 0:24:33.019,0:24:35.309 done. 0:24:35.309,0:24:37.789 Let's talk a little bit more in detail about 0:24:37.789,0:24:39.749 the different parties that are involved here,[br]and what 0:24:39.749,0:24:46.419 they're responsible for and considerations[br]there. So notifiers have 0:24:46.419,0:24:48.749 a lot of responsibility. They're, they're[br]kind of the 0:24:48.749,0:24:52.720 key points in your application. You should[br]be, in 0:24:52.720,0:24:55.159 this scheme, you would be adding events for[br]the 0:24:55.159,0:24:56.919 things that matter the most. 0:24:56.919,0:24:59.539 And on that, I think that naming is a 0:24:59.539,0:25:02.119 really critical thing around this to get the[br]benefit 0:25:02.119,0:25:04.850 that you're looking for. So in the example[br]that 0:25:04.850,0:25:08.179 I gave up front, you'll, you probably didn't[br]notice, 0:25:08.179,0:25:11.710 but I named the event configured, to say,[br]hey, 0:25:11.710,0:25:13.460 we are in a state where we are fully 0:25:13.460,0:25:13.909 configured. 0:25:13.909,0:25:17.179 I didn't name it connect to server or finish 0:25:17.179,0:25:19.789 with the set up or, you know, binding it 0:25:19.789,0:25:21.899 to the mechanism of what it was. I couched 0:25:21.899,0:25:24.840 it in the terms of what mattered to my 0:25:24.840,0:25:27.029 application. I think that that's something[br]that's really powerful 0:25:27.029,0:25:29.639 if you do this right. If you, it allows 0:25:29.639,0:25:32.529 for changes in the location, like in our case, 0:25:32.529,0:25:34.899 that change of when we were configured. It[br]moved 0:25:34.899,0:25:37.799 from just plain application start up to a[br]point 0:25:37.799,0:25:39.789 in time in the future when we may hear 0:25:39.789,0:25:42.200 back from a server. And who knows when that 0:25:42.200,0:25:45.110 configured point might change in the future? 0:25:45.110,0:25:48.379 We're not bound by the event name to some 0:25:48.379,0:25:51.529 particular method or point in time. We can[br]change 0:25:51.529,0:25:53.440 that and still have it make sense within the 0:25:53.440,0:25:57.039 domain of what we've created. 0:25:57.039,0:25:59.369 It's also important to consider what your[br]payload is. 0:25:59.369,0:26:02.190 What data you're sending along from the notifier.[br]So 0:26:02.190,0:26:05.669 Rails follows the convention with ActiveSupport::Notifications[br]that I would 0:26:05.669,0:26:09.119 definitely encourage, of sending along primarily[br]a hash of 0:26:09.119,0:26:12.429 different values that you can pipe through.[br]I learned 0:26:12.429,0:26:14.480 this the hard way the second time that I 0:26:14.480,0:26:16.440 needed to add a bit of data onto one 0:26:16.440,0:26:19.509 of my events. And the mechanism, as we saw, 0:26:19.509,0:26:21.539 just sort of percolates the arguments along[br]that we've 0:26:21.539,0:26:22.399 given it. 0:26:22.399,0:26:24.570 Well, if you add another argument, all those[br]other 0:26:24.570,0:26:28.309 handlers downstream need to get updated. So[br]do it 0:26:28.309,0:26:30.570 from the start to make these things flexible.[br]Pass 0:26:30.570,0:26:33.049 your payloads along as a hash that you can 0:26:33.049,0:26:36.619 then add additional data that old event handlers[br]don't 0:26:36.619,0:26:38.619 need to care about and that new things can 0:26:38.619,0:26:41.619 pick up along the way. 0:26:41.619,0:26:44.549 On that topic of the payload as well, if 0:26:44.549,0:26:47.230 you're writing some sort of internal application,[br]you know, 0:26:47.230,0:26:50.029 you can put whatever you want into these payloads. 0:26:50.029,0:26:51.820 But as a third party, you may want to 0:26:51.820,0:26:54.769 be cautious if you're having other people,[br]other gems, 0:26:54.769,0:26:57.389 and other codes subscribe to these events[br]to try 0:26:57.389,0:27:01.619 to keep your payloads as primitive as you[br]can. 0:27:01.619,0:27:03.269 Maybe even all the way down to just base 0:27:03.269,0:27:03.909 types. 0:27:03.909,0:27:06.429 The advantage here is that you are, if you 0:27:06.429,0:27:08.799 put one of your internal classes as something[br]that 0:27:08.799,0:27:11.320 you're packing around in this event, and then[br]broadcast 0:27:11.320,0:27:13.970 it out to the world for everybody to use, 0:27:13.970,0:27:16.340 you now don't know who might be getting access 0:27:16.340,0:27:19.799 to those objects and using them. And depending[br]on 0:27:19.799,0:27:22.240 what sort of usage you've got with your, your 0:27:22.240,0:27:25.869 app, it can be difficult to make changes to 0:27:25.869,0:27:28.659 things that maybe you consider to be internal[br]details. 0:27:28.659,0:27:31.559 If you turn things into primitives, you know,[br]it, 0:27:31.559,0:27:33.970 they're just strings and hashes and numbers,[br]those are 0:27:33.970,0:27:37.279 pretty safe, right. You can maintain that[br]mapping from 0:27:37.279,0:27:40.309 your internal objects to those primitives[br]and not have 0:27:40.309,0:27:43.200 to worry about who might be changed when you 0:27:43.200,0:27:46.529 refactor. 0:27:46.529,0:27:49.070 So the other end of things is the subscribers. 0:27:49.070,0:27:52.590 I think it's really important to consider,[br]carefully, who 0:27:52.590,0:27:56.110 the subscribers are for a given event. This[br]pattern 0:27:56.110,0:27:58.610 doesn't fit everywhere. This is not something[br]where every 0:27:58.610,0:28:00.909 single thing that happens in your application[br]should be 0:28:00.909,0:28:04.059 an event. And if you're writing an event,[br]and 0:28:04.059,0:28:06.749 there's only one thing that's gonna handle[br]it, you 0:28:06.749,0:28:08.960 might be misapplying this pattern. You might[br]not get 0:28:08.960,0:28:12.090 the benefit that you need, there. 0:28:12.090,0:28:14.289 A lot of times, you'll find that there is 0:28:14.289,0:28:17.700 some natural home, some place within your[br]app that 0:28:17.700,0:28:20.639 is already there that is the right place to 0:28:20.639,0:28:23.389 be subscribing to that event and responding[br]to what's 0:28:23.389,0:28:25.950 happening. But if you don't, it's an, there's[br]some 0:28:25.950,0:28:28.309 interesting ideas around how you can create[br]what that 0:28:28.309,0:28:30.889 location is. So there's this gem that I've[br]run 0:28:30.889,0:28:33.950 into, it's called mutations. It's sort of[br]building command 0:28:33.950,0:28:37.460 objects that represent different actions that[br]happen in your 0:28:37.460,0:28:38.220 system. 0:28:38.220,0:28:40.929 Now, you know, you might recognize something[br]very like 0:28:40.929,0:28:42.960 this from earlier in the morning, but it can 0:28:42.960,0:28:48.110 be an interesting idea if you have key pieces 0:28:48.110,0:28:50.950 of your system where a workflow or something[br]that 0:28:50.950,0:28:55.190 occurs is really important. You can write[br]something, a 0:28:55.190,0:28:58.350 command, that encapsulates what the event[br]is, what that 0:28:58.350,0:29:00.549 action is that needs to be taken. And this 0:29:00.549,0:29:03.119 can be something that helps in those cases[br]that 0:29:03.119,0:29:05.600 I described, where there may be implicit ordering.[br]There 0:29:05.600,0:29:08.730 may be ordering between different components.[br]You could create 0:29:08.730,0:29:11.320 a command that wraps those up in the right 0:29:11.320,0:29:14.129 ordering to be applied and then have that[br]be 0:29:14.129,0:29:18.049 what responds to the events. 0:29:18.049,0:29:20.320 Probably one of the biggest difficulties that[br]you can 0:29:20.320,0:29:23.399 run into with an evented pattern is, if there's 0:29:23.399,0:29:26.450 too much nesting, if this gets overused, and[br]events 0:29:26.450,0:29:28.889 trigger events and trigger events on all sorts[br]of 0:29:28.889,0:29:32.169 different things, it can become very difficult.[br]And the 0:29:32.169,0:29:34.769 main advice that I have there is that this, 0:29:34.769,0:29:37.190 this technique works best, I think, at the[br]critical 0:29:37.190,0:29:39.679 lynch points of your application. The things[br]that you 0:29:39.679,0:29:42.899 really care about the most to be providing,[br]that 0:29:42.899,0:29:46.840 sort of visibility and language around. 0:29:46.840,0:29:48.659 And another thing to be aware of with the 0:29:48.659,0:29:50.799 implementation that we've done here. I've[br]had a number 0:29:50.799,0:29:53.090 of poeple come up afterwards and point out,[br]they're 0:29:53.090,0:29:56.149 like, it's all still synchronous. It's all[br]still just 0:29:56.149,0:29:58.919 running. I mean, this is just splitting up[br]where 0:29:58.919,0:30:01.929 those things are. And that's totally true.[br]This is 0:30:01.929,0:30:05.279 not as described something that will make[br]your application 0:30:05.279,0:30:09.059 parallel or asynchronous in how that event[br]handling happens. 0:30:09.059,0:30:11.239 But it might give you good points in time 0:30:11.239,0:30:13.289 when you could decide to push things off.[br]Things 0:30:13.289,0:30:15.129 could go to background jobs or things could[br]get 0:30:15.129,0:30:17.149 dispatched to all sorts of other places if[br]you 0:30:17.149,0:30:19.279 wanted. 0:30:19.279,0:30:21.460 It's also important with subscribers to watch[br]out for 0:30:21.460,0:30:25.889 leaks. There is, when you create a block,[br]so 0:30:25.889,0:30:27.999 like, if this subscriber was created for every[br]web 0:30:27.999,0:30:31.869 request, the fact that we have that block[br]potentially 0:30:31.869,0:30:34.509 holds onto a reference to this object and[br]keeps 0:30:34.509,0:30:36.850 it alive past a point in time when you 0:30:36.850,0:30:38.460 might have thought that it was gonna go away. 0:30:38.460,0:30:40.629 I've seen this not just in Ruby but in 0:30:40.629,0:30:42.580 a number of different languages with these[br]sorts of 0:30:42.580,0:30:46.600 evented patterns with handlers that get subscribed,[br]where they 0:30:46.600,0:30:48.730 can hold references to objects that you might[br]not 0:30:48.730,0:30:51.110 be expecting them too. And so you gotta watch 0:30:51.110,0:30:55.610 out for that to keep things from leaking. 0:30:55.610,0:30:58.389 So those are some ideas around the responsibilities[br]that 0:30:58.389,0:31:01.590 your subscribers and your notifiers should[br]have. And I 0:31:01.590,0:31:03.389 hope that maybe this has opened your eyes[br]a 0:31:03.389,0:31:06.110 little bit to some ideas about how you might 0:31:06.110,0:31:08.489 be able to partition your app differently.[br]What are 0:31:08.489,0:31:12.489 those responsibilities and things that happen[br]during your app 0:31:12.489,0:31:14.269 that would be worth having an event or worth 0:31:14.269,0:31:16.090 giving that name to. 0:31:16.090,0:31:17.399 And as you can see that it's a pretty 0:31:17.399,0:31:19.799 simple thing to implement that can give you[br]a 0:31:19.799,0:31:22.999 lot of benefit down the road. Thank you.