1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:52:53 +08:00

Fix incorrect handling of StartChatRequest in websocket chat client

Fixes this happening on staging:

	[network] 2024-01-29 17:48:24 [verbose]: WebSocketNotificationsClientConnector connected!
	[network] 2024-01-29 17:48:24 [verbose]: WebSocketNotificationsClientConnector connect attempt failed: Can't use WaitSafely from inside an async operation.

I'm not sure how I ever allowed that `.WaitSafely()` to be there. It
did feel rather dangerous but then I must have forgotten and never
noticed it failing. Which is weird because you'd think that would be
caught by testing that chat isn't working but I'm pretty sure that I
tested that chat *was* indeed working.

Anyway now that entire flow is replaced by something that should
hopefully be somewhat more sane? It has a whole retry flow with logging
now which should be more robust than what was there previously (failing
to start to listen to chat events killing the entire websocket
connection for very little good reason).
This commit is contained in:
Bartłomiej Dach 2024-01-29 19:17:39 +01:00
parent 16c06169ed
commit 996ae0ecc1
No known key found for this signature in database

View File

@ -5,9 +5,10 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Logging;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@ -26,22 +27,50 @@ namespace osu.Game.Online.Chat
private readonly INotificationsClient client;
private readonly ConcurrentDictionary<long, Channel> channelsMap = new ConcurrentDictionary<long, Channel>();
private CancellationTokenSource? chatStartCancellationSource;
public WebSocketChatClient(IAPIProvider api)
{
this.api = api;
client = api.NotificationsClient;
client.IsConnected.BindValueChanged(start, true);
client.IsConnected.BindValueChanged(onConnectedChanged, true);
}
private void start(ValueChangedEvent<bool> connected)
private void onConnectedChanged(ValueChangedEvent<bool> connected)
{
if (connected.NewValue)
{
if (!connected.NewValue)
return;
client.MessageReceived += onMessageReceived;
client.SendAsync(new StartChatRequest()).WaitSafely();
attemptToStartChat();
RequestPresence();
}
else
chatStartCancellationSource?.Cancel();
}
private void attemptToStartChat()
{
chatStartCancellationSource?.Cancel();
chatStartCancellationSource = new CancellationTokenSource();
Task.Factory.StartNew(async () =>
{
while (!chatStartCancellationSource.IsCancellationRequested)
{
try
{
await client.SendAsync(new StartChatRequest()).ConfigureAwait(false);
Logger.Log(@"Now listening to websocket chat messages.", LoggingTarget.Network);
chatStartCancellationSource.Cancel();
}
catch (Exception ex)
{
Logger.Log($@"Could not start listening to websocket chat messages: {ex}", LoggingTarget.Network);
await Task.Delay(5000).ConfigureAwait(false);
}
}
}, chatStartCancellationSource.Token);
}
public void RequestPresence()
{
@ -137,7 +166,7 @@ namespace osu.Game.Online.Chat
public void Dispose()
{
client.IsConnected.ValueChanged -= start;
client.IsConnected.ValueChanged -= onConnectedChanged;
client.MessageReceived -= onMessageReceived;
}
}