Skip to content

Commit

Permalink
Configurable cache invalidation odds
Browse files Browse the repository at this point in the history
This commits adds a new hidden configuration value, `cache_invalidation_odds`
which allows developer to control how often cache is validated.

This is particularly usefull on stressed servers, and even better if
serving remote images, since it can lead to a 60% request time
diminution.

The default behaviour is not changed and cache validation will always
occur.

It also updates the x-jit debug header to specify the result of the
cache validation

Fixes symphonycms#138
  • Loading branch information
nitriques committed Aug 2, 2016
1 parent fdf9880 commit 091a58a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
12 changes: 12 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ A complete listing of the possible config settings:
'allow_origin' => '', // string (editable)
'max_age' => 259200, // integer (hidden)
'memory_exhaustion_factor' => '' // string/float/int (hidden)
'cache_invalidation_odds' => '' // string/float (hidden)
),
```

Expand Down Expand Up @@ -72,6 +73,17 @@ Recommended settings would be between 1.7 and 2.1.
Setting the value to 0, '' or null will disable the feature.
Default value is null (disabled).

### cache_invalidation_odds

Setting this value will make the cache invalidation checks more or less frequent.
If you care more about performance than serving a validated cache file, you can control the odds of doing a cache invalidation check.
We will generate a random number between 0 and 1 and compare it against your odds value.
By setting it to 0.1, the cache should only be validated 10% of the time.
In contrast, setting it to 0.9 would make the check happen really frequently.
Setting the value to 1, '' or null will disable the feature and always force the check.
Setting the value to 0 will prevent any cache validation.
Default value is null (disabled).

## Updating

### 2.1.0
Expand Down
54 changes: 42 additions & 12 deletions lib/class.jit.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,25 +124,32 @@ public function fetchValidImageCache(array &$parameters)

// Do we have a cache file ?
if (@file_exists($file) && @is_file($file)) {
// Validate that the cache is more recent than the original
$cache_mtime = @filemtime($file);
$original_mtime = $this->fetchLastModifiedTime($parameters);

// Original file's mtime is not determined or is more recent than cache
if ($original_mtime === 0 || $original_mtime > $cache_mtime) {
// Delete cache
General::deleteFile($file);
// Validate that the cache is more recent than the original
if ($this->shouldDoCacheInvalidation()) {
$original_mtime = $this->fetchLastModifiedTime($parameters);

// Original file's mtime is not determined or is more recent than cache
if ($original_mtime === 0 || $original_mtime > $cache_mtime) {
// Delete cache
General::deleteFile($file);
// Export the invalidation state
$parameters['cached_invalidated'] = 'invalidated';
// Cache is invalid
return null;
} else {
// Export the invalidation state
$parameters['cached_invalidated'] = 'validated';
}
} else {
// Export the invalidation state
$parameters['cached_invalidated'] = true;
// Cache is invalid
return null;
$parameters['cached_invalidated'] = 'ignored';
}

// Load the cache file
$image = @\Image::load($file);

if ($image) {

// Export the last modified time
$parameters['last_modified'] = $cache_mtime;

Expand All @@ -157,9 +164,30 @@ public function fetchValidImageCache(array &$parameters)
return $image;
}
}
// No valid cache found
return null;
}

/**
* This method returns true when this request should check if the
* cache is still valid. By default, this method always returns true.
* If the `cache_invalidation_odds` is properly set, it returns true
* if the odds are greater than a random number.
*
* @return boolean
* true if cache validation should occur, false otherwise
*/
public function shouldDoCacheInvalidation()
{
$odds = Symphony::Configuration()->get('cache_invalidation_odds', 'image');
if (!is_numeric($odds)) {
return true;
}
$odds = min((float)$odds, 1.0);
$random = (float)mt_rand() / (float)mt_getrandmax();
return $odds >= $random;
}

/**
* Given the parameters, tries to fetch the last modified time
* of the image. If the image is local, filemtime is used.
Expand Down Expand Up @@ -421,7 +449,9 @@ public function sendImageHeaders(array $parameters)
header('X-jit-cache: ' . $parameters['cache']);
if ($this->caching) {
header('X-jit-cache-file: ' . basename($parameters['cached_image']));
header('X-jit-cache-invalidated: ' . (isset($parameters['cached_invalidated']) ? '1' : '0'));
if (isset($parameters['cached_invalidated'])) {
header('X-jit-cache-validation: ' . $parameters['cached_invalidated']);
}
}
}

Expand Down

0 comments on commit 091a58a

Please sign in to comment.