Rewriting the stock market application with core.async
By using an example we are familiar with, we are able to focus on the differences between all of the approaches we have discussed so far, without getting sidetracked with new, specific domain rules.
Before we dive into the implementation, let's quickly get an overview of how our solution should work.
Just as in our previous implementations, we have a service from which we can query share prices. Where our approach differs, however, is a direct consequence of how core.async channels work.
On a given schedule, we would like to write the current price to a core.async channel. This might appear as follows:
This process will continuously put prices in the out channel. We need to do two things with each price: display it and display the calculated sliding window. Since we like our functions to be decoupled, we will use two go blocks—one for each task:
Hold on. There seems to be something off with our approach. Once we take a price from the output channel, it is not available to be taken by other go blocks any longer. So, instead of calculating the sliding window starting with 10, our function ends up getting the second value, 20. With this approach, we will end up with a sliding window that calculates a sliding window with roughly every other item, depending on how consistent the interleaving between the go blocks is.
Clearly, this is not what we want, but it helps us think about the problem a little more. The semantics of core.async prevent us from reading a value from a channel more than once. Most of the time, this behavior is just fine, especially if you think of them as queues. So, how can we provide the same value to both functions?
To solve this problem, we will take advantage of another channel constructor provided by core.async, called broadcast. As the name implies, broadcast returns a channel, which, when written to, writes its value into the channels passed to it as arguments. Effectively, this changes our high-level picture to something like the following:
In summary, we will have a go loop writing prices to this broadcast channel, which will then forward its values to the two channels from which we will be operating: prices and the sliding window.
With this general idea in place, we are ready to dive into the code.