crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 0bc11f38b39306bad211020566e1eec5e4668814
parent 5457ecc814ab8992aff63b3ef8653cfd1bac73a4
Author: Michael Camilleri <[email protected]>
Date:   Mon, 25 May 2026 06:12:14 +0900

Wrap puzzle teardown in a Player send burst

The open path brackets its three Player enqueues — readCursor(activeLease),
name-open, and the initial cursor track — in beginPlayerSendBurst /
endPlayerSendBurst so they collapse into one CKSyncEngine drain. The teardown
path issues two enqueues on the same Player record (clear-cursor via
selectionPublisher.clear() and close-lease via publishReadCursor with mode
currentTime) but did not, so every puzzle close paid two round trips where one
would do.

This commit brackets the teardown sequence in onDisappear the same way the open
path brackets its fan-out. The Moves flush stays outside the burst — it doesn't
touch the Player record and shouldn't gate the lease close on Moves drainage.

Co-Authored-By: Claude Opus 4.7 <[email protected]>

Diffstat:
MCrossmate/CrossmateApp.swift | 9+++++++++
1 file changed, 9 insertions(+), 0 deletions(-)

diff --git a/Crossmate/CrossmateApp.swift b/Crossmate/CrossmateApp.swift @@ -580,11 +580,20 @@ private struct PuzzleDisplayView: View { NotificationState.clearActivePuzzleID(if: gameID) let selectionPublisher = services.playerSelectionPublisher let movesUpdater = services.movesUpdater + let syncEngine = services.syncEngine let id = gameID Task { await movesUpdater.flush() + // Mirror the open-burst pattern: the clear-cursor and + // close-lease enqueues both target the same Player record, + // so wrap them in a player send burst to collapse the two + // CKSyncEngine drains into one. + let burstScope = await syncEngine.beginPlayerSendBurst(gameID: id) await selectionPublisher.clear() await services.publishReadCursor(for: id, mode: .currentTime) + if let burstScope { + await syncEngine.endPlayerSendBurst(scope: burstScope) + } } } }