Logging overhaul
This commit is contained in:
@@ -12,10 +12,27 @@ class SyncService: ObservableObject {
|
||||
@Published var isOfflineMode = false
|
||||
|
||||
private let userDefaults = UserDefaults.standard
|
||||
private let logTag = "SyncService"
|
||||
private var syncTask: Task<Void, Never>?
|
||||
private var pendingChanges = false
|
||||
private let syncDebounceDelay: TimeInterval = 2.0
|
||||
|
||||
private func logDebug(_ message: @autoclosure () -> String) {
|
||||
AppLogger.debug(message(), tag: logTag)
|
||||
}
|
||||
|
||||
private func logInfo(_ message: @autoclosure () -> String) {
|
||||
AppLogger.info(message(), tag: logTag)
|
||||
}
|
||||
|
||||
private func logWarning(_ message: @autoclosure () -> String) {
|
||||
AppLogger.warning(message(), tag: logTag)
|
||||
}
|
||||
|
||||
private func logError(_ message: @autoclosure () -> String) {
|
||||
AppLogger.error(message(), tag: logTag)
|
||||
}
|
||||
|
||||
private enum Keys {
|
||||
static let serverURL = "sync_server_url"
|
||||
static let authToken = "sync_auth_token"
|
||||
@@ -201,7 +218,7 @@ class SyncService: ObservableObject {
|
||||
return false
|
||||
}
|
||||
|
||||
print(
|
||||
logInfo(
|
||||
"iOS DELTA SYNC: Sending gyms=\(modifiedGyms.count), problems=\(modifiedProblems.count), sessions=\(modifiedSessions.count), attempts=\(modifiedAttempts.count), deletions=\(modifiedDeletions.count)"
|
||||
)
|
||||
|
||||
@@ -244,7 +261,7 @@ class SyncService: ObservableObject {
|
||||
let decoder = JSONDecoder()
|
||||
let deltaResponse = try decoder.decode(DeltaSyncResponse.self, from: data)
|
||||
|
||||
print(
|
||||
logInfo(
|
||||
"iOS DELTA SYNC: Received gyms=\(deltaResponse.gyms.count), problems=\(deltaResponse.problems.count), sessions=\(deltaResponse.sessions.count), attempts=\(deltaResponse.attempts.count), deletions=\(deltaResponse.deletedItems.count)"
|
||||
)
|
||||
|
||||
@@ -270,7 +287,7 @@ class SyncService: ObservableObject {
|
||||
let allDeletions = dataManager.getDeletedItems() + response.deletedItems
|
||||
let uniqueDeletions = Array(Set(allDeletions))
|
||||
|
||||
print(
|
||||
logInfo(
|
||||
"iOS DELTA SYNC: Applying \(uniqueDeletions.count) deletion records before merging data"
|
||||
)
|
||||
applyDeletionsToDataManager(deletions: uniqueDeletions, dataManager: dataManager)
|
||||
@@ -298,10 +315,10 @@ class SyncService: ObservableObject {
|
||||
_ = try imageManager.saveImportedImage(imageData, filename: consistentFilename)
|
||||
imagePathMapping[serverFilename] = consistentFilename
|
||||
} catch SyncError.imageNotFound {
|
||||
print("Image not found on server: \(serverFilename)")
|
||||
logInfo("Image not found on server: \(serverFilename)")
|
||||
continue
|
||||
} catch {
|
||||
print("Failed to download image \(serverFilename): \(error)")
|
||||
logInfo("Failed to download image \(serverFilename): \(error)")
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -436,7 +453,7 @@ class SyncService: ObservableObject {
|
||||
) async throws {
|
||||
guard !modifiedProblems.isEmpty else { return }
|
||||
|
||||
print("iOS DELTA SYNC: Syncing images for \(modifiedProblems.count) modified problems")
|
||||
logInfo("iOS DELTA SYNC: Syncing images for \(modifiedProblems.count) modified problems")
|
||||
|
||||
for backupProblem in modifiedProblems {
|
||||
guard
|
||||
@@ -465,9 +482,9 @@ class SyncService: ObservableObject {
|
||||
}
|
||||
|
||||
try await uploadImage(filename: consistentFilename, imageData: imageData)
|
||||
print("Uploaded modified problem image: \(consistentFilename)")
|
||||
logInfo("Uploaded modified problem image: \(consistentFilename)")
|
||||
} catch {
|
||||
print("Failed to upload image \(consistentFilename): \(error)")
|
||||
logInfo("Failed to upload image \(consistentFilename): \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,7 +566,7 @@ class SyncService: ObservableObject {
|
||||
|
||||
func syncWithServer(dataManager: ClimbingDataManager) async throws {
|
||||
if isOfflineMode {
|
||||
print("Sync skipped: Offline mode is enabled.")
|
||||
logInfo("Sync skipped: Offline mode is enabled.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -586,7 +603,7 @@ class SyncService: ObservableObject {
|
||||
|
||||
// If both client and server have been synced before, use delta sync
|
||||
if hasLocalData && hasServerData && lastSyncTime != nil {
|
||||
print("iOS SYNC: Using delta sync for incremental updates")
|
||||
logInfo("iOS SYNC: Using delta sync for incremental updates")
|
||||
try await performDeltaSync(dataManager: dataManager)
|
||||
|
||||
// Update last sync time
|
||||
@@ -597,32 +614,32 @@ class SyncService: ObservableObject {
|
||||
|
||||
if !hasLocalData && hasServerData {
|
||||
// Case 1: No local data - do full restore from server
|
||||
print("iOS SYNC: Case 1 - No local data, performing full restore from server")
|
||||
print("Syncing images from server first...")
|
||||
logInfo("iOS SYNC: Case 1 - No local data, performing full restore from server")
|
||||
logInfo("Syncing images from server first...")
|
||||
let imagePathMapping = try await syncImagesFromServer(
|
||||
backup: serverBackup, dataManager: dataManager)
|
||||
print("Importing data after images...")
|
||||
logInfo("Importing data after images...")
|
||||
try importBackupToDataManager(
|
||||
serverBackup, dataManager: dataManager, imagePathMapping: imagePathMapping)
|
||||
print("Full restore completed")
|
||||
logInfo("Full restore completed")
|
||||
} else if hasLocalData && !hasServerData {
|
||||
// Case 2: No server data - upload local data to server
|
||||
print("iOS SYNC: Case 2 - No server data, uploading local data to server")
|
||||
logInfo("iOS SYNC: Case 2 - No server data, uploading local data to server")
|
||||
let currentBackup = createBackupFromDataManager(dataManager)
|
||||
_ = try await uploadData(currentBackup)
|
||||
print("Uploading local images to server...")
|
||||
logInfo("Uploading local images to server...")
|
||||
try await syncImagesToServer(dataManager: dataManager)
|
||||
print("Initial upload completed")
|
||||
logInfo("Initial upload completed")
|
||||
} else if hasLocalData && hasServerData {
|
||||
// Case 3: Both have data - use safe merge strategy
|
||||
print("iOS SYNC: Case 3 - Merging local and server data safely")
|
||||
logInfo("iOS SYNC: Case 3 - Merging local and server data safely")
|
||||
try await mergeDataSafely(
|
||||
localBackup: localBackup,
|
||||
serverBackup: serverBackup,
|
||||
dataManager: dataManager)
|
||||
print("Safe merge completed")
|
||||
logInfo("Safe merge completed")
|
||||
} else {
|
||||
print("No data to sync")
|
||||
logInfo("No data to sync")
|
||||
}
|
||||
|
||||
// Update last sync time
|
||||
@@ -640,7 +657,7 @@ class SyncService: ObservableObject {
|
||||
if let date = formatter.date(from: timestamp) {
|
||||
return Int64(date.timeIntervalSince1970 * 1000)
|
||||
}
|
||||
print("Failed to parse timestamp: \(timestamp), using 0")
|
||||
logInfo("Failed to parse timestamp: \(timestamp), using 0")
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -666,12 +683,12 @@ class SyncService: ObservableObject {
|
||||
imageData, filename: consistentFilename)
|
||||
|
||||
imagePathMapping[serverFilename] = consistentFilename
|
||||
print("Downloaded and mapped image: \(serverFilename) -> \(consistentFilename)")
|
||||
logInfo("Downloaded and mapped image: \(serverFilename) -> \(consistentFilename)")
|
||||
} catch SyncError.imageNotFound {
|
||||
print("Image not found on server: \(serverFilename)")
|
||||
logInfo("Image not found on server: \(serverFilename)")
|
||||
continue
|
||||
} catch {
|
||||
print("Failed to download image \(serverFilename): \(error)")
|
||||
logInfo("Failed to download image \(serverFilename): \(error)")
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -704,18 +721,18 @@ class SyncService: ObservableObject {
|
||||
).path
|
||||
do {
|
||||
try FileManager.default.moveItem(atPath: fullPath, toPath: newPath)
|
||||
print("Renamed local image: \(filename) -> \(consistentFilename)")
|
||||
logInfo("Renamed local image: \(filename) -> \(consistentFilename)")
|
||||
|
||||
// Update problem's image path in memory for consistency
|
||||
} catch {
|
||||
print("Failed to rename local image, using original: \(error)")
|
||||
logInfo("Failed to rename local image, using original: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
try await uploadImage(filename: consistentFilename, imageData: imageData)
|
||||
print("Successfully uploaded image: \(consistentFilename)")
|
||||
logInfo("Successfully uploaded image: \(consistentFilename)")
|
||||
} catch {
|
||||
print("Failed to upload image \(consistentFilename): \(error)")
|
||||
logInfo("Failed to upload image \(consistentFilename): \(error)")
|
||||
// Continue with other images even if one fails
|
||||
}
|
||||
}
|
||||
@@ -733,7 +750,7 @@ class SyncService: ObservableObject {
|
||||
!activeSessionIds.contains($0.sessionId)
|
||||
}
|
||||
|
||||
print(
|
||||
logInfo(
|
||||
"iOS SYNC: Excluding \(dataManager.sessions.count - completedSessions.count) active sessions and \(dataManager.attempts.count - completedAttempts.count) active session attempts from sync"
|
||||
)
|
||||
|
||||
@@ -808,26 +825,26 @@ class SyncService: ObservableObject {
|
||||
let allDeletions = localDeletions + serverBackup.deletedItems
|
||||
let uniqueDeletions = Array(Set(allDeletions))
|
||||
|
||||
print("Merging gyms...")
|
||||
logInfo("Merging gyms...")
|
||||
let mergedGyms = mergeGyms(
|
||||
local: dataManager.gyms,
|
||||
server: serverBackup.gyms,
|
||||
deletedItems: uniqueDeletions)
|
||||
|
||||
print("Merging problems...")
|
||||
logInfo("Merging problems...")
|
||||
let mergedProblems = try mergeProblems(
|
||||
local: dataManager.problems,
|
||||
server: serverBackup.problems,
|
||||
imagePathMapping: imagePathMapping,
|
||||
deletedItems: uniqueDeletions)
|
||||
|
||||
print("Merging sessions...")
|
||||
logInfo("Merging sessions...")
|
||||
let mergedSessions = try mergeSessions(
|
||||
local: dataManager.sessions,
|
||||
server: serverBackup.sessions,
|
||||
deletedItems: uniqueDeletions)
|
||||
|
||||
print("Merging attempts...")
|
||||
logInfo("Merging attempts...")
|
||||
let mergedAttempts = try mergeAttempts(
|
||||
local: dataManager.attempts,
|
||||
server: serverBackup.attempts,
|
||||
@@ -887,7 +904,7 @@ class SyncService: ObservableObject {
|
||||
&& !allDeletedAttemptIds.contains($0.id.uuidString)
|
||||
}
|
||||
|
||||
print(
|
||||
logInfo(
|
||||
"iOS IMPORT: Preserving \(activeSessions.count) active sessions and \(activeAttempts.count) active attempts during import"
|
||||
)
|
||||
|
||||
@@ -977,7 +994,7 @@ class SyncService: ObservableObject {
|
||||
|
||||
// Restore active sessions and their attempts after import
|
||||
for session in activeSessions {
|
||||
print("iOS IMPORT: Restoring active session: \(session.id)")
|
||||
logInfo("iOS IMPORT: Restoring active session: \(session.id)")
|
||||
dataManager.sessions.append(session)
|
||||
if session.id == dataManager.activeSession?.id {
|
||||
dataManager.activeSession = session
|
||||
@@ -997,12 +1014,12 @@ class SyncService: ObservableObject {
|
||||
dataManager.clearDeletedItems()
|
||||
if let data = try? JSONEncoder().encode(backup.deletedItems) {
|
||||
UserDefaults.standard.set(data, forKey: "ascently_deleted_items")
|
||||
print("iOS IMPORT: Imported \(backup.deletedItems.count) deletion records")
|
||||
logInfo("iOS IMPORT: Imported \(backup.deletedItems.count) deletion records")
|
||||
}
|
||||
|
||||
// Update local data state to match imported data timestamp
|
||||
DataStateManager.shared.setLastModified(backup.exportedAt)
|
||||
print("Data state synchronized to imported timestamp: \(backup.exportedAt)")
|
||||
logInfo("Data state synchronized to imported timestamp: \(backup.exportedAt)")
|
||||
|
||||
} catch {
|
||||
throw SyncError.importFailed(error)
|
||||
|
||||
Reference in New Issue
Block a user