Description
I have been following the tutorial for Subscribing to Database Changes with the Swift client. The Swift client does not receive the database messages when triggered (like a record is updated), however, the JS client does receive the database messages.
I believe it's because supabase.realtimeV2.setAuth() does not send JWT credentials to channels because of this guard statement:
guard tokenToSend != mutableState.accessToken else {
return
}
Spelunking session
- Initialize SupabaseClient (
let supabase = SupabaseClient(...)
) - On init, SupabaseClient calls
listenForAuthEvents()
listenForAuthEvents()
callshandleTokenChanged(...)
handleTokenChanges()
callsawait realtimeV2.setAuth(accessToken)
The problem seems to be that since await realtimeV2.setAuth(accessToken)
is called in the initializing of SupabaseClient, it's triggered before we can subscribe to any channels. So if we have code like this:
let channel = supabase.channel("topic:id")
let broadcastStream = channel.broadcastStream(event: "UPDATE")
await channel.subscribe()
await supabase.realtimeV2.setAuth()
Task {
for await message in broadcastStream {
print("Message received", message)
}
The setAuth()
call does not send JWT auth to the channels, because the guard gets kicked in since the accessToken hasn't changed from initializing SupabaseClient:
public func setAuth(_ token: String? = nil) async {
var tokenToSend = token
if tokenToSend == nil {
tokenToSend = try? await options.accessToken?()
}
// 👇 guard kicks in, so the for channel in channels loop never get fired
guard tokenToSend != mutableState.accessToken else {
return
}
mutableState.withValue { [token] in
$0.accessToken = token
}
for channel in channels.values {
if channel.status == .subscribed {
options.logger?.debug("Updating auth token for channel \(channel.topic)")
await channel.push(
ChannelEvent.accessToken,
payload: ["access_token": token.map { .string($0) } ?? .null]
)
}
}
}
Now it's very possible I'm just doing something wrong or completely missed a piece, but it seems like it's impossible to push accessTokens to channels since SupabaseClient sets the accessToken at initialization. Please let me know if I'm off base though and there's another reason!