WEBVTT 00:00.270 --> 00:01.170 Hello everyone. 00:01.170 --> 00:06.480 Welcome to the new section of the course barrier future and pipeline design patterns in this section 00:06.480 --> 00:12.950 will see the three patterns barrier concurrency future design and pipeline design and work with them. 00:12.960 --> 00:17.490 Now we move on to the first video of this section that deals with barrier concurrency pattern. 00:17.490 --> 00:20.850 In this video we're going to take a look at the concept of barrier pattern. 00:20.850 --> 00:23.320 Then we'll create a barrier pattern and implement it. 00:24.150 --> 00:25.000 Let's start. 00:25.170 --> 00:28.100 The purpose of barrier pattern is simple. 00:28.350 --> 00:32.530 Put up a barrier so nobody passes until we have all the results we need. 00:32.760 --> 00:35.490 Something quite common in concurrent applications. 00:35.550 --> 00:37.080 Let's look at its description. 00:37.080 --> 00:42.000 Imagine the situation where we have a micro services application where one service needs to compose 00:42.000 --> 00:46.050 its response by merging the responses of other three micro services. 00:46.050 --> 00:48.090 This is where the barrier pattern can help us. 00:48.210 --> 00:52.530 Our barrier pattern could be a service that will block its response until it's been composed with the 00:52.530 --> 00:56.160 results returned by one or more different go routines or services. 00:56.160 --> 00:59.070 And what kind of primitive do we have that has a blocking nature. 00:59.070 --> 01:03.810 Well we can use LOC but it's more idiomatic in go to use an unbothered channel. 01:03.810 --> 01:06.000 What are our objectives. 01:06.000 --> 01:10.320 As its name implies the barrier pattern tries to stop an execution so it doesn't finish before it's 01:10.320 --> 01:11.520 ready to finish. 01:11.520 --> 01:16.410 The barrier patterns objectives are to compose the value of a type with the data coming from one or 01:16.410 --> 01:21.900 more go routines control the correctness of any of those incoming data pipes so that no inconsistent 01:21.900 --> 01:23.180 data is returned. 01:23.190 --> 01:28.080 We don't want her partially filled result because one of the pipes is returned an error for our example 01:28.080 --> 01:33.240 we're going to write a very typical situation in a micro services application an app that performs to 01:33.300 --> 01:38.270 H TTP get calls and joins them in a single response that were printed on the console. 01:38.390 --> 01:43.320 How a small app must perform each request in a different go routine and print results on the console. 01:43.320 --> 01:49.820 If both responses are great if any of them returns an error then we print just the error the design 01:49.820 --> 01:54.680 must be concurrent allowing us to take advantage of our multicore CPM use to make the calls in parallel 01:55.340 --> 01:56.100 in the diagram. 01:56.110 --> 02:00.700 These solid three lines represent calls and the dashed lines represent channels. 02:00.830 --> 02:06.890 The balloons are go routines so we have to go routines launched by the main function which could also 02:06.890 --> 02:08.270 be considered a good routine. 02:08.300 --> 02:12.190 These two functions will communicate back to the main function by using a common channel that they've 02:12.200 --> 02:15.270 received when they were created on the make request calls. 02:15.290 --> 02:17.920 Let's look at the acceptance criteria. 02:17.960 --> 02:22.400 Our main objective in this app is to get a merged response of two different calls so we can describe 02:22.400 --> 02:27.630 our acceptance criteria like this print on the console the merged results of the two calls to the link 02:27.630 --> 02:28.640 shown here. 02:28.670 --> 02:33.070 These are a couple of public endpoints that respond with data from the income and connections. 02:33.110 --> 02:35.330 They're very popular for testing purposes. 02:35.390 --> 02:37.310 You'll need an internet connection to do this exercise. 02:37.850 --> 02:40.590 If any of the calls fails it must not print any result. 02:40.730 --> 02:45.770 Just the error message or error messages if both calls failed the output must be printed as a composed 02:45.770 --> 02:47.850 result when both calls are finished. 02:47.870 --> 02:53.750 It means that we cannot print the result of one call and then the other now will look at unit test integration 02:54.230 --> 02:59.390 to write unit or integration tests for concurrent designs can sometimes be tricky but this won't stop 02:59.390 --> 03:01.930 us from writing our awesome unit tests. 03:02.030 --> 03:06.860 We'll have a single barrier method that accepts a set of end points defined as a string type the barrier 03:06.860 --> 03:10.940 will make a get request to each end point and compose the results before printing out. 03:10.940 --> 03:15.710 In this case we'll write 3 integration tests to simplify our code so we don't need to generate mock 03:15.710 --> 03:16.470 responses. 03:17.390 --> 03:20.180 First we'll create a new document called barrier Dok Go 03:23.100 --> 03:24.590 and another file barrier test. 03:24.600 --> 03:32.560 Don't go now Open the barrier test file and add the lines as shown. 03:32.560 --> 03:35.880 We have a single test that will execute three top tests. 03:36.010 --> 03:38.650 The first test makes two calls to the correct endpoints. 03:38.710 --> 03:42.670 The second test will have an incorrect endpoint so it must return an error. 03:42.760 --> 03:46.900 The last test will return the maximum timeout so that we can force a timeout error. 03:46.990 --> 03:51.010 We'll have a function called barrier that will accept an undetermined number of end points in the form 03:51.010 --> 03:57.470 of strings its signature could be like this as you can see the barrier function doesn't return any value 03:57.470 --> 04:00.300 because its result will be printed on the console. 04:00.380 --> 04:05.300 Previously we've written an implementation of an IO write interface to emulate the writing on the operating 04:05.300 --> 04:11.900 systems esti d out library just to change things a bit will capture the Estes out library instead of 04:11.900 --> 04:12.890 emulating one. 04:13.010 --> 04:16.180 The process to capture the EDL library isn't difficult. 04:16.190 --> 04:19.610 Once you understand concurrency primitives and go so let's add the function 04:22.430 --> 04:24.010 don't feel daunted by this code. 04:24.020 --> 04:25.360 It's really simple. 04:25.370 --> 04:27.060 First we created a pipe. 04:27.290 --> 04:32.720 A pipe allows us to connect and Io write the interface to an IO read interface so that the reader input 04:32.750 --> 04:40.600 is the right output we define the OS store FTD out as the writer then to capture FTD our output will 04:40.600 --> 04:44.290 need a different go routine that listens while we write to the console. 04:44.290 --> 04:48.470 As you know if we write we don't capture and if we capture we're not writing. 04:48.790 --> 04:53.710 The keyword here is while it's a good rule of thumb that if you find this word in some definition you'll 04:53.710 --> 04:55.690 probably need a concurrent structure. 04:55.690 --> 05:00.850 So we used to go keyword to launch a different go routine copiously read input to a bytes buffer before 05:00.850 --> 05:05.530 sending the contents of the buffer through a channel that we should have previously created. 05:05.800 --> 05:11.660 At this point we have a listening go meeting but we haven't printed anything yet so we call our not 05:11.660 --> 05:14.590 yet written function barrier with the provided endpoints. 05:14.600 --> 05:19.140 Next we have to close the writer to signal the go routine that no more input is going to come to it. 05:19.190 --> 05:23.100 Our channel called out blocks execution until some value is received. 05:23.180 --> 05:28.620 The one sent by our launch go reaching the last step is to return the contents captured from the console. 05:28.640 --> 05:29.040 Okay. 05:29.080 --> 05:34.310 So we have a function called Capture Barry output that will capture the outputs in STV out and return 05:34.310 --> 05:35.450 them as a string. 05:35.450 --> 05:36.400 We can write our tests. 05:36.410 --> 05:41.730 Now let's add the tests all the tests are very easy to implement. 05:41.840 --> 05:45.620 All in all it's the capture Barry output function that calls the barrier function. 05:45.830 --> 05:52.070 So we pass the end points in check the returned result our composed results directed to ATP colon for 05:52.200 --> 05:59.690 for Slash H TTP Ben to org must contain the text except dash encoding and user does agent in the responses 05:59.720 --> 06:00.720 of each end point. 06:00.890 --> 06:05.110 If we don't find those texts the tests will fail for further debugging purposes. 06:05.120 --> 06:10.190 We log the response in case we want check it with the minus lowercase v flag on the go test. 06:11.000 --> 06:16.640 Well edit our code further this time we use an incorrect endpoint your. 06:16.730 --> 06:22.250 So the response must return the error prefixed with the word error that will write ourselves in the 06:22.250 --> 06:23.570 barrier function. 06:23.660 --> 06:28.490 The last function we would use a time out of the TTP get client to a minimum of one millisecond. 06:28.580 --> 06:30.470 So we force a timeout. 06:30.470 --> 06:36.120 Let's add to our test further the time out milliseconds variable will be a package variable that will 06:36.120 --> 06:39.120 have to define later during implementation. 06:39.120 --> 06:44.810 Now we'll look at the implementation we needed to define a package variable called time out milliseconds. 06:44.850 --> 06:45.690 Let's start from there. 06:46.020 --> 06:50.710 Open the barrier don't go file and add the code lines as you can see here. 06:51.030 --> 06:57.810 The initial timeout delay is 5 seconds 5000 milliseconds and we'll need these packages in our code. 06:57.810 --> 07:01.820 Okay so we need a function that launches a go routine for each endpoint euro. 07:01.850 --> 07:06.750 You remember how we achieve the communication between routines exactly channels. 07:06.750 --> 07:10.660 So we'll need a channel to handle responses and a channel to handle errors. 07:10.860 --> 07:17.110 But we can simplify a bit more will receive two correct responses to errors or response and an error. 07:17.190 --> 07:22.950 In any case there are always two responses so we can join errors and responses in a merge type at these 07:22.950 --> 07:23.950 lines. 07:24.180 --> 07:29.040 So each go routine will send back a value of the barrier resp type. 07:29.250 --> 07:33.550 This value will have a value for IRR or value for the rest field. 07:33.600 --> 07:34.880 The procedure is simple. 07:35.040 --> 07:40.100 We create a channel of size to the one that received the responses of the barrier resp type. 07:40.440 --> 07:44.850 We launch both requests and wait for two responses and then check to see if there's any error. 07:46.190 --> 07:51.110 Following the previous description we created a buffered channel called in making it the size of the 07:51.110 --> 07:54.200 incoming end points and we deferred channel closing. 07:54.200 --> 07:58.700 Then we launched a function called Make request with each end point and the response channel. 07:58.700 --> 08:01.940 Now we'll loop twice one for each end point in the loop. 08:01.940 --> 08:05.570 We block the execution waiting for data from the end channel. 08:05.570 --> 08:11.960 If we find an error we print it prefixed with the word error as we expect in our tests and set has error 08:11.960 --> 08:13.370 var to true. 08:13.520 --> 08:18.920 After two responses if we don't find any error that is has error equals to false. 08:18.920 --> 08:21.610 We print every response and the channel will be closed. 08:21.710 --> 08:24.250 We still lack the make request function. 08:24.320 --> 08:30.180 Let's add that make request function is a very straightforward function that accepts a channel whose 08:30.270 --> 08:34.550 output Barry arrest values to and a your relative request. 08:34.800 --> 08:40.920 We create an H2 DP dot client and set its time outfield to the value of the time out milliseconds package 08:40.920 --> 08:42.120 variable. 08:42.120 --> 08:45.660 This is how we can change the timeout delay before the end function tests. 08:45.720 --> 08:48.030 Then we simply make the get call. 08:48.090 --> 08:53.190 Take the response pass it to a byte slice and send it through the out channel. 08:53.250 --> 08:57.720 We do all this by filling a variable called rez of the Barry arrest type. 08:57.960 --> 09:03.230 If we find an error while performing a get request or passing the body of the result we fill the rest 09:03.230 --> 09:09.270 or ARRL field send it to the out channel which has the opposite side connected to the original go routine 09:09.720 --> 09:11.400 and exit the function. 09:11.400 --> 09:14.490 So we don't send to values through the out channel by mistake. 09:14.700 --> 09:16.200 Time to run the tests. 09:16.230 --> 09:19.990 Remember that you need an internet connection or the first two Tests will fail. 09:20.010 --> 09:23.130 Well first try the test that has two endpoints that are correct. 09:23.130 --> 09:27.790 Say this file open the terminal and run this command. 09:27.920 --> 09:28.600 Perfect. 09:28.610 --> 09:33.500 We have a Jason respond to the key headers and another Jason response with a key. 09:33.500 --> 09:39.790 User agent in our integration tests we were looking for the strings used thus agent and accept Russian 09:39.790 --> 09:41.110 coding which are present. 09:41.270 --> 09:47.090 So the test has passed successfully now will run the test has an incorrect endpoint for that will run 09:47.090 --> 09:48.410 another command. 09:48.590 --> 09:54.240 We can see that we have had an era where HDP code and forward slash forward slash malformed dash you 09:54.240 --> 09:56.990 or L has returned a no such host error. 09:57.040 --> 10:01.630 Our request to this you URL must return a text with the keyword error prefixed. 10:01.910 --> 10:04.170 As we stated during the acceptance criteria. 10:04.260 --> 10:06.310 That's why this test is correct. 10:06.440 --> 10:10.010 The last test reduced time out to 1 milliseconds. 10:10.010 --> 10:15.680 Well again run the command again the test passed successfully and we've got to timeout errors. 10:15.800 --> 10:19.550 The Urals were correct but we didn't have a response in less than one millisecond. 10:19.700 --> 10:24.800 So the client returned a timeout error that the barrier pattern opens a door of micros services programming 10:24.800 --> 10:26.450 with its composer well nature. 10:26.540 --> 10:28.590 It could be considered a structural pattern. 10:28.600 --> 10:32.510 As you can imagine the barrier pattern is not only useful to make network requests. 10:32.510 --> 10:35.840 We could also use it to split some tasks into multiple go routines. 10:35.840 --> 10:40.910 For example an expensive operation could be split into a few smaller operations distributed in different 10:40.910 --> 10:44.900 go routines to maximize parallelism and achieve better performance. 10:44.930 --> 10:49.910 In this video we understood the barrier pattern successfully in the next video we'll look at the future 10:49.910 --> 10:50.570 design pattern.