views:

60

answers:

4

I have a RESTful web service which I access from the browser using JavaScript. As an example, say that this web service returns a list of all the Message resources assigned to me when I send a GET request to /messages/me. For performance reasons, I'd like to cache this response so that I don't have to re-fetch it every time I visit my Manage Messages web page. The cached response would expire after 5 minutes.

If a Message resource is created "behind my back", say by the system admin, it's possible that I won't know about it for up to 5 minutes, until the cached search response expires and is re-fetched. This is acceptable, because it creates no confusion for me.

However if I create a new Message resource which I know should be part of the search response, it becomes confusing when it doesn't appear on my Manage Messages page immediately. In general, when I knowingly create/delete/update a resource that invalidates a cached search response, I need that cached response to be expired/flushed immediately.

The core problem which I can't figure out:

I see no simple way of connecting the task of creating/deleting/updating a resource with the task of expiring the appropriate cached responses. In this example it seems simple, I could manually expire the cached search response whenever I create/delete/update a(ny) Message resource. But in a more complex system, keeping track of which search responses to expire under what circumstances will get clumsy quickly.

If someone could suggest a simple solution or some clarifying thoughts, I'd appreciate it.

+1  A: 

To quote Phil Karlton: "There are only two hard problems in Computer Science: cache invalidation and naming things."

If you are using a comprehensive data access layer, that would be the place to handle cache invalidation (although it's still not easy). You'd just tie in some cache invalidation logic to your logic for saving a Message so it clears the search cache for the assignee of the message.

Hank Gay
ha, love the quote. those around me know that one of my biggest gripes is naming things. :) and this cache stuff (which i've intentionally avoided for a long time) is rapidly coming in second.
Paul
@Paul If you don't like having a list of different caches that need invalidation in your DAO, you could instead set up some sort of event system. Then you can configure your cache layer to listen for the appropriate event and decide whether to invalidate as necessary. Obviously, this much work isn't really justified for a single cache, but it can pay off if you're caching message info in like 10 different places.
Hank Gay
+2  A: 

The simplest solution would be using a sever-side cache (like EhCache, for example) :) You will have less problems with consistency (as you wouldn't need to push changes to your JavaScript) and expiration.

Vasil Remeniuk
+2  A: 

Use E-Tag and If-None-Match headers to ensure that the client is always accessing the most up-to-date information.

The down-side to this is you will always make a call to the server to find out if anything had changed. The entire message will not be re-transmitted if nothing changed, and the server will/should simply respond back with a 304 Not Modified response in that case. If the content had changed, then the new message(s) will be transmitted as a response.

If the server is responsive (10-50 ms), then most users with a decent latency (50-500ms) should see no noticeable difference.

This increases the load on the server as it will have to verify for each request whether the received E-Tag matches with the current E-Tag for that resource. Clients never assume that a resource is valid/stale/expired, they always ping the server and find out.

Anurag
etags won't save me the trip to the server -- which is what i think i really wanted -- but it's simple and probably not a bad way to go. i'm going to focus on reducing the per-request start-up costs associated with my PHP server (bleh) and maybe that, in combination with etags, will be effective enough.
Paul
We've used E-Tags for various mobile applications, and it works pretty well there, especially when the connection isn't that good. The server has to be highly optimized though like you said. If the entire response is being generated as it would in a regular request, then the benefits go down significantly. Server side caching and cache invalidations work well with E-Tags.
Anurag
+2  A: 

The browser cache should automatically invalidate the cache when you do a POST to the same URI that you did a GET from. See this article, particularly the section on POST invalidation.

Darrel Miller