commit f4bcf5ee49520c7317b175502c8ddc6c19e14e5f
parent 965ebcaa3d790b9fff69870b35a740767951dd11
Author: Michael Camilleri <[email protected]>
Date: Mon, 27 Jul 2026 13:16:41 +0900
Report the current local lease in open snapshots
The open lease snapshot could report the local player as absent
immediately after minting a new lease because it read the cached
PlayerEntity.presenceUntil. Outgoing local Player records instead derive
presenceUntil from GameEntity.lastReadOtherMoveAt.
This commit reads that same source for the local player while continuing
to report received Player rows for peers, so the diagnostic reflects the
effective leases on both sides.
Co-Authored-By: Codex GPT 5.6 Sol <[email protected]>
Diffstat:
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift
@@ -2614,12 +2614,14 @@ final class AppServices {
)
}
- /// Diagnostic: logs each participant's `Player.presenceUntil` lease for `gameID`
- /// at open, so a lingering peer cursor or engagement room can be reasoned
- /// about from the device log alone — the lease value is otherwise only
- /// visible server-side. One line per player: self/peer, author prefix,
- /// name, the raw `presenceUntil` (UTC), and whether it currently reads as present
- /// (`+Ns` until expiry) or lapsed (`Ns ago`).
+ /// Diagnostic: logs each participant's effective `Player.presenceUntil` lease
+ /// for `gameID` at open, so a lingering peer cursor or engagement room can be
+ /// reasoned about from the device log alone. Peer leases come from their
+ /// received Player rows; the local lease comes from `GameEntity`, matching the
+ /// source `RecordBuilder` writes into the outgoing Player record. One line per
+ /// player: self/peer, author prefix, name, the raw `presenceUntil` (UTC), and
+ /// whether it currently reads as present (`+Ns` until expiry) or lapsed
+ /// (`Ns ago`).
func logPlayerLeaseSnapshot(gameID: UUID) async {
let localAuthorID = identity.currentID
let context = persistence.container.newBackgroundContext()
@@ -2635,7 +2637,10 @@ final class AppServices {
|| (localAuthorID.map { author == $0 } ?? false)
let tag = isLocal ? "self" : "peer"
let name = (player.name?.isEmpty == false) ? player.name! : "—"
- guard let presenceUntil = player.presenceUntil else {
+ let presenceUntil = isLocal
+ ? player.game?.lastReadOtherMoveAt
+ : player.presenceUntil
+ guard let presenceUntil else {
return "\(tag) \(author.prefix(8)) [\(name)] presenceUntil=nil"
}
let delta = Int(presenceUntil.timeIntervalSince(now))