Doctrine 2 result cache invalidation
Asked Answered
E

2

9

I'm using Doctrine 2's result cache on a query retrieving the number of new messages of a user (messaging app):

$query->useResultCache(true, 500, 'messaging.nb_new_messages.'.$userId);

I tried to invalidate this cache like this (in my entity repository):

public function clearNbNewMessagesOfUserCache($userId) {
    $cacheDriver = $this->getEntityManager()->getConfiguration()->getResultCacheImpl();
    $result  = $cacheDriver->delete('skepin_messaging.nbNewMessages.'.$userId);

    if (!$result) {
        return false;
    }

    return $cacheDriver->flushAll();
}

So that I don't need to make a useless query on each page of my website.

My questions: is that a recommended practice? Will I eventually run into problems?

Eddyede answered 23/6, 2012 at 18:12 Comment(0)
T
2

I had the idea to build an onFlush hook. There you have all entities queued for inserts, updates and deletes hence you can invalidate the caches depending on entity name and identifier etc.

Unfortunately, I have not yet build any event listeners but I definitely plan to build such a thing for my project.

Here is a link to the doctrine documentation for the onFlush event

Edit: There is even an easier way to implement events. In an entity class you can add @HasLifecycleCallbacks to the annotations and than you can define a function with a @PreUpdate or @PrePersist annotation. Than every time this model is updated or persisted this function will be called.

/**
 * @Entity
 * @Table(name="SomeEntity")
 * @HasLifecycleCallbacks
 */
class SomeEntity
{
    ...

    /**
     * @PreUpdate
     * @PrePersist
     */
    public function preUpdate()
    {
        // This function is called every time this model gets updated
        // or a new instance of this model gets persisted

        // Somethink like this maybe... 
        // I have not yet completely thought through all this.
        $cache->save(get_class($this) . '#' . $this->getId(), $this);
    }
}

So maybe this can be used to invalidate every single instance of an entity?

Triangulation answered 28/8, 2012 at 11:0 Comment(0)
E
0

This is an old question I stumbled upon. It's really simple using Doctrine 2.8 nowadays:

/** @var \Psr\Cache\CacheItemPoolInterface|null $cache */
$cache = $em->getConfiguration()->getResultCache();

$cache->deleteItem('skepin_messaging.nbNewMessages.'.$userId);
$cache->clear(); // clear all items

Please be aware that Doctrine internally generates a "real cache key" which won't look like yours. I don't know how to generate that cache key, without re-creating the used query.

Espionage answered 25/5, 2022 at 15:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.