rynop's tech blog

rynop's tech blog

rynop  //  I'm a computer nerd and entrepreneur who loves playing sports. Strange mix eh? yea thats me.

Jul 20 / 6:50am

CakePHP Cache::config and the prefix problem

I use memcache heavily when using CakePHP.  I ran into a problem tonight where one of my CakePHP webapps seemed to be using some cache files from another CakePHP webapp on the same server.

The fix was simple - the problem is the example values for Cache::config are a bit misleading. So here is the default config for memcache for CakePHP 1.3

Cache::config('default', array(
  'engine' => 'Memcache', //[required]
  'duration'=> 3600, //[optional]
  'probability'=> 100, //[optional]
   'prefix' => Inflector::slug(APP_DIR) . '_', //[optional]  prefix every cache file with this string
   'servers' => array(
    '127.0.0.1:11211' // localhost, default port 11211
   ), //[optional]
   'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
 ));

You will notice that by default, the prefix of your memcache keys is 'APP_DIR' define. Problem is, in app/webroot/index.php 'APP_DIR' is typically defined as 'app' - and what makes the app unique is really the 'ROOT' in index.php (I always change this value to my application root for performance reasons).

So webapp 1 and webapp 2 were both using keys prefixed by 'app_' - which of course will cause collisions. So the race condition was taking full form here, 1st webapp to load with a empty cache at the given key, got the write.

So the fix is simple, if your 'APP_DIR's are not unique (like mine) then choose something else instead of the APP_DIR.  Any per web app unique string will do - Inflector::slug will make sure its safe for a key.

So here is an example of how mine is implemented:

Cache::config('default', array(
  'engine' => 'Memcache', //[required]
  'duration'=> 3600, //[optional]
  'probability'=> 100, //[optional]
   'prefix' => Inflector::slug('leaguelogix.com') . '_', //[optional]  prefix every cache file with this string
   'servers' => array(
    '127.0.0.1:11211' // localhost, default port 11211
   ), //[optional]
   'compress' => true, // [optional] compress data in Memcache (slower, but uses less memory)
 ));

Hope this helps someone else..