-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Cache] Allow and use generators in AbstractAdapter #17438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,7 +64,7 @@ function ($deferred, $namespace) { | |
* | ||
* @param array $ids The cache identifiers to fetch. | ||
* | ||
* @return array The corresponding values found in the cache. | ||
* @return array|\Traversable The corresponding values found in the cache. | ||
*/ | ||
abstract protected function doFetch(array $ids); | ||
|
||
|
@@ -80,9 +80,11 @@ abstract protected function doHave($id); | |
/** | ||
* Deletes all items in the pool. | ||
* | ||
* @param string The prefix used for all identifiers managed by this pool. | ||
* | ||
* @return bool True if the pool was successfully cleared, false otherwise. | ||
*/ | ||
abstract protected function doClear(); | ||
abstract protected function doClear($namespace); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I propose adding $namespace to this abstract method so that adapters can flush only a subpart of their global pool if that applies |
||
|
||
/** | ||
* Removes multiple items from the pool. | ||
|
@@ -108,14 +110,10 @@ abstract protected function doSave(array $values, $lifetime); | |
*/ | ||
public function getItem($key) | ||
{ | ||
$id = $this->getId($key); | ||
|
||
if ($this->deferred) { | ||
$this->commit(); | ||
} | ||
if (isset($this->deferred[$key])) { | ||
return $this->deferred[$key]; | ||
} | ||
$id = $this->getId($key); | ||
|
||
$f = $this->createCacheItem; | ||
$isHit = false; | ||
|
@@ -136,40 +134,35 @@ public function getItems(array $keys = array()) | |
if ($this->deferred) { | ||
$this->commit(); | ||
} | ||
$f = $this->createCacheItem; | ||
$ids = array(); | ||
$items = array(); | ||
|
||
foreach ($keys as $key) { | ||
$id = $this->getId($key); | ||
|
||
if (isset($this->deferred[$key])) { | ||
$items[$key] = $this->deferred[$key]; | ||
} else { | ||
$ids[$key] = $id; | ||
} | ||
$ids[$key] = $this->getId($key); | ||
} | ||
$items = $this->doFetch($ids); | ||
$ids = array_flip($ids); | ||
|
||
$values = $this->doFetch($ids); | ||
|
||
foreach ($ids as $key => $id) { | ||
$isHit = isset($values[$id]); | ||
$items[$key] = $f($key, $isHit ? $values[$id] : null, $isHit); | ||
} | ||
|
||
return $items; | ||
return $this->generateItems($items, $ids); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function hasItem($key) | ||
{ | ||
if ($this->deferred) { | ||
$this->commit(); | ||
$id = $this->getId($key); | ||
|
||
if (isset($this->deferred[$key])) { | ||
$item = (array) $this->deferred[$key]; | ||
$ok = $this->doSave(array($item[CacheItem::CAST_PREFIX.'key'] => $item[CacheItem::CAST_PREFIX.'value']), $item[CacheItem::CAST_PREFIX.'lifetime']); | ||
unset($this->deferred[$key]); | ||
|
||
if (true === $ok || array() === $ok) { | ||
return true; | ||
} | ||
} | ||
|
||
return $this->doHave($this->getId($key)); | ||
return $this->doHave($id); | ||
} | ||
|
||
/** | ||
|
@@ -179,7 +172,7 @@ public function clear() | |
{ | ||
$this->deferred = array(); | ||
|
||
return $this->doClear(); | ||
return $th 8000 is->doClear($this->namespace); | ||
} | ||
|
||
/** | ||
|
@@ -198,7 +191,7 @@ public function deleteItems(array $keys) | |
$ids = array(); | ||
|
||
foreach ($keys as $key) { | ||
$ids[] = $this->getId($key); | ||
$ids[$key] = $this->getId($key); | ||
unset($this->deferred[$key]); | ||
} | ||
|
||
|
@@ -213,11 +206,12 @@ public function save(CacheItemInterface $item) | |
if (!$item instanceof CacheItem) { | ||
return false; | ||
} | ||
$key = $item->getKey(); | ||
$this->deferred[$key] = $item; | ||
$this->commit(); | ||
if ($this->deferred) { | ||
$this->commit(); | ||
} | ||
$this->deferred[$item->getKey()] = $item; | ||
|
||
return !isset($this->deferred[$key]); | ||
return $this->commit(); | ||
} | ||
|
||
/** | ||
|
@@ -230,10 +224,7 @@ public function saveDeferred(CacheItemInterface $item) | |
} | ||
try { | ||
$item = clone $item; | ||
} catch (\Error $e) { | ||
} catch (\Exception $e) { | ||
} | ||
if (isset($e)) { | ||
@trigger_error($e->__toString()); | ||
|
||
return false; | ||
|
@@ -250,7 +241,6 @@ public function commit() | |
{ | ||
$f = $this->mergeByLifetime; | ||
$ko = array(); | ||
$namespaceLen = strlen($this->namespace); | ||
|
||
foreach ($f($this->deferred, $this->namespace) as $lifetime => $values) { | ||
if (true === $ok = $this->doSave($values, $lifetime)) { | ||
|
@@ -259,13 +249,28 @@ public function commit() | |
if (false === $ok) { | ||
$ok = array_keys($values); | ||
} | ||
foreach ($ok as $failedId) { | ||
$key = substr($failedId, $namespaceLen); | ||
$ko[$key] = $this->deferred[$key]; | ||
foreach ($ok as $id) { | ||
$ko[$lifetime][] = array($id => $values[$id]); | ||
} | ||
} | ||
|
||
return !$this->deferred = $ko; | ||
$this->deferred = array(); | ||
$ok = true; | ||
|
||
// When bulk-save failed, retry each item individually | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The previous logic has a "memory leak" in that whenever a deferred couldn't be saved, it would never be freed. |
||
foreach ($ko as $lifetime => $values) { | ||
foreach ($values as $v) { | ||
if (!in_array($this->doSave($v, $lifetime), array(true, array()), true)) { | ||
$ok = false; | ||
|
||
foreach ($v as $key => $value) { | ||
@trigger_error(sprintf('Failed to cache key "%s" of type "%s"', is_object($value) ? get_class($value) : gettype($value))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could help someone someday figure out what's wrong... |
||
} | ||
} | ||
} | ||
} | ||
|
||
return $ok; | ||
} | ||
|
||
public function __destruct() | ||
|
@@ -289,4 +294,18 @@ private function getId($key) | |
|
||
return $this->namespace.$key; | ||
} | ||
|
||
private function generateItems($items, &$keys) | ||
{ | ||
$f = $this->createCacheItem; | ||
|
||
foreach ($items as $id => $value) { | ||
yield $keys[$id] => $f($keys[$id], $value, true); | ||
unset($keys[$id]); | ||
} | ||
|
||
foreach ($keys as $key) { | ||
yield $key => $f($key, null, false); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,11 @@ | |
*/ | ||
final class CacheItem implements CacheItemInterface | ||
{ | ||
/** | ||
* @internal | ||
*/ | ||
const CAST_PREFIX = "\0Symfony\Component\Cache\CacheItem\0"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping @dunglas There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
private $key; | ||
private $value; | ||
private $isHit; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this until the test suite fits our needs. I suggest we add a version number when the Component is stable enough/feature full, in a few weeks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be changed to
"^0.7"
now, I guess?