Hello everyone.
Welcome to the new section of the course barrier future and pipeline design patterns in this section
will see the three patterns barrier concurrency future design and pipeline design and work with them.
Now we move on to the first video of this section that deals with barrier concurrency pattern.
In this video we're going to take a look at the concept of barrier pattern.
Then we'll create a barrier pattern and implement it.
Let's start.
The purpose of barrier pattern is simple.
Put up a barrier so nobody passes until we have all the results we need.
Something quite common in concurrent applications.
Let's look at its description.
Imagine the situation where we have a micro services application where one service needs to compose
its response by merging the responses of other three micro services.
This is where the barrier pattern can help us.
Our barrier pattern could be a service that will block its response until it's been composed with the
results returned by one or more different go routines or services.
And what kind of primitive do we have that has a blocking nature.
Well we can use LOC but it's more idiomatic in go to use an unbothered channel.
What are our objectives.
As its name implies the barrier pattern tries to stop an execution so it doesn't finish before it's
ready to finish.
The barrier patterns objectives are to compose the value of a type with the data coming from one or
more go routines control the correctness of any of those incoming data pipes so that no inconsistent
data is returned.
We don't want her partially filled result because one of the pipes is returned an error for our example
we're going to write a very typical situation in a micro services application an app that performs to
H TTP get calls and joins them in a single response that were printed on the console.
How a small app must perform each request in a different go routine and print results on the console.
If both responses are great if any of them returns an error then we print just the error the design
must be concurrent allowing us to take advantage of our multicore CPM use to make the calls in parallel
in the diagram.
These solid three lines represent calls and the dashed lines represent channels.
The balloons are go routines so we have to go routines launched by the main function which could also
be considered a good routine.
These two functions will communicate back to the main function by using a common channel that they've
received when they were created on the make request calls.
Let's look at the acceptance criteria.
Our main objective in this app is to get a merged response of two different calls so we can describe
our acceptance criteria like this print on the console the merged results of the two calls to the link
shown here.
These are a couple of public endpoints that respond with data from the income and connections.
They're very popular for testing purposes.
You'll need an internet connection to do this exercise.
If any of the calls fails it must not print any result.
Just the error message or error messages if both calls failed the output must be printed as a composed
result when both calls are finished.
It means that we cannot print the result of one call and then the other now will look at unit test integration
to write unit or integration tests for concurrent designs can sometimes be tricky but this won't stop
us from writing our awesome unit tests.
We'll have a single barrier method that accepts a set of end points defined as a string type the barrier
will make a get request to each end point and compose the results before printing out.
In this case we'll write 3 integration tests to simplify our code so we don't need to generate mock
responses.
First we'll create a new document called barrier Dok Go
and another file barrier test.
Don't go now Open the barrier test file and add the lines as shown.
We have a single test that will execute three top tests.
The first test makes two calls to the correct endpoints.
The second test will have an incorrect endpoint so it must return an error.
The last test will return the maximum timeout so that we can force a timeout error.
We'll have a function called barrier that will accept an undetermined number of end points in the form
of strings its signature could be like this as you can see the barrier function doesn't return any value
because its result will be printed on the console.
Previously we've written an implementation of an IO write interface to emulate the writing on the operating
systems esti d out library just to change things a bit will capture the Estes out library instead of
emulating one.
The process to capture the EDL library isn't difficult.
Once you understand concurrency primitives and go so let's add the function
don't feel daunted by this code.
It's really simple.
First we created a pipe.
A pipe allows us to connect and Io write the interface to an IO read interface so that the reader input
is the right output we define the OS store FTD out as the writer then to capture FTD our output will
need a different go routine that listens while we write to the console.
As you know if we write we don't capture and if we capture we're not writing.
The keyword here is while it's a good rule of thumb that if you find this word in some definition you'll
probably need a concurrent structure.
So we used to go keyword to launch a different go routine copiously read input to a bytes buffer before
sending the contents of the buffer through a channel that we should have previously created.
At this point we have a listening go meeting but we haven't printed anything yet so we call our not
yet written function barrier with the provided endpoints.
Next we have to close the writer to signal the go routine that no more input is going to come to it.
Our channel called out blocks execution until some value is received.
The one sent by our launch go reaching the last step is to return the contents captured from the console.
Okay.
So we have a function called Capture Barry output that will capture the outputs in STV out and return
them as a string.
We can write our tests.
Now let's add the tests all the tests are very easy to implement.
All in all it's the capture Barry output function that calls the barrier function.
So we pass the end points in check the returned result our composed results directed to ATP colon for
for Slash H TTP Ben to org must contain the text except dash encoding and user does agent in the responses
of each end point.
If we don't find those texts the tests will fail for further debugging purposes.
We log the response in case we want check it with the minus lowercase v flag on the go test.
Well edit our code further this time we use an incorrect endpoint your.
So the response must return the error prefixed with the word error that will write ourselves in the
barrier function.
The last function we would use a time out of the TTP get client to a minimum of one millisecond.
So we force a timeout.
Let's add to our test further the time out milliseconds variable will be a package variable that will
have to define later during implementation.
Now we'll look at the implementation we needed to define a package variable called time out milliseconds.
Let's start from there.
Open the barrier don't go file and add the code lines as you can see here.
The initial timeout delay is 5 seconds 5000 milliseconds and we'll need these packages in our code.
Okay so we need a function that launches a go routine for each endpoint euro.
You remember how we achieve the communication between routines exactly channels.
So we'll need a channel to handle responses and a channel to handle errors.
But we can simplify a bit more will receive two correct responses to errors or response and an error.
In any case there are always two responses so we can join errors and responses in a merge type at these
lines.
So each go routine will send back a value of the barrier resp type.
This value will have a value for IRR or value for the rest field.
The procedure is simple.
We create a channel of size to the one that received the responses of the barrier resp type.
We launch both requests and wait for two responses and then check to see if there's any error.
Following the previous description we created a buffered channel called in making it the size of the
incoming end points and we deferred channel closing.
Then we launched a function called Make request with each end point and the response channel.
Now we'll loop twice one for each end point in the loop.
We block the execution waiting for data from the end channel.
If we find an error we print it prefixed with the word error as we expect in our tests and set has error
var to true.
After two responses if we don't find any error that is has error equals to false.
We print every response and the channel will be closed.
We still lack the make request function.
Let's add that make request function is a very straightforward function that accepts a channel whose
output Barry arrest values to and a your relative request.
We create an H2 DP dot client and set its time outfield to the value of the time out milliseconds package
variable.
This is how we can change the timeout delay before the end function tests.
Then we simply make the get call.
Take the response pass it to a byte slice and send it through the out channel.
We do all this by filling a variable called rez of the Barry arrest type.
If we find an error while performing a get request or passing the body of the result we fill the rest
or ARRL field send it to the out channel which has the opposite side connected to the original go routine
and exit the function.
So we don't send to values through the out channel by mistake.
Time to run the tests.
Remember that you need an internet connection or the first two Tests will fail.
Well first try the test that has two endpoints that are correct.
Say this file open the terminal and run this command.
Perfect.
We have a Jason respond to the key headers and another Jason response with a key.
User agent in our integration tests we were looking for the strings used thus agent and accept Russian
coding which are present.
So the test has passed successfully now will run the test has an incorrect endpoint for that will run
another command.
We can see that we have had an era where HDP code and forward slash forward slash malformed dash you
or L has returned a no such host error.
Our request to this you URL must return a text with the keyword error prefixed.
As we stated during the acceptance criteria.
That's why this test is correct.
The last test reduced time out to 1 milliseconds.
Well again run the command again the test passed successfully and we've got to timeout errors.
The Urals were correct but we didn't have a response in less than one millisecond.
So the client returned a timeout error that the barrier pattern opens a door of micros services programming
with its composer well nature.
It could be considered a structural pattern.
As you can imagine the barrier pattern is not only useful to make network requests.
We could also use it to split some tasks into multiple go routines.
For example an expensive operation could be split into a few smaller operations distributed in different
go routines to maximize parallelism and achieve better performance.
In this video we understood the barrier pattern successfully in the next video we'll look at the future
design pattern.