Caches (views) are not invalidated on indexing objects.

Created on 4 July 2022, almost 3 years ago
Updated 26 February 2024, about 1 year ago

Problem/Motivation

There is 'search_api_tag' views cache plugin that has unlimited cache lifetime and refreshed only when cachetags are invalidated. It defines 'search_api_list:'.YOUR_INDEX_ID tags.

The problem is it's invalidated now only when deleting items. Of course, your view also has other cachetags and the cache gets refreshed, for example, when you update one of the entities it shows.

Steps to reproduce

  1. Create a view based on Search API index.
  2. Set 'Caching' to 'Search API (tag-based)'.
  3. Check the output as non-admin user.
  4. Add a new entity (node, for example), that should appear in the view.
  5. Check the view output once again.

Expected result: the new entity appears on the list.
Actual result: output is not changed.

Try clearing Drupal caches and check the output once again - you should see the new item on the list.

Proposed resolution

Invalidate 'search_api_list:'.YOUR_INDEX_ID tag on items indexing.

๐Ÿ› Bug report
Status

Fixed

Version

1.0

Component

Framework

Created by

๐Ÿ‡ท๐Ÿ‡ธSerbia SAVEL

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    \Drupal\search_api\Entity\Index::indexSpecificItems() already invalidates that cache tag. Do you know why that doesnโ€™t happen in your case?
    If you can reproduce this problem from a clean site install, with just the necessary modules, it would be great to get a (failing) regression test for it.

  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria
  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ง๐Ÿ‡พBelarus dewalt

    I confirm that cache tag invalidated twice, but the issue with caching could take a place. The cache tags are cleared as a last action in the method (generally as should be), but exception thrown during indexing or results post-processing in $dispatcher->dispatch(new ItemsIndexedEvent($this, $processed_ids), SearchApiEvents::ITEMS_INDEXED); leads that execution stopped and cache tags aren't invalidated.

    In addition if "index_directly" option is enabled, indexing takes place after response was sent. In this way user doesn't see that any error was happened. It could be found in Drupal log, but if it is PHP error (out of memory/time limit), it could be found in server logs only.

    In this way from user viewpoint everything should be done, but cache isn't cleared and outdated results are shown.

    So, this is a question, should the cachetags be invalidated twice before and after indexing, or should try/catch be added (doesn't help on PHP errors), or it is and environment case and generally works as designed.

  • Status changed to Needs review over 1 year ago
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.0.11 + Environment: PHP 8.2 & sqlite-3.34
    last update over 1 year ago
    545 pass
  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Hm, thatโ€™s a good point, seems like that might indeed happen. Of course, any fatal errors occurring during indexing should be investigated and resolved anyways, but itโ€™s true that the search server state might have changed anyways in that case, so the caches must be invalidated nevertheless.

    Patch attached, please test/review. (Iโ€™d still like to keep the cache invalidation in the same method.)

  • Issue was unassigned.
  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Could someone please test/review?

  • ๐Ÿ‡ญ๐Ÿ‡บHungary huzooka Hungary ๐Ÿ‡ญ๐Ÿ‡บ๐Ÿ‡ช๐Ÿ‡บ

    TBH at Index::indexSpecificItems(), I would simply wrap every line from the first one potentially throwing a SearchApiException into a try / finally statement, and move the cache tag invalidation into finally. (So, trusting your judgement, from the line where you add the extra cache tag invalidation now.):

    /**
     * {@inheritdoc}
     */
    public function indexSpecificItems(array $search_objects) {
      if (!$search_objects || $this->read_only) {
        return [];
      }
      ...
      // Remove all items still in $items from $rejected_ids. Thus, only the
      // rejected items' IDs are still contained in $ret, to later be returned
      // along with the successfully indexed ones.
      foreach ($items as $item_id => $item) {
        unset($rejected_ids[$item_id]);
      }
    
      try {
        ...
      }
      finally {
        // Clear search api list caches.
        Cache::invalidateTags($tags_to_invalidate);
      }
    
      // Clear the static entity cache, to avoid running out of memory when
      // indexing lots of items in one process (especially via Drush).
      \Drupal::getContainer()->get('entity.memory_cache')->deleteAll();
    
      return $processed_ids;
    }
    
  • ๐Ÿ‡ญ๐Ÿ‡บHungary huzooka Hungary ๐Ÿ‡ญ๐Ÿ‡บ๐Ÿ‡ช๐Ÿ‡บ

    I think there is a good chance that ๐Ÿ› View recalculated with wrong data from cache Needs review is related to this issue (not because the possibility of the exceptions thrown during indexing, but because of the cache metadata).

    Feel free to remove it from the relations if you disagree.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.1.4 + Environment: PHP 8.2 & sqlite-3.34
    last update over 1 year ago
    Unable to generate test groups
  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Youโ€™re right, using a finally makes more sense here. Invalidating a cache tag might not be super-cheap, so doing it twice is just wasteful.
    Also, I guess this could need a test, which also isnโ€™t that hard to write. So, added that, too.
    Please give it another test/review!

    Based on your description in ๐Ÿ› View recalculated with wrong data from cache Needs review , I donโ€™t think itโ€™s related, but we can still leave the reference in case it helps someone.

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.1.4 + Environment: PHP 8.2 & sqlite-3.34
    last update about 1 year ago
    546 pass
  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 10.1.4 + Environment: PHP 8.2 & sqlite-3.34
    last update about 1 year ago
    545 pass, 1 fail
  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Every single time โ€ฆ

  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Does anyone still want to test/review or is this ready to be merged?

  • Status changed to Fixed about 1 year ago
  • ๐Ÿ‡ฆ๐Ÿ‡นAustria drunken monkey Vienna, Austria

    Merged. Thanks again, everyone!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024