Skip to content

Commit

Permalink
bug #33846 [Cache] give 100ms before starting the expiration countdow…
Browse files Browse the repository at this point in the history
…n (nicolas-grekas)

This PR was merged into the 4.3 branch.

Discussion
----------

[Cache] give 100ms before starting the expiration countdown

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #31573, Fix #33837
| License       | MIT
| Doc PR        | -

Because the expiration count-down starts immediately after calling `CachItem::expiresAfter(N)`, it's impossible to actually cache items for more than `N-1` seconds.

This PR adds a 0.1s grace period so that backends that have a second-level resolution can store the items for `N` seconds, provided the time between calling `CachItem::expiresAfter(N)` and saving the value to the backend is lower than 0.1s.

This PR also fixes the calculation of the computation time in `ContractsTrait`.

Commits
-------

ba63e18 [Cache] give 100ms before starting the expiration countdown
  • Loading branch information
nicolas-grekas committed Oct 4, 2019
2 parents 1124809 + ba63e18 commit 6016070
Show file tree
Hide file tree
Showing 6 changed files with 8 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
Expand Up @@ -76,15 +76,15 @@ static function ($deferred, $namespace, &$expiredIds) use ($getId) {
$key = (string) $key;
if (null === $item->expiry) {
$ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
} elseif (0 >= $ttl = (int) ($item->expiry - $now)) {
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
$expiredIds[] = $getId($key);
continue;
}
if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
unset($metadata[CacheItem::METADATA_TAGS]);
}
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
$byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
$byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
}

return $byLifetime;
Expand Down
Expand Up @@ -82,7 +82,7 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
$key = (string) $key;
if (null === $item->expiry) {
$ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
} elseif (0 >= $ttl = (int) ($item->expiry - $now)) {
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
$expiredIds[] = $getId($key);
continue;
}
Expand All @@ -96,7 +96,7 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {

if ($metadata) {
// For compactness, expiry and creation duration are packed, using magic numbers as separators
$value['meta'] = pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME]);
$value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]);
}

// Extract tag changes, these should be removed from values in doSave()
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
Expand Up @@ -84,7 +84,7 @@ static function (CacheItemInterface $innerItem, array $item) {
}
if ($metadata) {
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
$item["\0*\0value"] = ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
$item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
}
$innerItem->set($item["\0*\0value"]);
$innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', $item["\0*\0expiry"])) : null);
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Cache/Psr16Cache.php
Expand Up @@ -169,7 +169,7 @@ public function getMultiple($keys, $default = null)
unset($metadata[CacheItem::METADATA_TAGS]);

if ($metadata) {
$values[$key] = ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
$values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
}
}

Expand Down
Expand Up @@ -109,7 +109,7 @@ public function testGetMetadata()
$cache->deleteItem('foo');
$cache->get('foo', function ($item) {
$item->expiresAfter(10);
sleep(1);
usleep(999000);

return 'bar';
});
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Cache/Traits/ContractsTrait.php
Expand Up @@ -61,7 +61,7 @@ private function doGet(AdapterInterface $pool, string $key, callable $callback,
static function (CacheItem $item, float $startTime, ?array &$metadata) {
if ($item->expiry > $endTime = microtime(true)) {
$item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
$item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = 1000 * (int) ($endTime - $startTime);
$item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
} else {
unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]);
}
Expand Down

0 comments on commit 6016070

Please sign in to comment.