فهرست منبع

Broadcast Hash Deduplication Fix

The hash was being marked as "sent" BEFORE the actual send completed, as getAppStatus callback never fires or is severely delayed
All future broadcasts with same/similar data were blocked :
The hash from 21:40:07 is still stored in lastSentDataHash
Even though it was never actually sent via sendMessage!
So every subsequent call logs "Skipping duplicate broadcast"
Robert 7 ماه پیش
والد
کامیت
360694eead
1فایلهای تغییر یافته به همراه24 افزوده شده و 3 حذف شده
  1. 24 3
      Trio/Sources/Services/WatchManager/GarminManager.swift

+ 24 - 3
Trio/Sources/Services/WatchManager/GarminManager.swift

@@ -1128,9 +1128,6 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
 
 
         lastSentHashLock.lock()
         lastSentHashLock.lock()
         let isDuplicate = (lastSentDataHash == currentHash)
         let isDuplicate = (lastSentDataHash == currentHash)
-        if !isDuplicate {
-            lastSentDataHash = currentHash
-        }
         lastSentHashLock.unlock()
         lastSentHashLock.unlock()
 
 
         if isDuplicate {
         if isDuplicate {
@@ -1138,6 +1135,9 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
             return
             return
         }
         }
 
 
+        // Store hash - will be marked as "sent" only after successful transmission
+        let hashToSend = currentHash
+
         // Update display types in the state before sending (handles cached/throttled data)
         // Update display types in the state before sending (handles cached/throttled data)
         let updatedState = updateDisplayTypesInState(state)
         let updatedState = updateDisplayTypesInState(state)
 
 
@@ -1167,6 +1167,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
             // 1. If it's a datafield, ALWAYS send (no status check)
             // 1. If it's a datafield, ALWAYS send (no status check)
             if isDatafieldApp {
             if isDatafieldApp {
                 debug(.watchManager, "[\(formatTimeForLog())] Garmin: Sending to datafield \(app.uuid!) (no status check)")
                 debug(.watchManager, "[\(formatTimeForLog())] Garmin: Sending to datafield \(app.uuid!) (no status check)")
+                // Store hash to mark as sent on successful send
+                currentSendHash = hashToSend
                 sendMessage(updatedState, to: app)
                 sendMessage(updatedState, to: app)
                 return
                 return
             }
             }
@@ -1193,6 +1195,8 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
                 }
                 }
 
 
                 debug(.watchManager, "[\(self.formatTimeForLog())] Garmin: Sending to watchface \(app.uuid!)")
                 debug(.watchManager, "[\(self.formatTimeForLog())] Garmin: Sending to watchface \(app.uuid!)")
+                // Store hash to mark as sent on successful send
+                self.currentSendHash = hashToSend
                 self.sendMessage(updatedState, to: app)
                 self.sendMessage(updatedState, to: app)
             }
             }
         }
         }
@@ -1330,6 +1334,15 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
         set { triggerLock.withLock { _currentSendTrigger = newValue } }
         set { triggerLock.withLock { _currentSendTrigger = newValue } }
     }
     }
 
 
+    // Track hash of data currently being sent (thread-safe)
+    private let sendHashLock = OSAllocatedUnfairLock()
+    private var _currentSendHash: Int?
+
+    private var currentSendHash: Int? {
+        get { sendHashLock.withLock { _currentSendHash } }
+        set { sendHashLock.withLock { _currentSendHash = newValue } }
+    }
+
     // Track connection health
     // Track connection health
     private var lastSuccessfulSendTime: Date?
     private var lastSuccessfulSendTime: Date?
     private var failedSendCount = 0
     private var failedSendCount = 0
@@ -1372,6 +1385,14 @@ final class BaseGarminManager: NSObject, GarminManager, Injectable, @unchecked S
                     self.failedSendCount = 0
                     self.failedSendCount = 0
                     self.lastSuccessfulSendTime = Date()
                     self.lastSuccessfulSendTime = Date()
                     self.connectionAlertShown = false // Reset alert flag on success
                     self.connectionAlertShown = false // Reset alert flag on success
+
+                    // Mark hash as sent only after successful transmission
+                    if let sentHash = self.currentSendHash {
+                        self.lastSentHashLock.lock()
+                        self.lastSentDataHash = sentHash
+                        self.lastSentHashLock.unlock()
+                    }
+
                     debug(
                     debug(
                         .watchManager,
                         .watchManager,
                         "[\(self.formatTimeForLog())] Garmin: Successfully sent message to \(app.uuid!) [Trigger: \(self.currentSendTrigger)]"
                         "[\(self.formatTimeForLog())] Garmin: Successfully sent message to \(app.uuid!) [Trigger: \(self.currentSendTrigger)]"