Skip to content

Commit 2c47695

Browse files
grdsdevclaude
andcommitted
fix(realtime): resolve additional bugs in auth token handling and unsubscribe flow
This commit addresses additional bugs discovered during code review: **Auth Token Handling Bug:** 1. **setAuth() Token Assignment** - Fixed critical bug where wrong variable was assigned to accessToken - Was using input parameter `token` instead of computed `tokenToSend` - This prevented access token callback from being properly stored - Now correctly uses `tokenToSend` which includes callback result 2. **setAuth() Channel Updates** - Fixed sending wrong token to channels during auth updates - Was sending `token` parameter instead of `tokenToSend` - Channels now receive the correct token from callback **Disconnect Cleanup:** 3. **Missing reconnectTask Cancellation** - disconnect() now properly cancels reconnectTask - Prevents reconnect attempts during explicit disconnect **Subscription Improvements:** 4. **Socket Health Check During Retry** - Added socket connection verification after retry delay - Prevents subscription attempts on disconnected socket - Aborts retry loop if socket disconnects during backoff 5. **Unsubscribe Confirmation** - unsubscribe() now waits for server acknowledgment - Ensures clean channel removal before returning - Matches subscribe() behavior of waiting for status change **Impact:** - Fixes auth token not being updated when using callback - Prevents sending stale/incorrect tokens to channels - Cleaner disconnect and unsubscribe flows - More robust subscription retry logic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 376a8fc commit 2c47695

File tree

2 files changed

+15
-3
lines changed

2 files changed

+15
-3
lines changed

Sources/Realtime/RealtimeChannelV2.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
138138

139139
do {
140140
try await _clock.sleep(for: delay)
141+
142+
// Check if socket is still connected after delay
143+
if socket.status != .connected {
144+
logger?.debug(
145+
"Socket disconnected during retry delay for channel '\(topic)', aborting subscription"
146+
)
147+
throw CancellationError()
148+
}
141149
} catch {
142150
// If sleep is cancelled, break out of retry loop
143151
logger?.debug("Subscription retry cancelled for channel '\(topic)'")
@@ -240,6 +248,9 @@ public final class RealtimeChannelV2: Sendable, RealtimeChannelProtocol {
240248
logger?.debug("Unsubscribing from channel \(topic)")
241249

242250
await push(ChannelEvent.leave)
251+
252+
// Wait for server confirmation of unsubscription
253+
_ = await statusChange.first { @Sendable in $0 == .unsubscribed }
243254
}
244255

245256
@available(

Sources/Realtime/RealtimeClientV2.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ public final class RealtimeClientV2: Sendable, RealtimeClientProtocol {
519519
$0.messageTask?.cancel()
520520
$0.heartbeatTask?.cancel()
521521
$0.connectionTask?.cancel()
522+
$0.reconnectTask?.cancel()
522523
$0.pendingHeartbeatRef = nil
523524
$0.sendBuffer = []
524525
$0.conn = nil
@@ -544,16 +545,16 @@ public final class RealtimeClientV2: Sendable, RealtimeClientProtocol {
544545
return
545546
}
546547

547-
mutableState.withValue { [token] in
548-
$0.accessToken = token
548+
mutableState.withValue { [tokenToSend] in
549+
$0.accessToken = tokenToSend
549550
}
550551

551552
for channel in channels.values {
552553
if channel.status == .subscribed {
553554
options.logger?.debug("Updating auth token for channel \(channel.topic)")
554555
await channel.push(
555556
ChannelEvent.accessToken,
556-
payload: ["access_token": token.map { .string($0) } ?? .null]
557+
payload: ["access_token": tokenToSend.map { .string($0) } ?? .null]
557558
)
558559
}
559560
}

0 commit comments

Comments
 (0)