For this example, we are going to look at the situation whereby our Storefront system WizAStore needs to display current stock levels to the user for specific products as they view them.
There are a couple of things to notice about this call:
- Its immediate, the use case (albeit brief) above states that we need to display stock levels as the customer browses the store. This means that when we make the call we expect an answer.
- It is timely, this is slightly different from the above statement but essentially means that the information that is returned is useful only for a very short period of time, if the call takes 5 minutes then the customer has probably moved on and no longer requires the information, and to be honest the actual stock levels may well have changed in that time too so it’s probably of little use relying on that information for a significant amount of time within WizAStore
Other considerations include:
- What happens if the call cannot be made (networks and services can and will fail or be being upgraded, so this will happen – if you don’t believe me look at the uptime for cloud providers who are the people who should be best at this!).
- For this call we will assume that if the call fails then we just show a message stating stock is unavailable.
- And are there any security requirements?
- We will assume no (to keep things simple)
- And what are the non-functional requirements
- How many of these calls are we going to make? (assume we are well within our capabilities)
- How long could we realistically keep (or cache) the information for product stock levels in WizAStore? (assume 0 seconds)
- How much data are we looking to pass and can the connection handle it. (assume we are within our capabilities)
- Can EntMine can cope with the number of requests we are going to be throwing at it from WizAStore without affecting the day to day use internally. (assume yes)
- Do we care that we are exposing a rather large chance of a denial of service attack that could effectively take out our core ERP. (assume no – network security will handle that… yes this is a scary approach!)
So let’s look at the sequence of operations for this call.
Lets just take a minute to look at the diagram and understand what the lines mean here. What we are showing is a blocking synchronous call that means that within WizAStore there is a set of instructions that are being processed, at some point that process will call ‘request stock level’ that will call out to some more instructions in our custom integration layer, which will be worked through until it hits ‘make a network call to get the stock levels’. At this point the call to (in this case) EntMine, and the processing in WizAStore will Stop and wait for a response. There will then be a delay as the request is sent across the network, there will be a delay as EntMine interprets the request, a further delay as the stock levels are queried for, and the associated delays in formatting and returning that information back across the network to WizAStore. Only once WizAStore has received the response will it become unblocked and be able to continue through it’s set of instructions.
You often see this kind of behaviour as a whirling timer on a screen.
The diagram above shows what is called a ‘happy path’ in that we assume all went well, in actual fact anything in this process could fail quickly, and also the network connection could actually pause or hang until it times out causing a long delay to the customer’s experience.
This sounds awful doesn’t it.
Well oddly enough it is the most common way of making calls, and actually is the basis for pretty much all the API’s etc. that are currently live on the internet, anything that is RESTFul and any SOAP over HTML messages or RPC based communications out there.
For the technical bods out there there we know that underlying these lines, a whole raft of communications chatter that allows this conversation to be initiated, new sockets to be created on the server, and the whole thing shut down cleanly. This chatter is the thing that allows you to know that the whole sequence has been competed and that each end did or did not fail before the operation completed, but for now we can assume (safely) that if no errors are returned then everything worked fine.
This style of communication is ideally suited to operations that offer a quick response. If the process that discovers stock levels takes 3 minutes or more then on most protocols (HTTP for example) you start to run in to real problems, things like network switches, browsers and servers closing your connections on you to control bandwidth and resource usage, and not only that your user is sat there patiently looking at a timer for the full duration.
One common solution to the issue of these calls taking a long period of time is to use a programming language technique called multi-threading to essentially make the call using a different thread – essentially creating a new program in the background to make the call, block and deal with the response when it arrives, this changes the sequence diagram to:
Note that the major change here is that the call to the custom integration layer returns immediately with an Ack (or acknowledgement) to basically say ‘Ok I’m on it’. It’s the custom layer that then makes the network call and blocks whilst the main program is freed up to continue working with the user. At some point the custom integration later will receive the response back from the network and be able to pass that information back to the main program in some way (either by some kind of callback mechanism or by, say, updating a field on the user interface).
This kind of behaviour is often seen by the user when they are working with an interface and fields seem to be updated in the background with a slight delay, usually with address look ups and data refreshes on websites.
This pattern works well for user interfaces and network calls with delays that are perceptible to the user but are not so long as to cause a user to have to wait too long. Typically we are talking up to about 3-5 seconds is probably as far as you want to take this pattern, any more than that and the user will be wanting to move on to the next job.
The other thing to realise is that this pattern is still making a synchronous API call, that is there is a process in the caller that is being blocked until the value is returned. This is not an asynchronous API but an example of a synchronous API being called asynchronously.