After doing my homework, I found the necessary Drupal functions in cache_get() and cache_set().
Additionally, I found a good warning in this Civic Actions blog post (Drupal Gotchya: Cache_get() Returns Expired Items) about Drupal relying on cron to determine whether a cache has expired.
The best way to handle caching the way you want is to write some custom wrapper functions. This will give you the ability to deal with edge cases as you need. Here are my custom cache_get and cache_set functions.
/*
* Wrapper for cache getting
* @param: key - an arbitrary name given to the cached data
* @return: the cached data
*/
function mymodule_get_cache($key = 'asheville')
{
// get cache
$cache = cache_get('mymodule:'.$key);
// if no cache or expired, reset it
if (!$cache || (time() > $cache->expire))
{
// reset cache using our cache_set wrapper function
$data = mymodule_set_cache($key);
// for testing purposes, let's output some information for the admin
$admin_message = "The cache was just rebuilt";
}
else
{
$data = $cache->data;
// I'm a big fan of letting the admin know what's going on
$admin_message = "This cache expires on ".date("l, M d Y - g:i.s A ",$cache->expire);
}
// show admin the cache time
global $user;
if ($user->uid == 1) {
$data .= "<div style='clear:both;float:none;'>".$admin_message."</div>";
}
return $data;
}
/*
* Wrapper for cache setting
* My needs are that the cached page updates it self every 30 minutes. This is reflected below.
* @param: key - an arbitrary name given to the cached data
* @return: the data that was cached
*/
function mymodule_set_cache($key = 'asheville')
{
// get the data however you want, here I have a custom theme function returning the data
$data = theme('mymodule', mymodule_get_data());
// get expire time
$sql = "SELECT expire FROM {cache} WHERE `cid` = '%s' LIMIT 1";
$last_expire = db_result(db_query($sql, 'mymodule:'.$key));
// in case of trouble
if ($last_expire == 0)
{
$now = time();
// previous 30 minutes;
$last_expire = $now - ($now % (60*30));
}
// add 30 mins to the expire time
$expire = strtotime('+30 minutes', $last_expire);
// adjust for next day
if (date('g:iA',$last_expire) == '11:30PM')
{
$expire += (60*60*24);
}
// set the new cache
cache_set('mymodule:'.$key, $data, 'cache', $expire);
// add a notice to the watchdog for reference
watchdog('mymodule_cache', 'MyModule Cache: New cache was set and expires at %date', array('%date' => date("l, M d Y - g:i.s A", $expire)), WATCHDOG_NOTICE);
return $data;
}
Discussion