Make query cache rely on entity timestamp region #6001

Closed
wants to merge 4 commits into
from

Projects

None yet

3 participants

@lcobucci
Member
lcobucci commented Sep 2, 2016

As far as I saw that's the default Hibernate behavior (https://vladmihalcea.com/2015/06/08/how-does-hibernate-query-cache-work/) to keep the query cache consistent.

I'm just not sure if that is the way to go, basically because of the change on the CachedEntityPersister interface (I didn't want to duplicate the logic that generates the timestamp key).

@lcobucci
Member
lcobucci commented Sep 5, 2016 edited

I had an idea to improve this PR a bit by moving the timestamp region check to the query cache validator but this also means moving the timestampKey to the QueryCacheKey.

I think it's a better solution, what's your opinion?

@guilhermeblanco
Member

@lcobucci indeed that's a MUCH BETTER solution. If I understood your idea correctly, you'd eliminate the BC break by adding a new interface method.
This means it could potentially be part of 2.X series instead of 3.X only. =)

If you're willing to work on that, I'd appreciate.

@lcobucci
Member
lcobucci commented Sep 6, 2016 edited

@guilhermeblanco I really need this to be part of 2.X so I'm glad to help 😉

If I understood your idea correctly, you'd eliminate the BC break by adding a new interface method.

My idea basically is:

  1. Add timestampRegion to the TimestampQueryCacheValidator constructor
  2. Add timestampKey to the QueryCacheKey constructor
  3. Make TimestampQueryCacheValidator#isValid() also validate the timestamp using the region and the key

I couldn't see the BC break you said, can you please elaborate a bit more?

The biggest question here is: what'd be the best place to retrieve the timestampKey?
Passing it to the QueryCacheKey constructor means that we need to have it available also on the AbstractQuery#executeUsingQueryCache().

Moving those things to que validator also simplifies the AbstractEntityPersister#getHash() logic, since we don't need concatenate the $timestamp anymore (and we could also remove the unused timestampRegion from the persister).

@Ocramius Ocramius commented on an outdated diff Sep 7, 2016
.../ORM/Cache/Persister/Entity/CachedEntityPersister.php
@@ -44,4 +44,9 @@ public function getEntityHydrator();
* @return boolean
*/
public function storeEntityCache($entity, EntityCacheKey $key);
+
+ /**
+ * @return \Doctrine\ORM\Cache\TimestampCacheKey
+ */
+ public function getTimestampKey();
@Ocramius
Ocramius Sep 7, 2016 Member

bc break, sadly

@Ocramius
Ocramius Sep 7, 2016 Member

Also, I don't know how to regenerate a timestamp key, if not retrieved from here.

@lcobucci
Member
lcobucci commented Sep 7, 2016

Ow ofc. Do you think that the solution I explained is applicable?

@Ocramius
Member
Ocramius commented Sep 7, 2016

@lcobucci moving more info to the QueryCacheKey seems good to me, since it's information that sticks together anyway. I don't have the full picture though, sorry.

@lcobucci
Member
lcobucci commented Sep 7, 2016

@guilhermeblanco @Ocramius introduced a tiny duplication in order to remove the BC break. I think it should be ok to be merged on v2.X now.

Anything else?

@Ocramius Ocramius and 1 other commented on an outdated diff Sep 7, 2016
lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php
if ($key->lifetime == 0) {
return true;
}
return ($entry->time + $key->lifetime) > time();
}
+
+ private function regionUpdated(QueryCacheKey $key, QueryCacheEntry $entry)
+ {
+ if ($key->timestampKey === null) {
@Ocramius
Ocramius Sep 7, 2016 Member

The docblock states that it is never null: can you check that?

@lcobucci
lcobucci Sep 8, 2016 Member

The docblock is a liar! Will fix that, thanks

@Ocramius Ocramius and 1 other commented on an outdated diff Sep 7, 2016
lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php
if ($key->lifetime == 0) {
return true;
}
return ($entry->time + $key->lifetime) > time();
}
+
+ private function regionUpdated(QueryCacheKey $key, QueryCacheEntry $entry)
@Ocramius
Ocramius Sep 7, 2016 Member

Docblock plz, even if it just says that a boolean is returned

@lcobucci
Member
lcobucci commented Sep 8, 2016

@guilhermeblanco @Ocramius comments processed let me know if there's anything else preventing this to be merged and let's :shipit:

@Ocramius Ocramius commented on the diff Sep 8, 2016
lib/Doctrine/ORM/Cache/QueryCacheEntry.php
@@ -38,18 +38,18 @@ class QueryCacheEntry implements CacheEntry
/**
* READ-ONLY: Public only for performance reasons, it should be considered immutable.
*
- * @var integer Time creation of this cache entry
+ * @var float Time creation of this cache entry
@Ocramius
Ocramius Sep 8, 2016 Member

Since there was a change here, did you check all usages of this property?

@lcobucci
lcobucci Sep 8, 2016 Member

I did but I definitely forgot to change ($entry->time + $key->lifetime) > time() to ((int) $entry->time + $key->lifetime) > time() on the validator

@Ocramius Ocramius commented on the diff Sep 8, 2016
lib/Doctrine/ORM/Cache/QueryCacheKey.php
@@ -45,14 +45,27 @@ class QueryCacheKey extends CacheKey
public $cacheMode;
/**
- * @param string $hash Result cache id
- * @param integer $lifetime Query lifetime
- * @param integer $cacheMode Query cache mode
+ * READ-ONLY: Public only for performance reasons, it should be considered immutable.
+ *
+ * @var TimestampCacheKey|null
+ */
+ public $timestampKey;
+
+ /**
+ * @param string $hash Result cache id
+ * @param integer $lifetime Query lifetime
+ * @param int $cacheMode Query cache mode
+ * @param TimestampCacheKey|null $timestampKey
@Ocramius Ocramius commented on the diff Sep 8, 2016
...sts/ORM/Functional/SecondLevelCacheQueryCacheTest.php
+ $this->assertCount(2, $result1);
+ $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
+
+ $this->_em->persist(new Country('France'));
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $queryCount = $this->getCurrentQueryCount();
+
+ $result2 = $this->_em->createQuery($dql)
+ ->setCacheable(true)
+ ->getResult();
+
+ $this->assertCount(3, $result2);
+ $this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
@Ocramius
Ocramius Sep 8, 2016 Member

Wait... Shouldn't this be $queryCount + 2?

@Ocramius
Ocramius Sep 8, 2016 Member

I would expect that because of the region being updated (and therefore cache evicted)

@Ocramius
Ocramius Sep 8, 2016 Member

Argh, totally misread, sorry. Missed that you are resetting the $queryCount after the first query.

lcobucci added some commits Sep 2, 2016
@lcobucci lcobucci Use microtime to have more precision on cache time 9df3dd2
@lcobucci lcobucci Evict query cache when entities are updated 2a320f2
@lcobucci lcobucci Add timestamp key to QueryCacheKey fd15d7d
@lcobucci lcobucci The timestamp verification is now done by the validator
So it's useless to keep it here too.
9130d8c
@Ocramius Ocramius added a commit that referenced this pull request Sep 8, 2016
@Ocramius Ocramius #6001 documenting minor BC break in `QueryCacheEntry#time` type - spe…
…cific version used
5e702ad
@Ocramius Ocramius added a commit that referenced this pull request Sep 8, 2016
@Ocramius Ocramius #6001 adding `orderBy`, `limit` and `offset` variables (defined in `m…
…aster`, not in `2.5`)
3e57c46
@Ocramius Ocramius added a commit that referenced this pull request Sep 8, 2016
@Ocramius Ocramius Merge branch 'fix/#6001-second-level-cache-query-cache-timestamp-from…
…-region-2.5' into 2.5

Close #6001
e16de70
@Ocramius Ocramius self-assigned this Sep 8, 2016
@Ocramius Ocramius added this to the 2.5.5 milestone Sep 8, 2016
@Ocramius Ocramius added a commit that referenced this pull request Sep 8, 2016
@Ocramius Ocramius #6001 documenting minor BC break in `QueryCacheEntry#time` type - spe…
…cific version used
d27cffa
@Ocramius Ocramius closed this in 009e947 Sep 8, 2016
@Ocramius
Member
Ocramius commented Sep 8, 2016

This goes into 2.5.5! Thanks @lcobucci

master: doctrine/doctrine2@009e947
2.5: doctrine/doctrine2@e16de70

@lcobucci lcobucci deleted the lcobucci:fix/l2c-querycache branch Sep 8, 2016
@yvoyer yvoyer added a commit to yvoyer/doctrine2 that referenced this pull request Nov 21, 2016
@Ocramius @yvoyer Ocramius + yvoyer #6001 documenting minor BC break in `QueryCacheEntry#time` type - spe…
…cific version used
95ee378
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment