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

Skip to content

Commit 0978604

Browse files
committed
feature #28096 [Contracts] Add Cache contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection (nicolas-grekas)
This PR was merged into the 4.2-dev branch. Discussion ---------- [Contracts] Add Cache contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Let's separate the useful interfaces of the Cache component in Contracts. This does not include `PruneableInterface`, `MarshallerInterface` nor `*AdapterInterface` because they are too specific to the component. But `CacheInterface`, `TawAwareCacheInterface` and `ItemInterface` form a nice consistent set of features on top of PSR-6. Updating the Cache component to use these interfaces will be done in a separate PR so that we can focus on the contract itself here. Commits ------- ca6478b [Contracts] Add Cache contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection
2 parents baad332 + ca6478b commit 0978604

File tree

7 files changed

+187
-0
lines changed

7 files changed

+187
-0
lines changed

src/Symfony/Contracts/CHANGELOG.md

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

77
* added `Service\ResetInterface` to provide a way to reset an object to its initial state
88
* added `Translation\TranslatorInterface` and `Translation\TranslatorTrait`
9+
* added `Cache` contract to extend PSR-6 with tag invalidation, callback-based computation and stampede protection
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
* Gets/Stores items from/to a cache.
18+
*
19+
* On cache misses, a callback is called that should return the missing value.
20+
* This callback is given an ItemInterface object corresponding to the needed key,
21+
* that could be used e.g. for expiration control.
22+
*
23+
* @author Nicolas Grekas <[email protected]>
24+
*/
25+
interface CacheInterface
26+
{
27+
/**
28+
* @param callable(ItemInterface):mixed $callback Should return the computed value for the given key/item
29+
* @param float|null $beta A float that, as it grows, controls the likeliness of triggering
30+
* early expiration. 0 disables it, INF forces immediate expiration.
31+
* The default (or providing null) is implementation dependent but should
32+
* typically be 1.0, which should provide optimal stampede protection.
33+
* See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
34+
*
35+
* @return mixed The value corresponding to the provided key
36+
*
37+
* @throws InvalidArgumentException When $key is not valid or when $beta is negative
38+
*/
39+
public function get(string $key, callable $callback, float $beta = null);
40+
}
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 <[email protected]>
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 <[email protected]>
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 number, %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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 invalidate
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/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ Design Principles
1515
* all contracts must have a proven implementation to enter this repository;
1616
* they must be backward compatible with existing Symfony components.
1717

18+
Packages that implement specific contracts should list them in the "provide"
19+
section of their "composer.json" file, using the `symfony/*-contracts`
20+
convention (e.g. `"provide": { "symfony/cache-contracts": "1.0" }`).
21+
1822
FAQ
1923
---
2024

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)