Integrating Capifast to Episerver CMS
Vitec Capifast CRM is the most established CRM system for property owners in Sweden. Having built more than one Episerver CMS based website for real estate companies, Ted & Gustaf has extensive experience integrating external data into Episerver.
We will look at how we use the collection of APIs Capifast offers, to combine a polling method for full synchronization of properties, with the implementation of Capifast push notification system to minimize latency.
The entire integration and surrounding environment is huge and therefore out of scope for this article. Instead we will focus around some smart constructs to solve common issues integrating with any external data provider.
Getting the data without latency
One challenge you will be faced with when building a real estate website is that it is crucial to reduce latency. The person editing a property description, its images or information about rent in Capifast, expects the changes to take effect in Episerver immediately.
Capifast basically have 2 main integration points:
- A Web Service API with listings and property information.
- A push notification system that makes an HTTP request to the consumer, letting it know that some properties and premises have been changed. It is not actually pushing the data, only notifying a change.
The idea is to use the Web Service API when we need to get data for a property. To detect and refresh updated properties would require us to poll frequently, even if we poll every 5 minutes, it would mean the data could be more than 5 minutes old.
We use these integration points to:
- Schedule jobs which makes a full synchronization of the data in Capifast with Episerver. This is very time consuming and is normally not used. It is there to pick up changes if the server has been down or there has been issues with the push notification system in Capifast.
- Have an HTTP endpoint listen for push messages and call the Capifast Web service only for those properties and premises that have been modified.
Queueing code to execute in background thread
Capifast requires the endpoint that receives the push message to return a response without any delay whatsoever. The expected response should be a swift "OK".
This is what the action method in the receiving controller looks like:
public ActionResult Index(string userId, string dataSource)
{
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(dataSource))
{
return Content("FAIL", "text/plain");
}
ServiceLocator.Current.GetInstance<IActionWorker>().Enqueue(() => Update(customerNumber, dataSource));
return Content("OK", "text/plain");
}
As you can see, it passes an Action to the IActionWorker service. Basically it spawns a thread and starts a loop which wait for code to execute.
public class ActionWorker : IActionWorker
{
private readonly BlockingCollection<Action> _queue = new BlockingCollection<Action>();
public ActionWorker()
{
var thread = new Thread(() =>
{
while (true)
{
var action = _queue.Take();
action();
}
})
{
IsBackground = true
};
thread.Start();
}
public void Enqueue(Action action)
{
_queue.Add(action);
}
}
There are a few interesting constructs in use here. The BlockingCollection blocks the Take() call until there is something there. It expects the collection to contain Actions. That means you can add code to be executed, one after the other.
Conclusively
While there is a lot more to say about integration patterns and antipatterns, the key take-away points from this article should be;
- To use background threads where appropriate to avoid blocking and to reduce latency
- Decouple the separate systems by using a combination of polling and pushing
- Always think about performance!