From b3d47ed6cc3245ddf2f54343b4783fde05708c00 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 6 Dec 2010 17:05:32 -0500 Subject: Make code-dependent cache entries more volatile If a cache entry is dependent on the code that's running, upgrading (or enabling/disabling plugins) can generate hard-to-track inconsistencies. This change adds a close-to-unique fingerprint of the running code to some cache keys, so that if the fingerprint changes, the old values are ignored and new values are used. If the automated uniqueness fails, an administrator can add an extra config value, $config['site']['build'], that's thrown into the key also. --- lib/cache.php | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/default.php | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/cache.php b/lib/cache.php index ea0ff769d..dc667654a 100644 --- a/lib/cache.php +++ b/lib/cache.php @@ -86,6 +86,55 @@ class Cache return 'statusnet:' . $base_key . ':' . $extra; } + /** + * Create a cache key for data dependent on code + * + * For cache elements that are dependent on changes in code, this creates + * a more-or-less fingerprint of the current running code and adds it to + * the cache key. In the case of an upgrade of core, or addition or + * removal of plugins, a new unique fingerprint is generated and used. + * + * There can still be problems with a) differences in versions of the + * plugins and b) people running code between official versions. This is + * usually a problem only for experienced users like developers, who know + * how to clear their cache. + * + * For sites that run code between versions (like the status.net cloud), + * there's an additional build number configuration setting. + * + * @param string $extra the real part of the key + * + * @return string full key + */ + + static function codeKey($extra) + { + static $prefix = null; + + if (empty($prefix)) { + + $plugins = StatusNet::getActivePlugins(); + $names = array(); + + foreach ($plugins as $plugin) { + $names[] = $plugin[0]; + } + + $names = array_unique($names); + asort($names); + + // Unique enough. + + $uniq = crc32(implode(',', $names)); + + $build = common_config('site', 'build'); + + $prefix = STATUSNET_VERSION.':'.$build.':'.$uniq; + } + + return Cache::key($prefix.':'.$extra); + } + /** * Make a string suitable for use as a key * diff --git a/lib/default.php b/lib/default.php index a91fa338f..7388046d3 100644 --- a/lib/default.php +++ b/lib/default.php @@ -59,7 +59,8 @@ $default = 'textlimit' => 140, 'indent' => true, 'use_x_sendfile' => false, - 'notice' => null // site wide notice text + 'notice' => null, // site wide notice text + 'build' => 1, // build number, for code-dependent cache ), 'db' => array('database' => 'YOU HAVE TO SET THIS IN config.php', -- cgit v1.2.3-54-g00ecf From 8c4e14b59c649ff38159793a1e30229bcc4bf4d6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 6 Dec 2010 17:08:52 -0500 Subject: use Cache::codeKey() in Router class --- lib/router.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/router.php b/lib/router.php index 8670519ff..4b1fdeb92 100644 --- a/lib/router.php +++ b/lib/router.php @@ -156,21 +156,7 @@ class Router static function cacheKey() { - $plugins = StatusNet::getActivePlugins(); - $names = array(); - - foreach ($plugins as $plugin) { - $names[] = $plugin[0]; - } - - $names = array_unique($names); - asort($names); - - // Unique enough. - - $uniq = crc32(implode(',', $names)); - - return Cache::key('router:'.STATUSNET_VERSION.':'.$uniq); + return Cache::codeKey('router'); } function initialize() -- cgit v1.2.3-54-g00ecf From bb63fd4b75181e1e9429d3a62377dab72a5c0990 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 6 Dec 2010 17:19:41 -0500 Subject: Config flag to disable router caching if needed --- README | 12 ++++++++++++ lib/default.php | 2 ++ lib/router.php | 20 ++++++++++++-------- 3 files changed, 26 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/README b/README index 6343e3e02..3bebb11ee 100644 --- a/README +++ b/README @@ -1538,6 +1538,18 @@ external: external links in notices. One of three values: 'sometimes', nofollowed on profile, notice, and favorites page. Default is 'sometimes'. +router +------ + +We use a router class for mapping URLs to code. This section controls +how that router works. + +cache: whether to cache the router in memcache (or another caching + mechanism). Defaults to true, but may be set to false for + developers (who might be actively adding pages, so won't want the + router cached) or others who see strange behavior. You're unlikely + to need this unless you're a developer. + Plugins ======= diff --git a/lib/default.php b/lib/default.php index 7388046d3..029dbb390 100644 --- a/lib/default.php +++ b/lib/default.php @@ -328,4 +328,6 @@ $default = array('ssl_cafile' => false, // To enable SSL cert validation, point to a CA bundle (eg '/usr/lib/ssl/certs/ca-certificates.crt') 'curl' => false, // Use CURL backend for HTTP fetches if available. (If not, PHP's socket streams will be used.) ), + 'router' => + array('cache' => true), // whether to cache the router object. Defaults to true, turn off for devel ); diff --git a/lib/router.php b/lib/router.php index 4b1fdeb92..eff88bb46 100644 --- a/lib/router.php +++ b/lib/router.php @@ -127,15 +127,19 @@ class Router function __construct() { if (empty($this->m)) { - $k = self::cacheKey(); - $c = Cache::instance(); - $m = $c->get($k); - if (!empty($m)) { - $this->m = $m; - } else { + if (!common_config('router', 'cache')) { $this->m = $this->initialize(); - $c->set($k, $this->m); - } + } else { + $k = self::cacheKey(); + $c = Cache::instance(); + $m = $c->get($k); + if (!empty($m)) { + $this->m = $m; + } else { + $this->m = $this->initialize(); + $c->set($k, $this->m); + } + } } } -- cgit v1.2.3-54-g00ecf