commit a08b60856f1386c13aacb1f564214c9486e9dd76
parent 89e85099e3d7809eb1953b191e5b45d2dcb74860
Author: Michael Camilleri <[email protected]>
Date: Wed, 13 May 2026 04:29:16 +0900
Kick sendChanges() on player, game and delete enqueues
enqueueMoves and enqueuePing already trail their state.add with an explicit
Task { try? await engine.sendChanges() } because, as the comment on
enqueueMoves explains, repeated state.add calls against the same CKRecord.ID
get coalesced by the framework's scheduler and can sit in the queue for a
noticeable while before going out. enqueuePlayerRecord, enqueueGame and
enqueueDeleteGame had the same shape but no kick — selection updates re-target
the same player record on every cursor move and hit exactly the same trap, and
game create / update / delete fan out from one-shot user actions where waiting
on the scheduler is pure latency.
All three now match the existing pattern. PlayerSelectionPublisher's 300ms
debounce upstream still coalesces cursor bursts, so the change just hands
each debounced burst to CloudKit immediately instead of letting it idle.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Diffstat:
1 file changed, 3 insertions(+), 0 deletions(-)
diff --git a/Crossmate/Sync/SyncEngine.swift b/Crossmate/Sync/SyncEngine.swift
@@ -300,6 +300,7 @@ actor SyncEngine {
let engine = deletion.databaseScope == 1 ? sharedEngine : privateEngine
guard let engine else { return }
engine.state.add(pendingDatabaseChanges: [.deleteZone(zoneID)])
+ Task { try? await engine.sendChanges() }
}
/// Registers a Ping record as a pending send. Pings cover session-start,
@@ -420,6 +421,7 @@ actor SyncEngine {
let recordName = RecordSerializer.recordName(forPlayerInGame: gameID, authorID: authorID)
let recordID = CKRecord.ID(recordName: recordName, zoneID: info.zoneID)
engine.state.add(pendingRecordZoneChanges: [.saveRecord(recordID)])
+ Task { try? await engine.sendChanges() }
}
/// Registers a Game record as a pending send and ensures its zone is
@@ -434,6 +436,7 @@ actor SyncEngine {
engine.state.add(pendingDatabaseChanges: [.saveZone(CKRecordZone(zoneID: info.zoneID))])
let recordID = CKRecord.ID(recordName: ckRecordName, zoneID: info.zoneID)
engine.state.add(pendingRecordZoneChanges: [.saveRecord(recordID)])
+ Task { try? await engine.sendChanges() }
}
// MARK: - Explicit sync triggers (called by AppServices / diagnostics view)