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