Client API: How to Setup Aggressive Caching

Standard Cache Configuration

The RavenDB client provides a caching mechanism out of the box. The default caching configuration is to cache all requests.

The size of cache can be configured by changing MaxHttpCacheSize convention.

The client utilizes the notion of the 304 Not Modified server's response and will serve the data from the cache if available.

Aggressive Mode

The aggressive caching feature goes even further. Enabling it means that the client doesn't need to ask the server. It will simply return the response directly from a local cache without any usage of 304 Not Modified status. Results will be returned very fast.

Here's how it works: The client subscribes to server notifications using the Changes API. By taking advantage of them, he is able to invalidate cached documents when they are changed. The client knows when it can serve the response from the cache, and when it has to send the request to get the up-to-date result.

Important

Despite the fact that the aggressive cache uses the notifications to invalidate the cache, it is still possible to get stale data because of the time needed to receive the notification from the server.

Options for aggressive caching can be set in the Document Store conventions:

var documentStore = new DocumentStore
{
    Urls = new[] { "http://localhost:8080" },
    Database = "NorthWind",
    Conventions =
    {
        AggressiveCache =
        {
            Duration = TimeSpan.FromMinutes(5),
            Mode = AggressiveCacheMode.TrackChanges
        }
    }
}

We can activate this mode globally from the store or per session.

To activate this mode globally from the store we just need to add one of the following lines:

documentStore.AggressivelyCacheFor(TimeSpan.FromMinutes(5));

documentStore.AggressivelyCache(); // Defines the cache duration for 1 day

If we want to activate this mode only in the session we need to add this in the session:

using (session.Advanced.DocumentStore.AggressivelyCacheFor(TimeSpan.FromMinutes(5)))
{
    Order user = session.Load<Order>("orders/1");
}

If there is a value in the cache for orders/1 that is at most 5 minutes old and we haven't got any change notification about it, we can directly return it. The same mechanism works on queries as well:

using (session.Advanced.DocumentStore.AggressivelyCacheFor(TimeSpan.FromMinutes(5)))
{
    List<Order> users = session.Query<Order>().ToList();
}

The usage of the notification system means that you can set an aggressive cache duration to a longer period. The document store exposes the method:

using (session.Advanced.DocumentStore.AggressivelyCache())
{ }

which is equivalent to:

using (session.Advanced.DocumentStore.AggressivelyCacheFor(TimeSpan.FromDays(1)))
{ }

Disable Change Tracking

The client subscribes to change notifications from the server using the Changes API. You can choose to ignore these notifications from the server by changing the AggressiveCacheMode in the Document Store conventions.

The modes are:
* AggressiveCacheMode.TrackChanges - The default value. When the server sends a notification that some items (documents or indexes) have changed, those items are invalidated from the cache. The next time these items are loaded they will be retrieved from the server.
* AggressiveCacheMode.DoNotTrackChanges - Notifications from the server will be ignored. For the aggressive cache Duration, results will be retrieved from the cache and may therefore be stale.

documentStore.AggressivelyCacheFor(TimeSpan.FromMinutes(5), AggressiveCacheMode.DoNotTrackChanges);

//Disable change tracking for just one session:
using (session.Advanced.DocumentStore.AggressivelyCacheFor(TimeSpan.FromMinutes(5), 
                                                           AggressiveCacheMode.DoNotTrackChanges))
{ }

Disable Aggressive Mode

We can disable the aggressive mode by simply using documentStore.DisableAggressiveCaching();. In that way we will disable the aggressive caching globally in the store. But what if we need to disable the aggressive caching only for a specific call, or to manually update the cache, just like before we can use DisableAggressiveCaching() per session?

using (session.Advanced.DocumentStore.DisableAggressiveCaching())
{
    Order user = session.Load<Order>("orders/1");
}