.NET 6 - _client.InitializeAsync() gets stuck when AutoConnectRealtime = true
BlueWaterCrystal opened this issue · 7 comments
Hi,
When AutoConnectRealtime
is set to true, GetAuthenticationStateAsync
doesn't return as await _client.InitializeAsync()
gets stuck but still authenticates.
However, when a page refreshes and GetAuthenticationStateAsync
is called, it doesn't get stuck.
When AutoConnectRealtime
is set to false, GetAuthenticationStateAsync
returns normally when called from AuthService.
I'm presuming when the page is reloaded, it creates the ClaimsIdentity from the data from supabase it got from before and that's how it's currently authenticating instead of fully authenticating when called from AuthService.
Hello,
I don't think this is a bug, because the AutoConnectRealtime is setted to true in the BlazorWebAssemblySupabaseTemplate and it is working fine.
Furthermore, it could be trick to set the authentication to work ok, because there is a lot going on.
Maybe if you share a sample project of your implementation with this bug, I could help.
Hi,
I meant to add it to Questions.
The code is mostly the same other than being non-webassembly,
I've just tested putting await client.InitializeAsync();
inside the AuthService and it runs correctly, and then GetAuthenticationStateAsync can read the token, though InitializeAsync()
would only execute on login
Not sure how GetAuthenticationStateAsync
can read the session data but not execute InitializeAsync()
Is there something InitializeAsync()
requires that could be missing?
I would like to retract what I said. I just test it a bit more and find that my code on the template isn't work anymore. It was working when I deploy, but now it really get stucked await client.InitializeAsync();
Since the auth code didn't change in the last commits, I need to verify if it is a problem with the Supabase server or if something change in the last updates of the api.
I downgraded the supabase-csharp api to the 0.8.3 version and it worked fine.
Can you try this version @BlueWaterCrystal ?
My csproj file
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0" PrivateAssets="all" />
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
<PackageReference Include="MudBlazor" Version="6.1.2" />
<PackageReference Include="gotrue-csharp" Version="3.0.5" />
<PackageReference Include="postgrest-csharp" Version="3.1.3" />
<PackageReference Include="supabase-csharp" Version="0.8.3" />
</ItemGroup>
<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>
</Project>
Hi,
Version 0.8.3 Seems to fix the issue.
It looks like the core issue is related to realtime-csharp
, anything above 5.0.1 seems to produce the issue.
The error occurs in Client.cs
public Task<IRealtimeClient<RealtimeSocket, RealtimeChannel>> ConnectAsync()
{
var tsc = new TaskCompletionSource<IRealtimeClient<RealtimeSocket, RealtimeChannel>>();
try
{
Connect(tsc.SetResult);
}
catch (Exception ex)
{
tsc.TrySetException(ex);
}
return tsc.Task;
}
It looks like when the socket isn't null, it doesn't send a callback to the ConnectAsync(), invoking the callback seems to fix it.
In 5.0.1 I believe method used to use TrySetResult
Possible fix:
public IRealtimeClient<RealtimeSocket, RealtimeChannel> Connect(Action<IRealtimeClient<RealtimeSocket, RealtimeChannel>>? callback = null)
{
if (socket != null)
{
Options.Logger("error", "Socket already exists.", null);
callback?.Invoke(this);
return this;
}
EventHandler<SocketStateChangedEventArgs>? cb = null;
cb = (object sender, SocketStateChangedEventArgs args) =>
{
switch (args.State)
{
case SocketStateChangedEventArgs.ConnectionState.Open:
socket!.StateChanged -= cb;
callback?.Invoke(this);
break;
case SocketStateChangedEventArgs.ConnectionState.Close:
case SocketStateChangedEventArgs.ConnectionState.Error:
socket!.StateChanged -= cb;
throw new Exception("Error occurred connecting to Socket. Check logs.");
}
};
socket = new RealtimeSocket(realtimeUrl, Options, SerializerSettings);
socket.StateChanged += HandleSocketStateChanged;
socket.OnMessage += HandleSocketMessage;
socket.OnHeartbeat += HandleSocketHeartbeat;
socket.StateChanged += cb;
socket.Connect();
return this;
}
Available in 0.8.7 - Thanks for y'all's help!