@@ -165,14 +165,15 @@ actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol {
165
165
// Placing the actual subscription work in a deferred task and
166
166
// promptly returning the filtered publisher for downstream consumption of all error messages.
167
167
defer {
168
- Task { [ weak self] in
168
+ let task = Task { [ weak self] in
169
169
guard let self = self else { return }
170
170
if !( await self . isConnected) {
171
171
try await connect ( )
172
172
try await waitForState ( . connected)
173
173
}
174
- await self . bindCancellableToConnection ( try await self . startSubscription ( id) )
175
- } . toAnyCancellable. store ( in: & cancellablesBindToConnection)
174
+ await self . storeInConnectionCancellables ( try await self . startSubscription ( id) )
175
+ }
176
+ self . storeInConnectionCancellables ( task. toAnyCancellable)
176
177
}
177
178
178
179
return filterAppSyncSubscriptionEvent ( with: id)
@@ -236,24 +237,29 @@ actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol {
236
237
}
237
238
238
239
private func subscribeToWebSocketEvent( ) async {
239
- await self . webSocketClient. publisher. sink { [ weak self] _ in
240
+ let cancellable = await self . webSocketClient. publisher. sink { [ weak self] _ in
240
241
self ? . log. debug ( " [AppSyncRealTimeClient] WebSocketClient terminated " )
241
242
} receiveValue: { webSocketEvent in
242
243
Task { [ weak self] in
243
- await self ? . onWebSocketEvent ( webSocketEvent)
244
- } . toAnyCancellable. store ( in: & self . cancellables)
244
+ let task = Task { [ weak self] in
245
+ await self ? . onWebSocketEvent ( webSocketEvent)
246
+ }
247
+ await self ? . storeInCancellables ( task. toAnyCancellable)
248
+ }
245
249
}
246
- . store ( in : & cancellables )
250
+ self . storeInCancellables ( cancellable )
247
251
}
248
252
249
253
private func resumeExistingSubscriptions( ) {
250
254
log. debug ( " [AppSyncRealTimeClient] Resuming existing subscriptions " )
251
255
for (id, _) in self . subscriptions {
252
- Task {
256
+ Task { [ weak self ] in
253
257
do {
254
- try await self . startSubscription ( id) . store ( in: & cancellablesBindToConnection)
258
+ if let cancellable = try await self ? . startSubscription ( id) {
259
+ await self ? . storeInConnectionCancellables ( cancellable)
260
+ }
255
261
} catch {
256
- log. debug ( " [AppSyncRealTimeClient] Failed to resume existing subscription with id: ( \( id) ) " )
262
+ Self . log. debug ( " [AppSyncRealTimeClient] Failed to resume existing subscription with id: ( \( id) ) " )
257
263
}
258
264
}
259
265
}
@@ -286,7 +292,7 @@ actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol {
286
292
subject. filter {
287
293
switch $0 {
288
294
case . success( let response) : return response. id == id || response. type == . connectionError
289
- case . failure( let error ) : return true
295
+ case . failure: return true
290
296
}
291
297
}
292
298
. map { result -> AppSyncSubscriptionEvent ? in
@@ -350,10 +356,6 @@ actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol {
350
356
return errors. compactMap ( AppSyncRealTimeRequest . parseResponseError ( error: ) )
351
357
}
352
358
353
- private func bindCancellableToConnection( _ cancellable: AnyCancellable ) {
354
- cancellable. store ( in: & cancellablesBindToConnection)
355
- }
356
-
357
359
}
358
360
359
361
// MARK: - On WebSocket Events
@@ -366,8 +368,11 @@ extension AppSyncRealTimeClient {
366
368
if self . state. value == . connectionDropped {
367
369
log. debug ( " [AppSyncRealTimeClient] reconnecting appSyncClient after connection drop " )
368
370
Task { [ weak self] in
369
- try ? await self ? . connect ( )
370
- } . toAnyCancellable. store ( in: & cancellablesBindToConnection)
371
+ let task = Task { [ weak self] in
372
+ try ? await self ? . connect ( )
373
+ }
374
+ await self ? . storeInConnectionCancellables ( task. toAnyCancellable)
375
+ }
371
376
}
372
377
373
378
case let . disconnected( closeCode, reason) : //
@@ -425,24 +430,37 @@ extension AppSyncRealTimeClient {
425
430
}
426
431
}
427
432
428
- private func monitorHeartBeats( _ connectionAck: JSONValue ? ) {
433
+ func monitorHeartBeats( _ connectionAck: JSONValue ? ) {
429
434
let timeoutMs = connectionAck? . connectionTimeoutMs? . intValue ?? 0
430
435
log. debug ( " [AppSyncRealTimeClient] Starting heart beat monitor with interval \( timeoutMs) ms " )
431
- heartBeats. eraseToAnyPublisher ( )
436
+ let cancellable = heartBeats. eraseToAnyPublisher ( )
432
437
. debounce ( for: . milliseconds( timeoutMs) , scheduler: DispatchQueue . global ( ) )
433
438
. first ( )
434
- . sink ( receiveValue: {
435
- self . log. debug ( " [AppSyncRealTimeClient] KeepAlive timed out, disconnecting " )
439
+ . sink ( receiveValue: { [ weak self ] in
440
+ Self . log. debug ( " [AppSyncRealTimeClient] KeepAlive timed out, disconnecting " )
436
441
Task { [ weak self] in
437
- await self ? . reconnect ( )
438
- } . toAnyCancellable. store ( in: & self . cancellables)
442
+ let task = Task { [ weak self] in
443
+ await self ? . reconnect ( )
444
+ }
445
+ await self ? . storeInCancellables ( task. toAnyCancellable)
446
+ }
439
447
} )
440
- . store ( in : & cancellablesBindToConnection )
448
+ self . storeInConnectionCancellables ( cancellable )
441
449
// start counting down
442
450
heartBeats. send ( ( ) )
443
451
}
444
452
}
445
453
454
+ extension AppSyncRealTimeClient {
455
+ private func storeInCancellables( _ cancellable: AnyCancellable ) {
456
+ self . cancellables. insert ( cancellable)
457
+ }
458
+
459
+ private func storeInConnectionCancellables( _ cancellable: AnyCancellable ) {
460
+ self . cancellablesBindToConnection. insert ( cancellable)
461
+ }
462
+ }
463
+
446
464
extension Publisher where Output == AppSyncRealTimeSubscription . State , Failure == Never {
447
465
func toAppSyncSubscriptionEventStream( ) -> AnyPublisher < AppSyncSubscriptionEvent , Never > {
448
466
self . compactMap { subscriptionState -> AppSyncSubscriptionEvent ? in
0 commit comments