My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Cache  
How to use cache with SimpleDS
Updated Mar 27, 2012

Introduction

SimpleDS includes a Level 1 and Level 2 cache that will be used for classes annotated with @Cacheable.

When retrieving cacheable classes:

  • Check the Level 1 cache.
  • If no match is found, check the Level 2 cache.
  • If none matches, the datastore will be queried and the retrieved data will be published on both caches.

The cache will work with any single or batch get(), cleared with delete() and updated with put().

/**
 * Cacheable up to 1200 seconds
 */
@Cacheable(1200)
public class MyData {
}
// Invoke memcache or the datastore
List<MyData> data = entityManager.get(key1, key2, key3);

// this does not invoke anything (resolved by the Level 1 cache)
MyData d = entityManager.get(key1);

// Secondary effect: remove the affected instances from both caches
entityManager.delete(key2, key3);

// Secondary effect: update the cache entry
entityManager.put(d);

Level 1 cache

This is basically a Map bound to the current thread, and is not shared with other requests. Until the end of the current request, any get() invocation will check this cache first. If a match is found, no invocation will be propagated to GAE.

This is the best cache hit possible, since there is no unmarshalling involved and no invocation to GAE (thus, no quota consumption). The contents of this cache are java objects.

To enable the Level 1 cache you must add a filter in your web.xml:

 <filter>
	<filter-name>simpleds-cache</filter-name>
	<filter-class>org.simpleds.cache.CacheFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>simpleds-cache</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

This filter is not required, but Level 1 caching will be disabled if it is not found.

Level 2 cache

This is a shared cache backed up by memcache, and its contents are serialized Datastore entities. Any cache hit will be unmarshalled from Entity back into Java object and stored in the Level 1 cache. The cache timeout is specified using @Cache (in seconds) and if not specified Level 2 will be disabled for that bean.

/**
 * Cacheable in Level 1 but not in Level 2
 */
@Cacheable
public class Level1CacheableClass {
}

Cached queries

Starting with 1.0, all query results can be cached. To maximize cache performance only the returned primary keys will be cached, so you still have to use @Cacheable to cache the entity itself.

For example, to retrieve a User given the email:

User user = entityManager.createQuery(User.class)
		.equal("email", googleUser.getEmail())
		.withCacheSeconds(3600)
		.asSingleResult()
		;
DEBUG CacheManagerImpl - Level 2 cache hit: qdata{kind=User,pred=[email = test@example.com]}
DEBUG CacheManagerImpl - Level 2 cache hit: User(5)
DEBUG Level1Cache - Level 1 cache hit: User(5)

Cached queries work with FetchOptions (cursors, limit and offset) and support only count(), asSingleEntity(), asList() and asPagedList(). Any invocation to asIterable() / asIterator() will ignore the cache.

To remove the cached data, just prepare the same query and invoke clearCache():

entityManager.createQuery(User.class)
	.equal("email", googleUser.getEmail())
	.clearCache()
	;

Queries will ignore the cache and go directly to the datastore if a transaction is set, but they will store the return value in the cache before exiting.


Sign in to add a comment
Powered by Google Project Hosting