-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Do not query result cache twice in case of cache miss #4169
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 | ||
|---|---|---|---|---|
|
|
@@ -52,24 +52,29 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement, Result | |||
| /** @var ResultStatement */ | ||||
| private $statement; | ||||
|
|
||||
| /** @var array<string,mixed>|null */ | ||||
| private $fetchedData; | ||||
|
|
||||
| /** @var array<int,array<string,mixed>>|null */ | ||||
| private $data; | ||||
|
|
||||
| /** @var int */ | ||||
| private $defaultFetchMode = FetchMode::MIXED; | ||||
|
|
||||
| /** | ||||
| * @param string $cacheKey | ||||
| * @param string $realKey | ||||
| * @param int $lifetime | ||||
| * @param string $cacheKey | ||||
| * @param string $realKey | ||||
| * @param int $lifetime | ||||
| * @param array<string,mixed>|null $fetchedData | ||||
| */ | ||||
| public function __construct(ResultStatement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime) | ||||
| public function __construct(ResultStatement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime, ?array $fetchedData = null) | ||||
| { | ||||
| $this->statement = $stmt; | ||||
| $this->resultCache = $resultCache; | ||||
| $this->cacheKey = $cacheKey; | ||||
| $this->realKey = $realKey; | ||||
| $this->lifetime = $lifetime; | ||||
| $this->fetchedData = $fetchedData; | ||||
| } | ||||
|
|
||||
| /** | ||||
|
|
@@ -336,13 +341,16 @@ private function saveToCache(): void | |||
| return; | ||||
| } | ||||
|
|
||||
| $data = $this->resultCache->fetch($this->cacheKey); | ||||
| if (! $data) { | ||||
| $data = []; | ||||
| if ($this->fetchedData === null) { | ||||
| $this->fetchedData = $this->resultCache->fetch($this->cacheKey); | ||||
| } | ||||
|
|
||||
| if (! $this->fetchedData) { | ||||
|
Member
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. Please avoid implicit conversion to boolean. It's not allowed in newer branches.
Author
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. Ok. This line was written before me - I've just change the variable name.
|
||||
| $this->fetchedData = []; | ||||
| } | ||||
|
|
||||
| $data[$this->realKey] = $this->data; | ||||
| $this->fetchedData[$this->realKey] = $this->data; | ||||
|
|
||||
| $this->resultCache->save($this->cacheKey, $data, $this->lifetime); | ||||
| $this->resultCache->save($this->cacheKey, $this->fetchedData, $this->lifetime); | ||||
| } | ||||
| } | ||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -1207,10 +1207,19 @@ public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp) | |||
| } elseif (array_key_exists($realKey, $data)) { | ||||
| $stmt = new ArrayStatement([]); | ||||
| } | ||||
| } else { | ||||
| $data = []; | ||||
|
Member
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. Why is this needed?
Author
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. It is needed to distinguish "data from query cache is not loaded" and "data from query cache is loaded and empty".
|
||||
| } | ||||
|
|
||||
| if (! isset($stmt)) { | ||||
| $stmt = new ResultCacheStatement($this->executeQuery($sql, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime()); | ||||
| $stmt = new ResultCacheStatement( | ||||
| $this->executeQuery($sql, $params, $types), | ||||
| $resultCache, | ||||
| $cacheKey, | ||||
| $realKey, | ||||
| $qcp->getLifetime(), | ||||
| $data | ||||
| ); | ||||
| } | ||||
|
|
||||
| $stmt->setFetchMode($this->defaultFetchMode); | ||||
|
|
||||
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.
Should this new argument become mandatory in 3.0.x?
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.
I think, yes.
However, the class is renamed to CachingResult in 3.0
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.
Why don't we implement a proper fix in
3.0.xfirst and then backport in a BC-way? Otherwise, it's not clear what the new intended logic is.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.
I don't know how you releasing process is working. I consider this bug as a minor so it doesn't make sense to break backward compatibility.
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.
Let's at least make it clear in the parameter description that this parameter will be mandatory in
3.0. Otherwise, it's not clear why fetching the data has to be implemented twice.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.
I feel confused about how to do it all in 2.11.
I have opened the new #4189 for 3.0.x version with BC Break and mandatory $fetchedData field.
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.
I'm not that well familiar with the design of the caching layer and I still don't get the design: instead of fetching the data from the result, why does the result now use the fetched data and still can fetch from the result via
fetch*()methods? Is this still necessary?Uh oh!
There was an error while loading. Please reload this page.
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.
The result cache is fetched in
ResultCacheStatementonly if nofetchedDatais provided to the constructor. It is done for backward compatibility - someone could useResultCacheStatementbefore and it should continue working without the last parameter.DBAL uses this class only in one place and it always sends
fetchedData. So, result cache won't be fetched 2 times if DBAL is used ordinarily.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.
Let's then continue the discussion in #4189 where BC is of no concern. The new class still depends on the
Result.