fix(crypto): wait for the rebuilt client to publish, and say so when we stop #144
No reviewers
Labels
No labels
blocked
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
waiting-on-julian
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jlxq0/matrix-mcp!144
Loading…
Reference in a new issue
No description provided.
Delete branch "publish-wait"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The heal wiped the store, rebuilt the client and re-checked 531 ms later, then reported "device keys still not published after rebuild".
A rebuilt client publishes from the background sync loop, not from
for_user, so at 531 ms nothing could have happened. The device had in fact published: averify_statushours later answered normally, and Synapse's row count for that device went0at 12:25:13Z to1at 16:13:10Z. The failure the code reported was its own impatience. For scale, a healthy client on this deployment takes 1.19 s from build to first tool call with no publication in that path.That timing is an inference, not something the rows record. Two samples four hours apart cannot say the 16:08 rebuild published them rather than something in between, and the entry says so.
The wait
wait_for_publishpolls the observable with a ceiling instead of checking once. Polling rather than sleeping, because the original fault was a single check at a single moment and a fixed sleep is that fault with a larger constant. It is a free function over a closure so the loop is testable without a homeserver.Expiredis deliberately notNotPublished. At the ceiling we know only that we stopped asking. Reporting that as the keys are not published is precisely the confusion this cost an evening: a slow not yet read as a never. The log line says the wait expired and that the next call will look again.The ceiling is chosen, not derived, and the comment says which. 531 ms is known too short because it is what failed; the 1.19 s figure measures something else. Neither is the publish latency, and measuring that means wiping a live store.
The second negative no longer raises
The first version errored, and
verify_statusbegan failing where it had answeredcross_signed: false— an unknown converted into an outage. It now returns the client withkeys_verifiedstill false, so a late publish is picked up next call without another wipe.Mutations
Not covered
refused_second_healhas still never run. The live sequence took the race branch, and a working discriminator is not coverage of the path it did not exercise.Gates: fmt, clippy
-D warnings,312 passed; 0 failed, audit clean, deny ok.Merging, with one gap named rather than fixed. 312 passed here on 1.98.0 from
ci.yml, and I ran the call-site mutation.The wait is tested as a function and nothing holds that it is called. Third repository in two days:
jmap-mcp#30hadvalidate_send_bodies(¶ms)?deleted with 187 green,m365-mcp#28hadset_issuer(&issuers)reverted with 95 green.Why this one merges where
m365-mcp#28was held. Deleting the call there restored the outage exactly. Deleting it here leavesOk(rebuilt): no wait and no check, which is not the original defect.keys_verifiedstays false and the next call re-checks, so the failure mode of the untested wiring is a slower heal rather than a false failure report. The value that made this urgent, no longer erroring where it used to answer, survives the mutation.The call site needs a live homeserver and
for_user_inner, which is thejmap-mcp#31situation. File it as its own issue with this mutation in it, and say in the issue that the mutation does not reproduce the original defect, so nobody reads it as more urgent than it is.What I checked rather than took
The ceiling is declared chosen and both bounding numbers are named with what they are not. 531 ms known too short because it is what failed; 1.19 s build-to-first-call with no publication in the path; neither is the publish latency; the latency unmeasured because measuring it means wiping a live store. A number with its derivation absent and that absence stated is worth more than a number with a derivation invented.
Expiredis notNotPublishedand the log line says the wait expired and the next call will look again. At the ceiling that is the only true statement available.Not raising on the second negative is what stops this repeating the
verify_statusoutage, and the comment says so where thereturn Errused to be.The one about you
Committing through a red clippy twice in a day, then fixing forward rather than amending so a force push did not spend one of his approvals, is the right trade and the right thing to have said. Chaining the gates with
&&fixes the cause rather than the instance.refused_second_healstill never having run is stated, and it is the sentence that stops a working discriminator being read as coverage.