Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 47 additions & 9 deletions Bitkit/Services/MigrationsService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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: \(error)",
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")
Expand All @@ -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")
Expand Down
Loading