Skip to content

Commit 8dceb51

Browse files
[Cache] add CacheInterface::delete() + improve CacheContractsTrait
1 parent 0f653d8 commit 8dceb51

File tree

8 files changed

+176
-104
lines changed

8 files changed

+176
-104
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,12 @@ public function commit()
151151
{
152152
return true;
153153
}
154+
155+
/**
156+
* {@inheritdoc}
157+
*/
158+
public function delete(string $key): bool
159+
{
160+
return $this->deleteItem($key);
161+
}
154162
}

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

+8
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ public function commit()
119119
return false;
120120
}
121121

122+
/**
123+
* {@inheritdoc}
124+
*/
125+
public function delete(string $key): bool
126+
{
127+
return $this->deleteItem($key);
128+
}
129+
122130
private function generateItems(array $keys)
123131
{
124132
$f = $this->createCacheItem;

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

+13
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,19 @@ public function reset()
237237
}
238238
}
239239

240+
/**
241+
* {@inheritdoc}
242+
*/
243+
public function delete(string $key): bool
244+
{
245+
$event = $this->start(__FUNCTION__);
246+
try {
247+
return $event->result[$key] = $this->pool->deleteItem($key);
248+
} finally {
249+
$event->end = microtime(true);
250+
}
251+
}
252+
240253
public function getCalls()
241254
{
242255
return $this->calls;

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

+18-45
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Cache\CacheItem;
1616
use Symfony\Component\Cache\Exception\InvalidArgumentException;
1717
use Symfony\Component\Cache\LockRegistry;
18+
use Symfony\Contracts\Cache\CacheContractsTrait;
1819
use Symfony\Contracts\Cache\CacheInterface;
1920
use Symfony\Contracts\Cache\ItemInterface;
2021

@@ -25,6 +26,10 @@
2526
*/
2627
trait GetTrait
2728
{
29+
use CacheContractsTrait {
30+
doGet as private contractsGet;
31+
}
32+
2833
private $callbackWrapper = array(LockRegistry::class, 'compute');
2934

3035
/**
@@ -42,47 +47,12 @@ public function setCallbackWrapper(callable $callbackWrapper): callable
4247
return $previousWrapper;
4348
}
4449

45-
/**
46-
* {@inheritdoc}
47-
*/
48-
public function get(string $key, callable $callback, float $beta = null)
49-
{
50-
return $this->doGet($this, $key, $callback, $beta);
51-
}
52-
5350
private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta)
5451
{
5552
if (0 > $beta = $beta ?? 1.0) {
5653
throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta));
5754
}
5855

59-
$t = 0;
60-
$item = $pool->getItem($key);
61-
$recompute = !$item->isHit() || INF === $beta;
62-
63-
if (0 < $beta) {
64-
if ($recompute) {
65-
$t = microtime(true);
66-
} else {
67-
$metadata = $item->getMetadata();
68-
$expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
69-
$ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
70-
71-
if ($ctime && $expiry) {
72-
$t = microtime(true);
73-
$recompute = $expiry <= $t - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX);
74-
}
75-
}
76-
if ($recompute) {
77-
// force applying defaultLifetime to expiry
78-
$item->expiresAt(null);
79-
}
80-
}
81-
82-
if (!$recompute) {
83-
return $item->get();
84-
}
85-
8656
static $save;
8757

8858
$save = $save ?? \Closure::bind(
@@ -99,16 +69,19 @@ function (AdapterInterface $pool, ItemInterface $item, $value, float $startTime)
9969
CacheItem::class
10070
);
10171

102-
// don't wrap nor save recursive calls
103-
if (null === $callbackWrapper = $this->callbackWrapper) {
104-
return $callback($item);
105-
}
106-
$this->callbackWrapper = null;
72+
return $this->contractsGet($pool, $key, function (CacheItem $item) use ($pool, $callback, $save) {
73+
// don't wrap nor save recursive calls
74+
if (null === $callbackWrapper = $this->callbackWrapper) {
75+
return $callback($item);
76+
}
77+
$this->callbackWrapper = null;
78+
$t = microtime(true);
10779

108-
try {
109-
return $save($pool, $item, $callbackWrapper($item, $callback, $pool), $t);
110-
} finally {
111-
$this->callbackWrapper = $callbackWrapper;
112-
}
80+
try {
81+
return $save($pool, $item, $callbackWrapper($item, $callback, $pool), $t);
82+
} finally {
83+
$this->callbackWrapper = $callbackWrapper;
84+
}
85+
}, $beta);
11386
}
11487
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Contracts\Cache;
13+
14+
use Psr\Cache\CacheItemPoolInterface;
15+
use Psr\Cache\InvalidArgumentException;
16+
17+
/**
18+
* An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
19+
*
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*/
22+
trait CacheContractsTrait
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function get(string $key, callable $callback, float $beta = null)
28+
{
29+
return $this->doGet($this, $key, $callback, $beta);
30+
}
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function delete(string $key): bool
36+
{
37+
return $this->deleteItem($key);
38+
}
39+
40+
private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta)
41+
{
42+
if (0 > $beta = $beta ?? 1.0) {
43+
throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException {
44+
};
45+
}
46+
47+
$item = $pool->getItem($key);
48+
$recompute = !$item->isHit() || INF === $beta;
49+
50+
if (!$recompute && $item instanceof ItemInterface) {
51+
$metadata = $item->getMetadata();
52+
$expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
53+
$ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
54+
55+
if ($recompute = $ctime && $expiry && $expiry <= microtime(true) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) {
56+
// force applying defaultLifetime to expiry
57+
$item->expiresAt(null);
58+
}
59+
}
60+
61+
if ($recompute) {
62+
$pool->save($item->set($callback($item)));
63+
}
64+
65+
return $item->get();
66+
}
67+
}

src/Symfony/Contracts/Cache/CacheInterface.php

+21-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Contracts\Cache;
1313

14+
use Psr\Cache\CacheItemInterface;
1415
use Psr\Cache\InvalidArgumentException;
1516

1617
/**
@@ -25,17 +26,30 @@
2526
interface CacheInterface
2627
{
2728
/**
28-
* @param string $key The key of the item to retrieve from the cache
29-
* @param callable(ItemInterface):mixed $callback Should return the computed value for the given key/item
30-
* @param float|null $beta A float that, as it grows, controls the likeliness of triggering
31-
* early expiration. 0 disables it, INF forces immediate expiration.
32-
* The default (or providing null) is implementation dependent but should
33-
* typically be 1.0, which should provide optimal stampede protection.
34-
* See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
29+
* Fetches a value from the pool or computes it if not found.
30+
*
31+
* @param string $key The key of the item to retrieve from the cache
32+
* @param callable(CacheItemInterface):mixed $callback Should return the computed value for the given key/item
33+
* @param float|null $beta A float that, as it grows, controls the likeliness of triggering
34+
* early expiration. 0 disables it, INF forces immediate expiration.
35+
* The default (or providing null) is implementation dependent but should
36+
* typically be 1.0, which should provide optimal stampede protection.
37+
* See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
3538
*
3639
* @return mixed The value corresponding to the provided key
3740
*
3841
* @throws InvalidArgumentException When $key is not valid or when $beta is negative
3942
*/
4043
public function get(string $key, callable $callback, float $beta = null);
44+
45+
/**
46+
* Removes the item from the pool.
47+
*
48+
* @param string $key The key to delete
49+
*
50+
* @throws InvalidArgumentException When $key is not valid
51+
*
52+
* @return bool True if the item was successfully removed, false if there was any error
53+
*/
54+
public function delete(string $key): bool;
4155
}

src/Symfony/Contracts/Cache/GetForCacheItemPoolTrait.php

-44
This file was deleted.

0 commit comments

Comments
 (0)