Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 08554ea

Browse files
[Cache] Use sub-second accuracy for internal expiry calculations
1 parent d4f5d46 commit 08554ea

File tree

9 files changed

+22
-23
lines changed

9 files changed

+22
-23
lines changed

src/Symfony/Component/Cache/Adapter/AbstractAdapter.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,13 @@ function ($key, $value, $isHit) use ($defaultLifetime) {
6868
$this->mergeByLifetime = \Closure::bind(
6969
function ($deferred, $namespace, &$expiredIds) use ($getId) {
7070
$byLifetime = array();
71-
$now = time();
71+
$now = microtime(true);
7272
$expiredIds = array();
7373

7474
foreach ($deferred as $key => $item) {
7575
if (null === $item->expiry) {
7676
$ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
77-
} elseif ($item->expiry > $now) {
78-
$ttl = $item->expiry - $now;
79-
} else {
77+
} elseif (0 >= $ttl = (int) ($item->expiry - $now)) {
8078
$expiredIds[] = $getId($key);
8179
continue;
8280
}
@@ -107,7 +105,7 @@ function ($deferred, $namespace, &$expiredIds) use ($getId) {
107105
*/
108106
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
109107
{
110-
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED);
108+
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
111109

112110
if (null === self::$apcuSupported) {
113111
self::$apcuSupported = ApcuAdapter::isSupported();

src/Symfony/Component/Cache/Adapter/ArrayAdapter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function getItems(array $keys = array())
8787
CacheItem::validateKey($key);
8888
}
8989

90-
return $this->generateItems($keys, time(), $this->createCacheItem);
90+
return $this->generateItems($keys, microtime(true), $this->createCacheItem);
9191
}
9292

9393
/**
@@ -115,7 +115,7 @@ public function save(CacheItemInterface $item)
115115
$value = $item["\0*\0value"];
116116
$expiry = $item["\0*\0expiry"];
117117

118-
if (null !== $expiry && $expiry <= time()) {
118+
if (null !== $expiry && $expiry <= microtime(true)) {
119119
$this->deleteItem($key);
120120

121121
return true;
@@ -131,7 +131,7 @@ public function save(CacheItemInterface $item)
131131
}
132132
}
133133
if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
134-
$expiry = time() + $item["\0*\0defaultLifetime"];
134+
$expiry = microtime(true) + $item["\0*\0defaultLifetime"];
135135
}
136136

137137
$this->values[$key] = $value;

src/Symfony/Component/Cache/Adapter/ProxyAdapter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function (CacheItemInterface $innerItem, array $item) {
8181
$item["\0*\0value"] = array("\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $item["\0*\0value"]);
8282
}
8383
$innerItem->set($item["\0*\0value"]);
84-
$innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U', $item["\0*\0expiry"]) : null);
84+
$innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', $item["\0*\0expiry"])) : null);
8585
},
8686
null,
8787
CacheItem::class
@@ -200,7 +200,7 @@ private function doSave(CacheItemInterface $item, $method)
200200
}
201201
$item = (array) $item;
202202
if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) {
203-
$item["\0*\0expiry"] = time() + $item["\0*\0defaultLifetime"];
203+
$item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"];
204204
}
205205
$innerItem = $item["\0*\0poolHash"] === $this->poolHash ? $item["\0*\0innerItem"] : $this->pool->getItem($this->namespace.$item["\0*\0key"]);
206206
($this->setInnerItem)($innerItem, $item);

src/Symfony/Component/Cache/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* added `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache
8+
* added sub-second expiry accuracy for backends that support it
89
* throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool
910
* deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead
1011
* deprecated the `AbstractAdapter::createSystemCache()` method

src/Symfony/Component/Cache/CacheItem.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ public function set($value)
8989
public function expiresAt($expiration)
9090
{
9191
if (null === $expiration) {
92-
$this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null;
92+
$this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null;
9393
} elseif ($expiration instanceof \DateTimeInterface) {
94-
$this->expiry = (int) $expiration->format('U');
94+
$this->expiry = (float) $expiration->format('U.u');
9595
} else {
9696
throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given', is_object($expiration) ? get_class($expiration) : gettype($expiration)));
9797
}
@@ -105,11 +105,11 @@ public function expiresAt($expiration)
105105
public function expiresAfter($time)
106106
{
107107
if (null === $time) {
108-
$this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null;
108+
$this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null;
109109
} elseif ($time instanceof \DateInterval) {
110-
$this->expiry = (int) \DateTime::createFromFormat('U', time())->add($time)->format('U');
110+
$this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u');
111111
} elseif (\is_int($time)) {
112-
$this->expiry = $time + time();
112+
$this->expiry = $time + microtime(true);
113113
} else {
114114
throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', is_object($time) ? get_class($time) : gettype($time)));
115115
}

src/Symfony/Component/Cache/Simple/ArrayCache.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function getMultiple($keys, $default = null)
6464
CacheItem::validateKey($key);
6565
}
6666

67-
return $this->generateItems($keys, time(), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; });
67+
return $this->generateItems($keys, microtime(true), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; });
6868
}
6969

7070
/**
@@ -121,7 +121,7 @@ public function setMultiple($values, $ttl = null)
121121
}
122122
}
123123
}
124-
$expiry = 0 < $ttl ? time() + $ttl : PHP_INT_MAX;
124+
$expiry = 0 < $ttl ? microtime(true) + $ttl : PHP_INT_MAX;
125125

126126
foreach ($valuesArray as $key => $value) {
127127
$this->values[$key] = $value;

src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ public function testGetMetadata()
7777
$item = $cache->getItem('foo');
7878

7979
$expected = array(
80-
CacheItem::METADATA_EXPIRY => 9 + time(),
80+
CacheItem::METADATA_EXPIRY => 9.5 + time(),
8181
CacheItem::METADATA_CTIME => 1000,
8282
);
83-
$this->assertSame($expected, $item->getMetadata());
83+
$this->assertEquals($expected, $item->getMetadata(), 'Item metadata should embed expiry and ctime.', .6);
8484
}
8585

8686
public function testDefaultLifeTime()

src/Symfony/Component/Cache/Tests/Fixtures/ArrayCache.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ protected function doContains($id)
2121

2222
$expiry = $this->data[$id][1];
2323

24-
return !$expiry || time() <= $expiry || !$this->doDelete($id);
24+
return !$expiry || microtime(true) < $expiry || !$this->doDelete($id);
2525
}
2626

2727
protected function doSave($id, $data, $lifeTime = 0)
2828
{
29-
$this->data[$id] = array($data, $lifeTime ? time() + $lifeTime : false);
29+
$this->data[$id] = array($data, $lifeTime ? microtime(true) + $lifeTime : false);
3030

3131
return true;
3232
}

src/Symfony/Component/Cache/Traits/ArrayTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function hasItem($key)
4444
{
4545
CacheItem::validateKey($key);
4646

47-
return isset($this->expiries[$key]) && ($this->expiries[$key] >= time() || !$this->deleteItem($key));
47+
return isset($this->expiries[$key]) && ($this->expiries[$key] > microtime(true) || !$this->deleteItem($key));
4848
}
4949

5050
/**
@@ -81,7 +81,7 @@ private function generateItems(array $keys, $now, $f)
8181
{
8282
foreach ($keys as $i => $key) {
8383
try {
84-
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] >= $now || !$this->deleteItem($key))) {
84+
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
8585
$this->values[$key] = $value = null;
8686
} elseif (!$this->storeSerialized) {
8787
$value = $this->values[$key];

0 commit comments

Comments
 (0)