10000 [Contracts] Add Cache contract to extend PSR-6 with tag invalidation,… · symfony/symfony@a6659db · GitHub
[go: up one dir, main page]

Skip to content

Commit a6659db

Browse files
[Contracts] Add Cache contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection
1 parent a31f4aa commit a6659db

8 files changed

+222
-0
lines changed

src/Symfony/Contracts/CHANGELOG.md

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

77
* added `Service\ResetInterface` to provide a way to reset an object to its initial state
8+
* added `Cache` contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
/**
15+
* Gets and stores items from a cache.
16+
*
17+
* On cache misses, a callback is called that should return the missing value.
18+
* This callback is given an ItemInterface object corresponding to the needed key,
19+
* that could be used e.g. for expiration control.
20+
*
21+
* @author Nicolas Grekas <p@tchwork.com>
22+
*/
23+
interface CacheInterface
24+
{
25+
/**
26+
* @param callable(ItemInterface):mixed $callback Should return the computed value for the given key/item
27+
* @param float|null $beta A float that, as it grows, controls the likeliness of triggering
28+
* early expiration. 0 disables it, INF forces immediate expiration.
29+
* The default (or providing null) is implementation dependent but should
30+
* typically be 1.0, which should provide optimal stampede protection.
31+
*
32+
* @return mixed The value corresponding to the provided key
33+
*
34+
* @throws InvalidArgumentException When $key is not valid or when $beta is negative
35+
*/
36+
public function get(string $key, callable $callback, float $beta = null);
37+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
16+
/**
17+
* An interface that extends CacheInterface with the methods from PSR-6's CacheItemPoolInterface.
18+
*/
19+
interface ExtendedCacheInterface extends CacheInterface, CacheItemPoolInterface
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
16+
/**
17+
* An interface that extends TagAwareCacheInterface with the methods from PSR-6's CacheItemPoolInterface.
18+
*/
19+
interface ExtendedTagAwareCacheInterface extends TagAwareCacheInterface, CacheItemPoolInterface
20+
{
21+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
* A simple implementation of CacheInterface::get() for PSR-6 CacheItemPoolInterface classes.
19+
*
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*/
22+
trait GetForCacheItemPoolTrait
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function get(string $key, callable $callback, float $beta = null)
28+
{
29+
if (0 > $beta) {
30+
throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive integer, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException {
31+
};
32+
}
33+
34+
$item = $this->getItem($key);
35+
36+
if (INF === $beta || !$item->isHit()) {
37+
$value = $callback($item);
38+
$item->set($value);
39+
}
40+
41+
return $item->get();
42+
}
43+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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\CacheException;
15+
use Psr\Cache\CacheItemInterface;
16+
use Psr\Cache\InvalidArgumentException;
17+
18+
/**
19+
* @author Nicolas Grekas <p@tchwork.com>
20+
*/
21+
interface ItemInterface extends CacheItemInterface
22+
{
23+
/**
24+
* References the Unix timestamp stating when the item will expire.
25+
*/
26+
const METADATA_EXPIRY = 'expiry';
27+
28+
/**
29+
* References the time the item took to be created, in milliseconds.
30+
*/
31+
const METADATA_CTIME = 'ctime';
32+
33+
/**
34+
* References the list of tags that were assigned to the item, as string[].
35+
*/
36+
const METADATA_TAGS = 'tags';
37+
38+
/**
39+
* Adds a tag to a cache item.
40+
*
41+
* Tags are strings that follow the same validation rules as keys.
42+
*
43+
* @param string|string[] $tags A tag or array of tags
44+
*
45+
* @return $this
46+
*
47+
* @throws InvalidArgumentException When $tag is not valid
48+
* @throws CacheException When the item comes from a pool that is not tag-aware
49+
*/
50+
public function tag($tags): self;
51+
52+
/**
53+
* Returns a list of metadata info that were saved alongside with the cached value.
54+
*
55+
* See ItemInterface::METADATA_* consts for keys potentially found in the returned array.
56+
*/
57+
public function getMetadata(): array;
58+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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\InvalidArgumentException;
15+
16+
/**
17+
* Interface for invalidating cached items using tags.
18+
*
19+
* @author Nicolas Grekas <p@tchwork.com>
20+
*/
21+
interface TagAwareCacheInterface extends CacheInterface
22+
{
23+
/**
24+
* Invalidates cached items using tags.
25+
*
26+
* When implemented on a PSR-6 pool, invalidation should not apply
27+
* to deferred items. Instead, they should be committed as usual.
28+
* This allows replacing old tagged values by new ones without
29+
* race conditions.
30+
*
31+
* @param string[] $tags An array of tags to inval C28F idate
32+
*
33+
* @return bool True on success
34+
*
35+
* @throws InvalidArgumentException When $tags is not valid
36+
*/
37+
public function invalidateTags(array $tags);
38+
}

src/Symfony/Contracts/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
"require": {
1919
"php": "^7.1.3"
2020
},
21+
"suggest": {
22+
"psr/cache": "When using the Cache contract"
23+
},
2124
"autoload": {
2225
"psr-4": { "Symfony\\Contracts\\": "" },
2326
"exclude-from-classmap": [

0 commit comments

Comments
 (0)
0