Cache duration and configuration tips

320gb-werstern-digital-hard-drive-7200-rpm-cache-8mb-hd-w3200jbAs you know you can cache several elements in you application. When I wrote a value to the cache I did it by setting the duration in the third parameter of write:

Cache::write('cache_key', 'value to cache',array(
    'config'=>'default',
    'duration'=>'+1 day')
);

But today I learned a lesson from Mark Story that this was a bug and it is fixed and doens’t work anymore. It is ignored.

So how do I set the duration before read/write for specific data in my code?

First of all you have to set the Cache engine in APP/config/core.php to the engine you want to use. I mostly use the File engine:

Cache::config('default', array(
    'engine' => 'File',
    'duration'=> '+2 hours',
    'probability'=> 100,
    'path' => CACHE,
    'prefix' => 'cake_',
    'lock' => false,
    'serialize' => true)
);

Then use Cache::set() to set the duration before every read/write action

Cache::set(array('duration' => '+1 day'));
if (!$cachedata = Cache::read(('cache_key','default')) {
    // retrieve data if cache is empty
    $data = $this->Model->read(null, $id);
    Cache::set(array('duration' => '+1 day'));
    Cache::write('cache_key', $data, 'default');
}

So you have to set the duration before read AND write. Not very DRY and short code IMHO.

Then Mark Story told his secret how he uses cache durations etc. It was a nice one. Just define a couple of cache configurations and set the duration you need for every configuration. Most of the time I need three: 2 hours, 1 day and 1 week. So here it is:

// File engine caching
// short
Cache::config('short', array(
    'engine' => 'File',
    'duration'=> '+2 hours',
    'probability'=> 100,
    'path' => CACHE,
    'prefix' => 'cake_',
    'lock' => false,
    'serialize' => true)
);
// medium
Cache::config('medium', array(
    'engine' => 'File',
    'duration'=> '+1 day',
    'probability'=> 100,
    'path' => CACHE,
    'prefix' => 'cake_',
    'lock' => false,
    'serialize' => true)
);
// long
Cache::config('long', array(
    'engine' => 'File',
    'duration'=> '+1 week',
    'probability'=> 100,
    'path' => CACHE,
    'prefix' => 'cake_',
    'lock' => false,
    'serialize' => true)
);
// default = medium
Cache::config('default', Cache::settings('medium'));

And then you can just use the config name to set the duration:

if (!$cachedata = Cache::read(('cache_key','short')) {
    // retrieve data if cache is empty
    $data = $this->Model->read(null, $id);
    Cache::write('cache_key', $data, 'short');
}

How genius is that! :) And if you want to change the duration you just change it in the core.php Cache::config or add another one with different duration.

Thanks a lot to Phally and Mark Story!

16 Responses to “Cache duration and configuration tips”

  1. CakePHP : signets remarquables du 18/03/2009 au 19/03/2009 | Cherry on the... Says:

    [...] Cache duration and configuration tips [...]

  2. Taras Kozlov Says:

    I’m trying to achieve the same functionality with multiple file cache storages different by the duration. And I found interesting thing in the \cake\libs\cache.php (CakePHP 1.2.2.8120) in the Cache::read method

    $success = $_this->_Engine[$engine]->read($settings['prefix'] . $key);

    It looks for me that it uses engine only to check the data and doesn’t take into account actual storage.

    Next, let’s take a look at at \cake\libs\cache\file.php, FileEngine::read method, there is a line there:

    if ($cachetime !== false && ($cachetime settings['duration']) < $cachetime))

    I’m thinking about the part of the code after || sign and can’t find an explanation for it.

    But because of this part if you will try to reverse cache storage definition (long, medium, short), you will find the problem I did – cache doesn’t work. I.e. cached data is treated as invalid.

    E.g. we have “+1 month” and “+1 day” storages, first storage has got file that was cached until 2009-05-01 15:29:44 ($cachetime), and today is 2009-03-31 15:37:31 ($time) when it’s time to check the data for validness, it’s calculated:
    - $cachetime !== false is true and OK
    - $cachetime settings['duration']) < $cachetime) becomes 2009-03-31 15:37:31 + 86400 < 2009-05-01 15:29:44 and it’s true. So, the entire expression is true and file goes to dev/null

    On the other hand I’m new to CakePHP and probably I’ve just missed something and I would appreciate any help here.

  3. Taras Kozlov Says:

    It’s stripped tags in last line of code, so you can take a look at line #169 (the next after $cachetime = intval($this->__File->read(11)); one)

  4. primeminister Says:

    Hi Taras: best way to find out is entering the IRC channel #cakephp on freenode. A lot of people there that can help you more quickly then I can now..

  5. Taras Kozlov Says:

    Thank you for the hint, I’ll definitely find the answer somewhere. But I just want to mention again, that multiple file cache storages must be defined in the way you shown in your post – in ascending order by duration, otherwise it won’t work.

  6. primeminister Says:

    @Taras: You read and write and set the cache config explicitly. SO how come that the order of the configs in core.php will be of any influence?

  7. Taras Kozlov Says:

    When Cache::read calls FileEngine::read actual storage’s settings aren’t passed there (I understand that I probably missed something), but when I added a dump to the FileEngine::read method to show me the actual settings it’s shown data the was defined in the _last_ file storage defined in core.php

    So, when it evaluates line #169 (that I explained above) it uses incorrect values.

  8. primeminister Says:

    Interesting Taras… I will dive into that myself. If this is true, it is a bug.

  9. primeminister Says:

    Taras: you were right. I made a ticket with a testcase patch: https://trac.cakephp.org/ticket/6262

  10. Taras Kozlov Says:

    Charlie,

    Thank you for your help in clarifying the issue.

  11. primeminister Says:

    @Taras: Sorry, my bad. It is working perfectly. I used it wrong. If you use the config name for every read and write action it is wroking fine.
    If you are not sure, make a testcase (or change my patch at https://trac.cakephp.org/ticket/6262 )

  12. Taras Kozlov Says:

    Charlie,

    You probably won’t believe in this, but according to my tests – cache works fine when defined right in the action, but doesn’t work when defined in the core.php. Moreover, even if you initialize another storage engine right in the action – other ones will work fine.

    Btw, I used storage names in the read/write from the beginning.

  13. primeminister Says:

    File a ticket on trac.cakephp.org. Reference to my ticket and specify this. They will help you

  14. Taras Kozlov Says:

    Charlie,

    Thank you again for your help. And you are right that we probably need to finish the conversation here.

  15. morris Says:

    I came across the same “problem”. I don’t know if it is really a problem but it IS making most of my cache writes register as expired.. and it makes using Cache a bit more of a headache.

    Seems to be that when you READ a cache file it will check against two values to see if should be expired. First it will compare to the defined expiration… if you set one, ie:

    Cache::write(‘filename’, ‘data’, ‘+1 day’);

    Then it ALSO checks against the DEFAULT expiration duration + current time. It is 3600 (1 hour) by default.

    Strange thing (to me) is that it is checking if cachetime (+1 day) is greater than time + duration (current time + 3600). If it is.. it is considered expired. So, if I write a cache that expires in +1 day.. and try to read that cache within 23 hours, it will be considered expired.

    I’m still trying to wrap my head around this but so far a workaround seems to be if you set the default duration for your cache config to something longer than you typically use in your app.. like +1 month. Then, as long as you aren’t caching anything longer than that, it will work as it had previously (and you can just write in the duration as your third param in Cache::write)

  16. paremuya Says:

    new tips for php I found….I try to learn it thanks

Leave a Reply