Developers > Kernel Documentation > Fundamentals > Cache.pm

Cache.pm


ExSite::Cache

ExSite::Cache is a generic cache tool for saving re-useable data.

The cache is an in-memory hash of arbitrary data values. The data can be indexed based on an arbitrary amount of indexing data, so that the cache can store completely unrelated data with low risk of collision.

The primary use in ExSite is to remember results of database queries, so that we don't need to make a DB server call to re-fetch something we've already fetched (but forgotten).

For instance, if you've fetched data record #123 from table XYZ, you could save it in cache this way:

    my $cache = new ExSite::Cache;
    $cache->save($data,"XYZ","123");

The first value is the data to save; the remaining values (there can be any number) are used to uniquely index the data. In this case, the table name and record number are sufficient to uniquely specify this piece of data.

If later someone asks for the same data, eg:

    $db->fetch("XYZ",123);

then you could first check the cache for a value before querying the the database:

    $data = $cache->get("XYZ",123);

    if (! $data) { # go to database...

In practice, all of the above is done automatically by the ExSite::DB class.

Cache Persistence

There are actually two caches that mirror each other, the soft cache (which is the one that is used directly), and the hard cache (which is where cache data is stored for persistence). The soft cache is used automatically; the hard cache is only effective if the persistent data store (see ExSite::Store) is enabled. If the persistent data store is enabled, then the soft cache will initialize itself using the hard cache. Otherwise the soft cache will be empty at the start of each request, and cached items will not be remembered by subsequent requests.

Without the hard cache, cached items persist for the lifetime of the current request only.

If the hard cache is enabled, cached items persist for the default lifetime of items in the persistent data store. This is 1 hour in the default configuration.

If the hard cache is enabled, but you do not want your cached items to persist, then you must set the following configuration setting:

    cache.persistent = 0

Invalidating Cached Items

Items in the cache are mirrors of original source items stored in a slower data storage medium, such as a SQL database. If the original source changes, then the cached copies of those items are invalid and should be cleared from the cache.

In practice, it is not feasible to know if any particular item has been invalidated by any particular SQL query. Instead we use a more general rule, in which cached items are indexed under their table names. Any write operation that hits any of those tables will invalidate cached items from those tables. This is effected using primary cache keys, below.

Cache Keys

You can provide any number of key values to index the data in the cache. These are combined together to give the aggregate hash key which is used to look up the data in future.

It is a good idea to append a unique ID for the database to the cache keys, as this will keep cache entries from multiple database handles separated in the cache. Otherwise, you would have troubles connecting to two ExSite databases simultaneously, since you could easily have similar records in both (especially if one was a backup or archive of the other).

Primary Cache Keys

The first of the key values provided is the primary key, which has a special use. All cache items that share a primary key are remembered, and those cache items can be cleared at a stroke, using:

    $cache->clear("XYZ");

Example: The purpose of this is to allow you to cache the results of numerous queries, eg:

    select * from page where page_id=99
    select * from page where section_id=4 & type="template"

These 2 queries would result in at least 2 separate entries in the cache, potentially with overlapping results. If the primary key for both of these cache entries was ``page'', then the keys for these cache entries would be saved in the key index under ``page''. At some later time, if we updated some records in the page table, we might not know if any of the data in the cache has now been superceded. The safe thing to do is expire all page entries in the cache:

    $cache->clear("page");

If you perform more complex queries involving joins of multiple tables, eg.

    select content_id,name from page,content where page.type="template" & content.page_id=page.page_id

Then you can index these under a compound primary key, by using an array reference for your primary key, eg.

    $cache->save($data,["page","content"],...);

Then a request to clear either ``page'' OR ``content'' would clear that cache entry.

If you do not want your cache data to be cleared based on its cache primary key, then use undef as the primary key when saving, eg.

    $cache->save($data,undef,...);

You can also remove a single cache entry as follows:

    # remove it using original indexing data
    $cache->delete("XYZ",123);

    # remove it using cache key
    $cache->clear_key($key);

Topics