1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 03:27:24 +08:00

Add recovery logic after disconnection

This commit is contained in:
Dean Herbert 2022-07-04 17:49:08 +09:00
parent d217d66852
commit b0d4f7aff6

View File

@ -1,10 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Client;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game.Online.API; using osu.Game.Online.API;
@ -16,6 +17,8 @@ namespace osu.Game.Online.Metadata
private IHubClientConnector? connector; private IHubClientConnector? connector;
private uint? lastQueueId;
private HubConnection? connection => connector?.CurrentConnection; private HubConnection? connection => connector?.CurrentConnection;
public OnlineMetadataClient(EndpointConfiguration endpoints) public OnlineMetadataClient(EndpointConfiguration endpoints)
@ -38,18 +41,78 @@ namespace osu.Game.Online.Metadata
// https://github.com/dotnet/aspnetcore/issues/15198 // https://github.com/dotnet/aspnetcore/issues/15198
connection.On<BeatmapUpdates>(nameof(IMetadataClient.BeatmapSetsUpdated), ((IMetadataClient)this).BeatmapSetsUpdated); connection.On<BeatmapUpdates>(nameof(IMetadataClient.BeatmapSetsUpdated), ((IMetadataClient)this).BeatmapSetsUpdated);
}; };
connector.IsConnected.BindValueChanged(isConnectedChanged, true);
} }
} }
public override Task BeatmapSetsUpdated(BeatmapUpdates updates) private bool catchingUp;
private void isConnectedChanged(ValueChangedEvent<bool> connected)
{
if (!connected.NewValue)
return;
if (lastQueueId != null)
{
catchingUp = true;
Task.Run(async () =>
{
try
{
while (true)
{
Logger.Log($"Requesting catch-up from {lastQueueId.Value}");
var catchUpChanges = await GetChangesSince(lastQueueId.Value);
lastQueueId = catchUpChanges.LastProcessedQueueID;
if (catchUpChanges.BeatmapSetIDs.Length == 0)
{
Logger.Log($"Catch-up complete at {lastQueueId.Value}");
break;
}
await ProcessChanges(catchUpChanges.BeatmapSetIDs);
}
}
finally
{
catchingUp = false;
}
});
}
}
public override async Task BeatmapSetsUpdated(BeatmapUpdates updates)
{ {
Logger.Log($"Received beatmap updates {updates.BeatmapSetIDs.Length} updates with last id {updates.LastProcessedQueueID}"); Logger.Log($"Received beatmap updates {updates.BeatmapSetIDs.Length} updates with last id {updates.LastProcessedQueueID}");
// If we're still catching up, avoid updating the last ID as it will interfere with catch-up efforts.
if (!catchingUp)
lastQueueId = updates.LastProcessedQueueID;
await ProcessChanges(updates.BeatmapSetIDs);
}
protected Task ProcessChanges(int[] beatmapSetIDs)
{
foreach (int id in beatmapSetIDs)
Logger.Log($"Processing {id}...");
return Task.CompletedTask; return Task.CompletedTask;
} }
public override Task<BeatmapUpdates> GetChangesSince(uint queueId) public override Task<BeatmapUpdates> GetChangesSince(uint queueId)
{ {
throw new NotImplementedException(); if (connector?.IsConnected.Value != true)
return Task.FromCanceled<BeatmapUpdates>(default);
Logger.Log($"Requesting any changes since last known queue id {queueId}");
Debug.Assert(connection != null);
return connection.InvokeAsync<BeatmapUpdates>(nameof(IMetadataServer.GetChangesSince), queueId);
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)