@@ -34,6 +34,11 @@ class LightningNodeService {
3434 var network : Network
3535 var server : EsploraServer
3636 var lsp : LightningServiceProvider
37+ private var eventListenerTask : Task < Void , Never > ?
38+
39+ deinit {
40+ cancelEventListenerTask ( )
41+ }
3742
3843 init (
3944 keyService: KeyClient = . live
@@ -195,11 +200,59 @@ class LightningNodeService {
195200 }
196201 }
197202
203+ private static func existingInstance( ) -> LightningNodeService ? {
204+ lock. lock ( )
205+ let instance = _shared
206+ lock. unlock ( )
207+ return instance
208+ }
209+
210+ static func stopAndReleaseShared( ) throws {
211+ guard let instance = existingInstance ( ) else { return }
212+ do {
213+ try instance. stop ( )
214+ } catch let error as NodeError {
215+ if case . NotRunning = error {
216+ instance. cancelEventListenerTask ( )
217+ } else {
218+ throw error
219+ }
220+ }
221+ stopTrackingSharedInstance ( )
222+ }
223+
224+ static func rebuildShared( keyService: KeyClient ) throws -> LightningNodeService {
225+ if let instance = existingInstance ( ) {
226+ do {
227+ try instance. stop ( )
228+ } catch let error as NodeError {
229+ if case . NotRunning = error {
230+ instance. cancelEventListenerTask ( )
231+ } else {
232+ throw error
233+ }
234+ }
235+ }
236+
237+ let service = LightningNodeService ( keyService: keyService)
238+ lock. lock ( )
239+ _shared = service
240+ lock. unlock ( )
241+ return service
242+ }
243+
244+ private static func stopTrackingSharedInstance( ) {
245+ lock. lock ( )
246+ _shared = nil
247+ lock. unlock ( )
248+ }
249+
198250 func start( ) async throws {
199251 try ldkNode. start ( )
200252 }
201253
202254 func stop( ) throws {
255+ cancelEventListenerTask ( )
203256 try ldkNode. stop ( )
204257 }
205258
@@ -211,8 +264,11 @@ class LightningNodeService {
211264 }
212265
213266 func reset( ) throws {
214- if LightningNodeService . shared. status ( ) . isRunning {
215- try LightningNodeService . shared. stop ( )
267+ if let instance = LightningNodeService . existingInstance ( ) {
268+ if instance. status ( ) . isRunning {
269+ try instance. stop ( )
270+ }
271+ instance. cancelEventListenerTask ( )
216272 }
217273
218274 // Clean up wallet data to prevent conflicts on next initialization
@@ -223,7 +279,7 @@ class LightningNodeService {
223279
224280 try ? FileManager . default. removeItem ( atPath: networkPath)
225281
226- LightningNodeService . _shared = nil
282+ LightningNodeService . stopTrackingSharedInstance ( )
227283 }
228284
229285 func nodeId( ) -> String {
@@ -390,14 +446,17 @@ extension LightningNodeService {
390446
391447extension LightningNodeService {
392448 func listenForEvents( ) {
393- Task {
394- while true {
395- let event = await ldkNode. nextEventAsync ( )
449+ eventListenerTask? . cancel ( )
450+ eventListenerTask = Task { [ weak self] in
451+ guard let self else { return }
452+ while !Task. isCancelled {
453+ let event = await self . ldkNode. nextEventAsync ( )
454+ if Task . isCancelled { break }
396455 NotificationCenter . default. post (
397456 name: . ldkEventReceived,
398457 object: event
399458 )
400- try ? ldkNode. eventHandled ( )
459+ try ? self . ldkNode. eventHandled ( )
401460 }
402461 }
403462 }
@@ -407,6 +466,13 @@ extension LightningNodeService {
407466 }
408467}
409468
469+ extension LightningNodeService {
470+ fileprivate func cancelEventListenerTask( ) {
471+ eventListenerTask? . cancel ( )
472+ eventListenerTask = nil
473+ }
474+ }
475+
410476extension LightningNodeService {
411477 func save( mnemonic: Mnemonic ) throws {
412478 let backupInfo = BackupInfo (
0 commit comments