From 4b349ba38738fbf862acccaeb43e6954782f6ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 23 Sep 2024 11:53:32 +0200 Subject: [PATCH] Use cache for beatmap lookups on spectate screen @peppy noticed recently that attempting to spectate just a few users was very likely to end up in requests very quickly being rejected with code 429 ("Too Many Requests"). I'm somewhat certain that the reason for that is that a significant number of players is wont to retry a lot in quick succession. That means that spectator server is going to note a lot of gameplay start and end messages in quick succession, too. And as it turns out, every gameplay start would end up triggering a new beatmap set fetch request: https://github.com/ppy/osu/blob/ccf1acce56798497edfaf92d3ece933469edcf0a/osu.Game/Screens/Spectate/SpectatorScreen.cs#L131-L134 https://github.com/ppy/osu/blob/ccf1acce56798497edfaf92d3ece933469edcf0a/osu.Game/Screens/Play/SoloSpectatorScreen.cs#L168-L172 https://github.com/ppy/osu/blob/ccf1acce56798497edfaf92d3ece933469edcf0a/osu.Game/Screens/Play/SoloSpectatorScreen.cs#L243-L256 To attempt to curtail that, use the beatmap cache instead, which should prevent these unnecessary requests from firing in the first place, therefore reducing the chance of the client getting throttled. This technically means that a different endpoint is used to fetch the data (`GET /beatmaps/?ids[]=` rather than `GET /beatmapsets/lookup?beatmap_id={id}`), but docs claim that both should return the same data, and it looks to work fine in practice. --- osu.Game/Screens/Play/SoloSpectatorScreen.cs | 26 +++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/SoloSpectatorScreen.cs b/osu.Game/Screens/Play/SoloSpectatorScreen.cs index 95eb2d4376..269bc3bb92 100644 --- a/osu.Game/Screens/Play/SoloSpectatorScreen.cs +++ b/osu.Game/Screens/Play/SoloSpectatorScreen.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,12 +14,11 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; using osu.Game.Overlays; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play public partial class SoloSpectatorScreen : SpectatorScreen, IPreviewTrackOwner { [Resolved] - private IAPIProvider api { get; set; } = null!; + private BeatmapLookupCache beatmapLookupCache { get; set; } = null!; [Resolved] private PreviewTrackManager previewTrackManager { get; set; } = null!; @@ -60,7 +60,7 @@ public partial class SoloSpectatorScreen : SpectatorScreen, IPreviewTrackOwner /// private SpectatorGameplayState? immediateSpectatorGameplayState; - private GetBeatmapSetRequest? onlineBeatmapRequest; + private ScheduledDelegate? beatmapFetchCallback; private APIBeatmapSet? beatmapSet; @@ -210,7 +210,7 @@ private void resetStartState() => Schedule(() => private void clearDisplay() { watchButton.Enabled.Value = false; - onlineBeatmapRequest?.Cancel(); + beatmapFetchCallback?.Cancel(); beatmapPanelContainer.Clear(); previewTrackManager.StopAnyPlaying(this); } @@ -244,15 +244,17 @@ private void showBeatmapPanel(SpectatorState state) { Debug.Assert(state.BeatmapID != null); - onlineBeatmapRequest = new GetBeatmapSetRequest(state.BeatmapID.Value, BeatmapSetLookupType.BeatmapId); - onlineBeatmapRequest.Success += beatmapSet => Schedule(() => + beatmapLookupCache.GetBeatmapAsync(state.BeatmapID.Value).ContinueWith(t => beatmapFetchCallback = Schedule(() => { - this.beatmapSet = beatmapSet; - beatmapPanelContainer.Child = new BeatmapCardNormal(this.beatmapSet, allowExpansion: false); - checkForAutomaticDownload(); - }); + var beatmap = t.GetResultSafely(); - api.Queue(onlineBeatmapRequest); + if (beatmap?.BeatmapSet == null) + return; + + beatmapSet = beatmap.BeatmapSet; + beatmapPanelContainer.Child = new BeatmapCardNormal(beatmapSet, allowExpansion: false); + checkForAutomaticDownload(); + })); } private void checkForAutomaticDownload()