5

I have a particular use case where we use a cache warmer to keep a custom resource in cache (/api/the-url/xxx). The cache warming is done with a bash script that is added to the crontab and runs at night.

For this particular use case I want /api/the-url/xxx to stay in cache even if admins flush the cache in the Drupal back-end.

For now I wrote 2 queries:

One query that moves all the /api/the-url/xxx from cached_data to cached_data_temp on flush cache.

/**
 * Copies xxx cache from "cache_data" to "cache_data_temp".
 * @param $cid
 */
public function copyCacheDataToTempDataCache($cid) {
    $select = $this->connection->select('cache_data', 'c');
    $select->fields('c');
    $select->condition('cid', $cid . '%', 'LIKE');
    $query = $this->connection->insert('cache_data_temp')->from($select);
    $query->execute();
}

One query to move all the /api/the-url/xxx from the cached_data_temp after the flush cache.

/**
 * Copies xxx cache from "cache_data_temp" to "cache_data".
 */
public function copyTempCacheToCacheData() {
    // Select query to fetch all rows.
    $select = $this->connection->select('cache_data_temp', 'c');
    $select->fields('c');
    // Insert rows into "cache_data".
    $query = $this->connection->insert('cache_data')->from($select);
    $query->execute();
    // Empty table.
    $this->connection->truncate('cache_data_temp')->execute();
 }

I've implemented hook_cache_flush which implements the following:

/**
 * Implements hook_cache_flush.
 */
function MY_MODULE_cache_flush() {
    // Before cache is cleared, get all CID's that start with route:api/the-url/%
    // And store it in "cache_data_temp" table.
    $manager = Drupal::service('xxx.manager');
    $manager->copyCacheDataToTempDataCache('route:api/the-url/');
}

And to rebuild the cache:

/**
 * Implements hook_rebuild.
 */
function MY_MODULE_rebuild() {
    // On info rebuild, put back all data stored in "cache_data_temp" in cache_data.
    $manager = Drupal::service('xxx.manager');
    $manager->copyTempCacheToCacheData();
}

Technically everything works fine. The data is kept in cache_data on flush (after moving it to the temp table) but it seems the cache is invalidated. What am I missing here?

2

For this use case, you might need to consider another storage instead of cache.

warmer -> cache

warmer -> storage -> cache

storage could be either key value or entity or any other storage you prefer.Check here if you are not sure which one to pick.

This way, your warmed data always persistent in the system and can be purged only by warmer (crontab).

When cache clear happen, you can always fallback to storage.

  • Thank you, this is indeed an option but I still want to figure out why the cache is invalidated and what I'm missing in the above example to make it work. – Fons Vandamme Mar 16 '17 at 7:01
  • I marked your answer as correct. We changed the implementation slightly to work like this: warmer -> storage -> cache Thanks a lot for the information. – Fons Vandamme Mar 22 '17 at 9:18
  • glad to hear it. I can see you voted for this answer, but if you think this is the solution, you can accept it. More info at stackoverflow.com/help/accepted-answer – vijaycs85 Mar 22 '17 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.