Skip to content

gridstore iter livelock#7983

Merged
generall merged 2 commits intodevfrom
gridstore-iter-livelock
Jan 26, 2026
Merged

gridstore iter livelock#7983
generall merged 2 commits intodevfrom
gridstore-iter-livelock

Conversation

@generall
Copy link
Member

Currently, there is a livelock problem, which reproduces in the following situation:

  • we have a stream of search requests hitting a collection
  • On the same collection we run create_payload request, which is supposed to create an index for unrelated field

During index building search gets stuck.

Why it happens?

  • For building index we iterate over payload storage, which is currently implemented via gridstore.
  • We read payloads, and everything is good until suddenly it stucks. Why?
  • Flush happes and tries to lock tracker inside gridstore. It is unternally mutable.
  • Flush can't lock the tracker as we have an iterator going on, but it also stays in a queue and prevents incomming requests from reading gridstore.
  • So, everything is waiting on the iterator to finish.

This PR changes behaviour of the iterator, so it doesn't require locking the tracker whole time.
It also includes couple of cosmetic changes

@generall generall requested review from coszio and timvisee and removed request for coszio January 24, 2026 22:06
Comment on lines -536 to -541
self.tracker
.read()
.iter_pointers()
.filter_map(|(point_offset, opt_pointer)| {
opt_pointer.map(|pointer| (point_offset, pointer))
})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this locked tracker for the whole existance of the iterator

}

let old_pointers = tracker.write().write_pending_and_flush(pending_updates)?;
let old_pointers = tracker.write().write_pending(pending_updates);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was waiting for iterator and blocking everything

@qdrant qdrant deleted a comment from coderabbitai bot Jan 26, 2026
length,
} = pointer;

let raw = self.read_from_pages::<true>(page_id, block_offset, length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks sound 👍

I was afraid it could data race where newly incoming data could be written to pages before we read here. But writes require a &mut self, while this holds a &self.

@generall generall merged commit 6404051 into dev Jan 26, 2026
15 checks passed
@generall generall deleted the gridstore-iter-livelock branch January 26, 2026 10:47
IvanPleshkov pushed a commit that referenced this pull request Jan 27, 2026
* granular lock for writing and flushing pending updates in gridstore tracker

* avoid grigstore tracker lock in iterator
generall added a commit that referenced this pull request Feb 9, 2026
* granular lock for writing and flushing pending updates in gridstore tracker

* avoid grigstore tracker lock in iterator
@timvisee timvisee mentioned this pull request Feb 17, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants