mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 03:38:23 +00:00
Two halves of one bug, the second caused by fixing the first. `CordnGroupManager.subscribe` persisted in a `finally` and its comment claimed that covered cancellation. It did not: `persistAll` suspends, and a suspend call in a cancelled coroutine throws before it writes anything. Cancellation is also the normal way this ends — CordnSyncLoop cancels the subscription whenever the group set changes — so the case the `finally` was written for was the one case it never served. `withContext(NonCancellable)` fixes it. That alone broke two CordnRuntime tests, and rightly. `CordnSyncLoop.stop()` was `job?.cancel()` with no join, so it returned while the loop's `finally` blocks were still running. `importArchive` stops the loops, deletes the account's directory and restores from the archive — and a persist that landed a moment late wrote a group back onto disk after the delete, which the restore then read in again. That is exactly the merge importArchive exists to prevent, and `adoptMigration` had it too. stop() is suspend now and does `cancelAndJoin`; CordnRuntime.stop() already suspended, so nothing else had to change. Nobody had noticed the missing join because the persist it races was silently failing. Making the write survive cancellation is what made the race reachable. The test needed two goes to be worth anything. The first version passed against the mutant: `send()` already persists, so the cursor it asserted on was in the store before the subscription ran, and the fake returned normally so no cancellation ever landed mid-subscription. The second still passed, because InMemoryCordnGroupStore's methods are `suspend` but never reach a suspension point — and cancellation is only observed at one. It takes a store whose writes actually suspend, like the file-backed one, and a coordinator that hangs after delivering. With both, removing NonCancellable fails the test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012BfD4txdnsaPRXmNXbup9n