Conversation
|
The lock order change in However, I think the added test can be removed, since it does not actually test any observable behaviors of the component in question (but does add a test hook to the production code and depends on an undocumented, unstable internal debug API). I personally consider locking order invariants an internal detail of the implementation that's more appropriately checked by TSan/fuzzing/stress testing rather than a unit test, so just having a proper documented rationale in the code should suffice. Also, a question:
What is the actual observed effects of an operation getting "stranded" in the queue? My empirical expectation of such an edge case is that it would most likely cause the search core and the content layer bucket states to get out of sync, but not cause any noticeable stalls as per se. The sync issue could remain until the next process restart (at which point all bucket state is reloaded from the search core), but it's also likely that the sending distributor process is usually able to observe the inconsistency and silently trigger a repair almost immediately. That would explain why this edge case has been present for such a long time. I'll allow myself to quote a poignant observation from the 2007 Google paper "Paxos Made Live - An Engineering Perspective" 🙂
|
you are right the stranded is overstated. As your noted the impact is over stated, the distributor may detect and repair this, and a restart would rebuild the bucket DB from Proton. Very true—“fault-tolerant systems try to mask problems” captures this case well. Deterministic simulation and fault injection may at least help expose these otherwise silent failures. |
38c1278 to
0fccfa5
Compare
I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.
A feed operation checks that its source bucket exists and schedules the operation while holding the bucket DB entry lock. Previously, join remapped queued operations before acquiring this lock to remove the source bucket.
This left a window where a feed operation could be scheduled after the queue remap but before the source bucket was removed. The operation would then be stranded in the queue for a bucket that no longer existed in the bucket DB.
The join path now acquires the source bucket DB entry lock before remapping queued operations and holds it until the source entry has been removed. This ensures that a concurrent feed operation either:
This also makes the join path consistent with the existing split lock ordering.