fix(fuse,core): idle drain workers no longer spin while offline

Offline or paused, a drain worker claims nothing and then slept until the
earliest queued op fell due. Every queued op was already due and nothing
attempted it, so the wait was zero and all 16 workers spun on the queue
for the whole outage (issue #35: 17 min of CPU in 2 min 16 s).

A worker that claims nothing now sleeps the full idle poll; a reconnect
or resume wakes it. earliest_due_at also uses the claim's exclusions, so
an op held behind a claimed op on the same node no longer counts as due.

docs/BUGS.md B200.
This commit is contained in:
nvrl committed 2026-10-09 11:05:12 +02:00
1 parent 4c498d559c
commit 51d114a8da
4 files changed
+129 -34

No files matched your search

+30
View File
@@ -6547,6 +6547,36 @@ fn an_idle_worker_does_not_wait_on_an_op_another_worker_has() {
);
}
/// B200: a rename queued behind a long upload of the same node is due, but no
/// worker may claim it until the upload retires. Counted as due, it had every
/// idle worker wake at once, find nothing, and go round again.
#[test]
fn earliest_due_at_skips_an_op_held_behind_a_claimed_one() {
let db = Db::open_in_memory().unwrap();
let root = uid("root").to_string();
let mut revision = bulk_op(0, &root);
revision.parent_uid = None;
db.enqueue_op(&revision).unwrap();
db.enqueue_op(&PendingOp {
kind: OP_RENAME.to_string(),
parent_uid: Some(root.clone()),
blob_path: None,
meta_json: None,
..bulk_op(0, &root)
})
.unwrap();
db.claim_next_due_op(10)
.unwrap()
.expect("the revision is due");
assert!(db.claim_next_due_op(10).unwrap().is_none());
assert_eq!(
db.earliest_due_at().unwrap(),
None,
"a row no worker can claim is not work an idle worker is waiting for"
);
}
/// Trashing a photo from the gallery must not leave it behind on an album page:
/// the row goes, its album membership goes with it, and nothing else moves.
#[test]