mirror of
https://github.com/ppy/osu.git
synced 2026-06-03 15:54:44 +08:00
Merge pull request #34620 from bdach/reduce-redundant-subscription-triggers
Reduce number of realm subscription triggers from song select online lookups
This commit is contained in:
@@ -700,9 +700,17 @@ namespace osu.Game.Database
|
||||
if (lookupSucceeded)
|
||||
{
|
||||
Debug.Assert(result != null);
|
||||
beatmap.Metadata.UserTags.Clear();
|
||||
beatmap.Metadata.UserTags.AddRange(result.UserTags);
|
||||
return beatmap.Metadata.UserTags.Any();
|
||||
|
||||
var userTags = result.UserTags.ToHashSet();
|
||||
|
||||
if (!userTags.SetEquals(beatmap.Metadata.UserTags))
|
||||
{
|
||||
beatmap.Metadata.UserTags.Clear();
|
||||
beatmap.Metadata.UserTags.AddRange(userTags);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.Log(@$"Could not find {beatmap.GetDisplayString()} in local cache while backpopulating missing user tags");
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@@ -57,46 +58,59 @@ namespace osu.Game.Screens.SelectV2
|
||||
return;
|
||||
}
|
||||
|
||||
var tagsById = (onlineBeatmapSet.RelatedTags ?? []).ToDictionary(t => t.Id);
|
||||
var onlineBeatmaps = onlineBeatmapSet.Beatmaps.ToDictionary(b => b.OnlineID);
|
||||
await realm.WriteAsync(r =>
|
||||
{
|
||||
var beatmapSet = r.All<BeatmapSetInfo>().Where(b => b.OnlineID == id);
|
||||
|
||||
foreach (var dbBeatmapSet in beatmapSet)
|
||||
{
|
||||
dbBeatmapSet.Status = onlineBeatmapSet.Status;
|
||||
|
||||
foreach (var dbBeatmap in dbBeatmapSet.Beatmaps)
|
||||
{
|
||||
if (onlineBeatmaps.TryGetValue(dbBeatmap.OnlineID, out var onlineBeatmap))
|
||||
{
|
||||
// compare `BeatmapUpdaterMetadataLookup`
|
||||
dbBeatmap.OnlineMD5Hash = onlineBeatmap.MD5Hash;
|
||||
dbBeatmap.LastOnlineUpdate = onlineBeatmap.LastUpdated;
|
||||
|
||||
if (dbBeatmap.MatchesOnlineVersion)
|
||||
dbBeatmap.Status = onlineBeatmap.Status;
|
||||
|
||||
string[] userTagsArray = onlineBeatmap.TopTags?
|
||||
.Select(t => (topTag: t, relatedTag: tagsById.GetValueOrDefault(t.TagId)))
|
||||
.Where(t => t.relatedTag != null)
|
||||
// see https://github.com/ppy/osu-web/blob/bb3bd2e7c6f84f26066df5ea20a81c77ec9bb60a/resources/js/beatmapsets-show/controller.ts#L103-L106 for sort criteria
|
||||
.OrderByDescending(t => t.topTag.VoteCount)
|
||||
.ThenBy(t => t.relatedTag!.Name)
|
||||
.Select(t => t.relatedTag!.Name)
|
||||
.ToArray() ?? [];
|
||||
dbBeatmap.Metadata.UserTags.Clear();
|
||||
dbBeatmap.Metadata.UserTags.AddRange(userTagsArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).ConfigureAwait(true);
|
||||
await realm.WriteAsync(r => updateRealmBeatmapSet(r, onlineBeatmapSet)).ConfigureAwait(true);
|
||||
tcs.SetResult(onlineBeatmapSet);
|
||||
};
|
||||
request.Failure += tcs.SetException;
|
||||
api.Queue(request);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
private static void updateRealmBeatmapSet(Realm r, APIBeatmapSet onlineBeatmapSet)
|
||||
{
|
||||
var tagsById = (onlineBeatmapSet.RelatedTags ?? []).ToDictionary(t => t.Id);
|
||||
var onlineBeatmaps = onlineBeatmapSet.Beatmaps.ToDictionary(b => b.OnlineID);
|
||||
|
||||
var dbBeatmapSets = r.All<BeatmapSetInfo>().Where(b => b.OnlineID == onlineBeatmapSet.OnlineID);
|
||||
|
||||
foreach (var dbBeatmapSet in dbBeatmapSets)
|
||||
{
|
||||
// note that every single write to realm models is preceded by a guard, even if it technically would write the same value back.
|
||||
// the reason this matters is that doing so avoids triggering realm subscription callbacks.
|
||||
// unfortunately in terms of subscriptions realm treats *every* write to any realm object as a modification,
|
||||
// even if the write was redundant and had no observable effect.
|
||||
|
||||
if (dbBeatmapSet.Status != onlineBeatmapSet.Status)
|
||||
dbBeatmapSet.Status = onlineBeatmapSet.Status;
|
||||
|
||||
foreach (var dbBeatmap in dbBeatmapSet.Beatmaps)
|
||||
{
|
||||
if (onlineBeatmaps.TryGetValue(dbBeatmap.OnlineID, out var onlineBeatmap))
|
||||
{
|
||||
// compare `BeatmapUpdaterMetadataLookup`
|
||||
if (dbBeatmap.OnlineMD5Hash != onlineBeatmap.MD5Hash)
|
||||
dbBeatmap.OnlineMD5Hash = onlineBeatmap.MD5Hash;
|
||||
|
||||
if (dbBeatmap.LastOnlineUpdate != onlineBeatmap.LastUpdated)
|
||||
dbBeatmap.LastOnlineUpdate = onlineBeatmap.LastUpdated;
|
||||
|
||||
if (dbBeatmap.MatchesOnlineVersion && dbBeatmap.Status != onlineBeatmap.Status)
|
||||
dbBeatmap.Status = onlineBeatmap.Status;
|
||||
|
||||
HashSet<string> userTags = onlineBeatmap.TopTags?
|
||||
.Select(t => (topTag: t, relatedTag: tagsById.GetValueOrDefault(t.TagId)))
|
||||
.Where(t => t.relatedTag != null)
|
||||
.Select(t => t.relatedTag!.Name)
|
||||
.ToHashSet() ?? [];
|
||||
|
||||
if (!userTags.SetEquals(dbBeatmap.Metadata.UserTags))
|
||||
{
|
||||
dbBeatmap.Metadata.UserTags.Clear();
|
||||
dbBeatmap.Metadata.UserTags.AddRange(userTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user