1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-16 02:12:51 +08:00
Files
osu-lazer/osu.Game/Database/BeatmapLookupCache.cs
T
Bartłomiej Dach 553c20397a Do not cache null values in beatmap lookup cache (#37456)
RFC.

The reason I'm bringing this up is
https://github.com/ppy/osu/issues/37383.

In this case, the retrieval of the beatmap failed on a timeout:

```
2026-04-19 02:43:10 [verbose]: Request to https://osu.ppy.sh/api/v2/beatmaps/?ids[]=5090069 failed with System.Net.WebException: Request to https://osu.ppy.sh/api/v2/beatmaps/?ids[]=5090069 timed out after 10 seconds idle (read 0 bytes, retried 0 times)..
2026-04-19 02:43:10 [verbose]: Failing request osu.Game.Online.API.Requests.GetBeatmapsRequest (System.Net.WebException: Request to https://osu.ppy.sh/api/v2/beatmaps/?ids[]=5090069 timed out after 10 seconds idle (read 0 bytes, retried 0 times).)
```

```
2026-04-19 02:43:10 [error]: Failed to load beatmap 5090069 for playlistItem 0.
2026-04-19 02:43:10 [verbose]: ⚠️ Failed to load beatmap 5090069 for playlistItem 0.
```

This fails at


https://github.com/ppy/osu/blob/0e9664bfdfa69b4b26ff9cf84615c4b83a195a0e/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Card/RankedPlayCard.cs#L167-L171

Just this failing wouldn't cause the game to soft-lock; when I suppress
the lookup locally, the game continues as normal. *However*, suppressing
the lookup is not the same as the lookup *failing*, because a failed
lookup will write a null to the cache, which means that when a beatmap
download is initiated later in


https://github.com/ppy/osu/blob/1b488949e13568c23faa0d88b18c8036f4a7dbc8/osu.Game/Screens/OnlinePlay/Matchmaking/Match/ScreenMatchmaking.cs#L308-L320

it'll just do nothing and the user will be stuck, even though they could
very well attempt to download the beatmap here if the lookup were to
succeed on the second go.

To a degree changing the whole cache for this could be viewed as the
tail wagging the dog, but I think in general caching nulls here seems
pretty anti-user. From within the client I would generally not expect
very many complete misses when looking up beatmaps.

Note that this wouldn't soft-lock the match anymore since
https://github.com/ppy/osu-server-spectator/pull/471. It's just another
step in making degradation less impactful.
2026-04-21 22:12:50 +09:00

38 lines
1.8 KiB
C#

// 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.
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Database
{
public partial class BeatmapLookupCache : OnlineLookupCache<int, APIBeatmap, GetBeatmapsRequest>
{
protected override bool CacheNullValues => false;
/// <summary>
/// Perform an API lookup on the specified beatmap, populating a <see cref="APIBeatmap"/> model.
/// </summary>
/// <param name="beatmapId">The beatmap to lookup.</param>
/// <param name="token">An optional cancellation token.</param>
/// <returns>The populated beatmap, or null if the beatmap does not exist or the request could not be satisfied.</returns>
public Task<APIBeatmap?> GetBeatmapAsync(int beatmapId, CancellationToken token = default) => LookupAsync(beatmapId, token);
/// <summary>
/// Perform an API lookup on the specified beatmaps, populating a <see cref="APIBeatmap"/> model.
/// </summary>
/// <param name="beatmapIds">The beatmaps to lookup.</param>
/// <param name="token">An optional cancellation token.</param>
/// <returns>The populated beatmaps. May include null results for failed retrievals.</returns>
public Task<APIBeatmap?[]> GetBeatmapsAsync(int[] beatmapIds, CancellationToken token = default) => LookupAsync(beatmapIds, token);
protected override GetBeatmapsRequest CreateRequest(IEnumerable<int> ids) => new GetBeatmapsRequest(ids.ToArray());
protected override IEnumerable<APIBeatmap>? RetrieveResults(GetBeatmapsRequest request) => request.Response?.Beatmaps;
}
}