The scenario is a bit complicated and does (I think) require custom code, but I’d say this should still work well in the Search API – and currently doesn’t. Steps to reproduce:

  1. Create an index with “Index items immediately” enabled.
  2. Use a custom datasource that ignores some items/entities based on their properties. E.g., this could be a datasource that only tracks published items.
  3. Perform some action that, in a single page request, will track an item first as updated, and then as deleted, by the datasource.
  4. (For testing purposes, you can also replace the previous two steps by manually calling first Index::trackItemsUpdated() and then Index::trackItemsDeleted() on the same item(s).)
  5. The expected result here would, of course, be that the item is missing from both the tracking table and the server.
  6. Actually, however, it will only be missing from the tracking table, but still be on the server. The reason for this is that the delete from the server happens immediately when tracking it, while the indexing operation is only queued when the update is tracked and happens via PostRequestIndexing, at the end of the page request. Therefore, the update “overwrites” the delete.

As said, the setup is quite complicated, and probably rare, but I still think this qualifies as a bug in the Search API: when you track the deletion of an item, you wouldn’t expect it to be indexed afterwards.

As a side note, the reason this cannot happen with our own Content Entity datasource (as far as I can see) is that this only discards items based on their type or language. Since the type is immutable and the language is part of the ID (and not really a regular property at all, I’d say), the scenario described here cannot happen. (Except when changing the datasource settings and updating an item twice, all in the same page request.)

Comments

drunken monkey created an issue. See original summary.

drunken monkey’s picture

Status: Active » Needs review
StatusFileSize
new3.96 KB

This should fix the problem: when tracking the deletion of an item, also remove it from the PostRequestIndexing queue.

drunken monkey’s picture

Status: Needs review » Needs work
drunken monkey’s picture

Status: Needs work » Needs review
andriy khomych’s picture

Status: Needs review » Reviewed & tested by the community

Hey Thomas. I've tested this patch locally and it fixed the issue for my test case.
Moving it to RTBC.

  • drunken monkey committed a1604fd5 on 8.x-1.x
    Issue #3325206 by drunken monkey: Fixed bug when an item is first...
drunken monkey’s picture

Status: Reviewed & tested by the community » Fixed

Good to hear, thanks a lot for testing.
Merged. Thanks again!

andriy khomych’s picture

Thank you, Thomas!

Status: Fixed » Closed (fixed)

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

andriy khomych’s picture

Hey Thomas :)
I've now faced another issue when we have multiple tracking/untracking/tracking/untracking/tracking/untracking in the same request
it can end up with a tracking entity that should be untracked and stored with tracked status (which is incorrect).
What about queueing tracking calls and executing the latest one after the actual request finishes? E.g. by using https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drup...