Skip to content

Commit bae91a6

Browse files
authored
Merge pull request #286 from synonymdev/fix/backup-client
fix: prevent channel monitor loss when remote backup fails
2 parents 960d8f5 + daa2a04 commit bae91a6

File tree

3 files changed

+39
-54
lines changed

3 files changed

+39
-54
lines changed

lib/android/src/main/java/com/reactnativeldk/classes/LdkPersister.kt

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,12 @@ class LdkPersister {
2323

2424
val isNew = !file.exists()
2525

26-
if (BackupClient.skipRemoteBackup) {
27-
file.writeBytes(data.write())
28-
if (isNew) {
29-
LdkEventEmitter.send(EventTypes.new_channel, body)
30-
}
31-
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed
32-
}
33-
34-
BackupClient.addToPersistQueue(BackupClient.Label.CHANNEL_MONITOR(channelId=channelId), data.write()) { error ->
35-
if (error != null) {
36-
LdkEventEmitter.send(EventTypes.native_log, "Failed to persist channel (${channelId}) to remote backup: $error")
37-
return@addToPersistQueue
38-
}
39-
40-
try {
41-
file.writeBytes(data.write())
42-
} catch (e: Exception) {
43-
//If this fails we can't do much but LDK will retry on startup
44-
LdkEventEmitter.send(EventTypes.native_log, "Failed to locally persist channel (${channelId}) to disk")
45-
return@addToPersistQueue
46-
}
26+
// Always write locally first
27+
val serialized = data.write()
28+
file.writeBytes(serialized)
4729

48-
//Update chain monitor with successful persist
30+
// Update chain monitor on main thread to avoid threading issues
31+
LdkModule.reactContext?.runOnUiThread {
4932
val res = LdkModule.chainMonitor?.channel_monitor_updated(channelFundingOutpoint, data._latest_update_id)
5033
if (res == null || !res.is_ok) {
5134
LdkEventEmitter.send(EventTypes.native_log, "Failed to update chain monitor with persisted channel (${channelId})")
@@ -57,7 +40,16 @@ class LdkPersister {
5740
}
5841
}
5942

60-
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_InProgress
43+
// Kick off remote backup asynchronously; never block/skip local persist
44+
if (!BackupClient.skipRemoteBackup) {
45+
BackupClient.addToPersistQueue(BackupClient.Label.CHANNEL_MONITOR(channelId=channelId), serialized) { error ->
46+
if (error != null) {
47+
LdkEventEmitter.send(EventTypes.native_log, "Failed to persist channel (${channelId}) to remote backup: $error")
48+
}
49+
}
50+
}
51+
52+
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed
6153
} catch (e: Exception) {
6254
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_UnrecoverableError
6355
}

lib/ios/Classes/LdkPersist.swift

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,17 @@ class LdkPersister: Persist {
2727
}
2828

2929
let isNew = !FileManager().fileExists(atPath: channelStoragePath.path)
30-
31-
// If we're not remotely backing up no need to update status later
32-
if BackupClient.skipRemoteBackup {
33-
try Data(data.write()).write(to: channelStoragePath)
34-
if isNew {
35-
LdkEventEmitter.shared.send(withEvent: .new_channel, body: body)
36-
}
37-
return ChannelMonitorUpdateStatus.Completed
38-
}
39-
40-
BackupClient.addToPersistQueue(.channelMonitor(id: channelIdHex), data.write()) { error in
41-
if let error {
42-
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed persist channel on remote server (\(channelIdHex)). \(error.localizedDescription)")
43-
return
44-
}
45-
46-
// Callback for when the persist queue queue entry is processed
47-
do {
48-
try Data(data.write()).write(to: channelStoragePath)
49-
} catch {
50-
// If this fails we can't do much but LDK will retry on startup
51-
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to locally persist channel (\(channelIdHex)). \(error.localizedDescription)")
52-
return
53-
}
54-
55-
// Update chainmonitor with successful persist
56-
let res = Ldk.chainMonitor?.channelMonitorUpdated(fundingTxo: channelFundingOutpoint, completedUpdateId: data.getLatestUpdateId())
30+
31+
// Always write locally first
32+
let serialized = Data(data.write())
33+
try serialized.write(to: channelStoragePath)
34+
35+
// Notify chain monitor on main thread to avoid threading issues
36+
DispatchQueue.main.async {
37+
let res = Ldk.chainMonitor?.channelMonitorUpdated(
38+
fundingTxo: channelFundingOutpoint,
39+
completedUpdateId: data.getLatestUpdateId()
40+
)
5741
if let error = res?.getError() {
5842
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to update chain monitor for channel (\(channelIdHex)) Error \(error.getValueType()).")
5943
} else {
@@ -63,10 +47,19 @@ class LdkPersister: Persist {
6347
}
6448
}
6549
}
66-
67-
return ChannelMonitorUpdateStatus.InProgress
50+
51+
// Kick off remote backup asynchronously; log but never block/skip local persist
52+
if !BackupClient.skipRemoteBackup {
53+
BackupClient.addToPersistQueue(.channelMonitor(id: channelIdHex), [UInt8](serialized)) { error in
54+
if let error {
55+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed persist channel on remote server (\(channelIdHex)). \(error.localizedDescription)")
56+
}
57+
}
58+
}
59+
60+
return ChannelMonitorUpdateStatus.Completed
6861
} catch {
69-
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist channel (\(channelIdHex)) to disk Error \(error.localizedDescription).")
62+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to locally persist channel (\(channelIdHex)). \(error.localizedDescription)")
7063
return ChannelMonitorUpdateStatus.UnrecoverableError
7164
}
7265
}

lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@synonymdev/react-native-ldk",
33
"title": "React Native LDK",
4-
"version": "0.0.160",
4+
"version": "0.0.161",
55
"description": "React Native wrapper for LDK",
66
"main": "./dist/index.js",
77
"types": "./dist/index.d.ts",

0 commit comments

Comments
 (0)