From 0267e23185c74a19f058d173b494ea213be2e77b Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 2 Feb 2026 10:57:00 -0300 Subject: [PATCH 1/2] fix: add retry logic and loggin for channel retrieve --- Bitkit/Services/MigrationsService.swift | 56 +++++++++++++++++++++---- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/Bitkit/Services/MigrationsService.swift b/Bitkit/Services/MigrationsService.swift index 4c0c8aa1..9b2c025a 100644 --- a/Bitkit/Services/MigrationsService.swift +++ b/Bitkit/Services/MigrationsService.swift @@ -1915,6 +1915,28 @@ extension MigrationsService { Logger.info("RN remote backup restore completed", context: "Migration") } + private func retrieveChannelMonitorWithRetry( + channelId: String, + maxAttempts: Int = 3, + baseDelayMs: UInt64 = 1000 + ) async -> Data? { + for attempt in 1 ... maxAttempts { + do { + return try await RNBackupClient.shared.retrieveChannelMonitor(channelId: channelId) + } catch { + if attempt < maxAttempts { + let delayMs = baseDelayMs * UInt64(attempt) + Logger.debug( + "Retrying channel monitor retrieval for \(channelId) (attempt \(attempt + 1)/\(maxAttempts)) after \(delayMs)ms", + context: "Migration" + ) + try? await Task.sleep(nanoseconds: delayMs * 1_000_000) + } + } + } + return nil + } + private func fetchRNRemoteLdkData() async { do { let files = try await RNBackupClient.shared.listFiles(fileGroup: "ldk") @@ -1924,28 +1946,44 @@ extension MigrationsService { return } - let monitors = await withTaskGroup(of: Data?.self) { group in - var results: [Data] = [] + let expectedCount = files.channel_monitors.count + let monitorResults = await withTaskGroup(of: (String, Data?).self) { group in + var results: [(String, Data?)] = [] for monitorFile in files.channel_monitors { + let channelId = monitorFile.replacingOccurrences(of: ".bin", with: "") group.addTask { - let channelId = monitorFile.replacingOccurrences(of: ".bin", with: "") - return try? await RNBackupClient.shared.retrieveChannelMonitor(channelId: channelId) + await (channelId, self.retrieveChannelMonitorWithRetry(channelId: channelId)) } } - for await monitor in group { - if let monitor { - results.append(monitor) - } + for await result in group { + results.append(result) } return results } + let failedMonitors = monitorResults.filter { $0.1 == nil }.map(\.0) + if !failedMonitors.isEmpty { + Logger.error( + "Failed to retrieve \(failedMonitors.count)/\(expectedCount) channel monitors after retries: \(failedMonitors.joined(separator: ", "))", + context: "Migration" + ) + } + + let monitors = monitorResults.compactMap(\.1) + + if monitors.count < expectedCount { + Logger.warn( + "Channel monitor count mismatch: expected \(expectedCount), got \(monitors.count). Some channels may not be recoverable.", + context: "Migration" + ) + } + if !monitors.isEmpty { pendingChannelMigration = PendingChannelMigration( channelManager: managerData, channelMonitors: monitors ) - Logger.info("Prepared \(monitors.count) channel monitors for migration", context: "Migration") + Logger.info("Prepared \(monitors.count)/\(expectedCount) channel monitors for migration", context: "Migration") } } catch { Logger.error("Failed to fetch remote LDK data: \(error)", context: "Migration") From 110a34400a7fc901a1d3f53882df8bb492302db9 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Tue, 3 Feb 2026 07:18:58 -0300 Subject: [PATCH 2/2] chore: add error cause to log --- Bitkit/Services/MigrationsService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bitkit/Services/MigrationsService.swift b/Bitkit/Services/MigrationsService.swift index 9b2c025a..9c98318a 100644 --- a/Bitkit/Services/MigrationsService.swift +++ b/Bitkit/Services/MigrationsService.swift @@ -1927,7 +1927,7 @@ extension MigrationsService { if attempt < maxAttempts { let delayMs = baseDelayMs * UInt64(attempt) Logger.debug( - "Retrying channel monitor retrieval for \(channelId) (attempt \(attempt + 1)/\(maxAttempts)) after \(delayMs)ms", + "Retrying channel monitor retrieval for \(channelId) (attempt \(attempt + 1)/\(maxAttempts)) after \(delayMs)ms: \(error)", context: "Migration" ) try? await Task.sleep(nanoseconds: delayMs * 1_000_000)