It is easy to forecast how many widgets you can ship when you are creating them in the factory behind your office. It is another story when those widgets are being created in another factory that you do not own. You are now a customer of your distributor, but as a market economy would dictate, your customer’s do not care where the product comes from. They just want to know if you have it in stock, and if you do not, they would like to know how soon you will have it. Any company that ships a product that they do not produce themselves runs into this problem consistently, and often enough you will need to connect you systems to your distributors to get a virtual inventory to keep your customer happy.
The Problem of Real-Time Inventory
Let us call our fictitious company Alpha Parts. They sell computer paraphernali, thousands of items like printers and mice and laptops, and procure their inventory from the following five warehouses: MicroBell, JME, DataTech, Xenns and LargeDeutsche.
Now, as simple as this model seems from a business perspective (maybe it is more complicated than I think) it poses a very interesting technical challenge in order to display product availability on the Alpha Parts website of items that have not physically entered their inventory. How do we know how many Cannon X15 printers MicroBell has? Or the amount of Microsoft Explorer mice that is in the Xenns warehouse?
Alpha Parts could request daily files of inventory availability from their partners, but that data could become stale in minutes. It turns out that each of these partner warehouses has XML web services that can be called individually via HTTP. Now, Alpha Parts need has an interface into individual product inventory per warehouse, but needs to turn that data into a usable system that aggregates and gives meaning to these numbers to their customers.
And here lies the problem: Real time on the web. We have the following challenges: multiple long running real time method calls to a third-party service over the internet, displaying results that return at different times and handling unresponsive services.
One of the lead engineers at Alpha Parts proposes solving these challenges by using the Service Gateway pattern in the middle tier and an ASP.NET compatible Ajax component on the front end. Let us take a look at the Service Gateway.
The Service Gateway pattern is a repeatable design that “encapsulates the details of connecting to the source and performing any necessary translation.” Here is a logical overview of the pattern.
The web application sends its request to the Gateway. The Gateway is then responsible for translating the request into the proper format to send to the External Service. After the response comes back from the external service it is returned to the gateway where it is then translated back into a representation that the application understands. It is also at this point where the gateway can use the persistence layer for storage or retrieval of data.
The next figure is a UML breakdown of the gateway layer.
Gateway – responsible for providing coordination and translation for calling the external service
PartnerInventory – object that describes products availability at a particular vendor
PartnerInventoryCollection – object representing a collection of PartnerInventory objects
RealTimeInventoryAccess – this is an existing class that handles the actual post to the services
GatewayPersistence – responsible for persisting and retrieving data from cache or the database – this could also be used to perform an algorithm to decide what stock results are active enough to stay in memory cache and which should persist to the database
GatewayDataAccess – responsible for physically persisting and retrieving data to the database
The pattern is straightforward enough and only really gets complicated depending on the extent of logic that is desired in the persistence layer.
Each time a method is invoked from the Gateway to RealTimeInventoryAccess (and hence, the external service itself) it will be done with an asynchronous method. The following figure shows the idea behind this, not the exact code.
ThirdPartyInventoryDelegate third = new ThirdPartyInventoryDelegate(RealTimeInventoryAccess.GetInventoryByVendorsAndItemsCode); IAsynchResult synchResult = third.Invoke(parameter, new AsychCallback(method), third); synchResult.AsynchWaitHandle.WaitOne(time, true);
The Alpha Parts engineers want to ensure that the web application continues processing while the web services are being called; so they propose calling each web service asynchronously in order to return information to the Gateway object as the services returns. This way they can be run through the persistence layer sooner. Each asynchronous method call is also done with a timeout value in order to prevent the HTTP post from waiting on the default timeout which could be too long (notice the WaitOne in the above listing). This will also enforce our own time limits for those remote method calls.
Being as such, if a method was called at 8:00:01 AM and method two was invoked right after that, if the first service call took longer to return, the second call could already be done processing the service XML and have handed the data back to the Gateway for the persistence layer. It basically allows the multiple calls to return on their own time and not queue up behind each other so that there are not wasted cycles.
The Ajax capable front end is another key facet to this design coming to life.
When a product page loads on the Alpha Parts website, the full page will load except for the real time html region. The CallBack component will call the page class which will check with the Gateway and its persistence engine to see if there is current inventory information available. If it is available, those objects are returned to the page and bound to the CallBack control. If they are not available from persistence, they are sent out to the external service(s) and the CallBack control will display a “loading” icon. The user is then free to use the rest of the page and as soon as the Service Gateway is done with its work its return objects will be bound to the CallBack control.
In this way, the middle tier will be working asynchronously to retrieve inventory information from multiple services and the web application will work asynchronously to display the data it will have to occasionally wait for.
Jim Tyhurst, Services That Reach from the Inside Out. Dr Dobbs Architecture and Design World 2006