Command Caching - HomeAdvisor/Robusto GitHub Wiki

Command Caching

The API Client Framework offers a pluggable command caching mechanism, letting you cache the results of remote service calls to avoid future requests for the same data. This is different from Hystrix request caching, which de-duplicates commands prior to execution. Command caching in the API Client Framework pertains to responses from remote services.

CommandCache

This is the main mechanism you use if you wish to perform command caching. When building your ApiCommands, the builder takes an optional reference to CommandCache and key. When these are present, the ApiCommand.run() method does two additional steps:

  1. Prior to executing UriProvider.execute(), it looks for the provided key in the provided CommandCache. If the cache returns a result, that result is passed back to the client without ever invoking the UriProvider or RemoteServiceCallback.
  2. After the remote service call returns a value, it puts the result into the provided CommandCache using the provided key.

The following chart summarizes the execution flow with command caching:

API Client Framework Overview with Command Caching

CommandCacheFactory

This is an interface for specifying how to build a command cache. It has a single method you need to implement:

public interface CommandCacheFactory<T extends CommandCache>
{
    T create(String name, Map<String, Object> config);
}

Your implementation should return an instance of your specific CommandCache. The config map that is passed in is a simple key/value map pulled from the configuration object.

Manipulating Cache Behavior

The CommandCache object provides two ways to override caching behavior:

  1. The CacheGetHandler interface provides a way to intercept cache hits, allowing you to examine the cached data and either modify it or reject it entirely before returning to client.
  2. The CachePutHandler interface provides a way to intercept cache puts, allowing you to examine the remote service result prior to placing into the cache, and either modify it or skip caching entirely.

Providing Different Cache Mechanisms

The core framework comes with a very simple HashMap based caching mechanism. This is really meant to be a reference implementation of CommandCache and should be avoided for 2 reasons:

  1. There is no direct way to set size limits on number of entries.
  2. There is no way to set timeouts on cache entries.

Both of these can cause the CommandCache to grow in size unbounded.

Providing your own caching mechanism is fairly easy, just extend CommandCache and provide implementations for doGetCache and doPutCache that call into your underlying cache mechanism.

HomeAdvisor also provides two implementations that you may find useful.

Guava Cache

The robusto-guava library adds an extension of CommandCache that uses a GuavaCache as the backing mechanism. This is suitable for most use cases and allows you to configure both cache size and expiration to avoid growing the cache too large.

Coherence Cache

At HomeAdvisor, we use Oracle's distributed caching product Coherence to store data and avoid database calls. In some cases, it's useful for our clients to tap directly into these caches instead of making a remote service call, so we also provide the robusto-coherence library to facilitate using Coherence caches.