From 2423bbb776bb0fd5042693684cd2e57ac7f3eff8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 Jul 2024 15:28:35 +0900 Subject: [PATCH] Ensure realm subscriptions always fire initial callback with null `ChangeSet` We expect this to be the case, but it turns out that it [may be coalesced](https://www.mongodb.com/docs/realm-sdks/dotnet/latest/reference/Realms.IRealmCollection-1.html#Realms_IRealmCollection_1_SubscribeForNotifications_Realms_NotificationCallbackDelegate__0__Realms_KeyPathsCollection_): > Notifications are delivered via the standard event loop, and so can't > be delivered while the event loop is blocked by other activity. When > notifications can't be delivered instantly, multiple notifications may > be coalesced into a single notification. This can include the > notification with the initial collection. Rather than struggle with handling this locally every time, let's fix the callback at our end to ensure we receive the initial null case. I've raised concern for the API being a bit silly with realm (https://github.com/realm/realm-dotnet/issues/3641). --- osu.Game/Database/RealmObjectExtensions.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/RealmObjectExtensions.cs b/osu.Game/Database/RealmObjectExtensions.cs index 72529ed9ff7c..bd8c52bb8549 100644 --- a/osu.Game/Database/RealmObjectExtensions.cs +++ b/osu.Game/Database/RealmObjectExtensions.cs @@ -65,7 +65,8 @@ public static class RealmObjectExtensions if (!d.Beatmaps.Contains(existingBeatmap)) { Debug.Fail("Beatmaps should never become detached under normal circumstances. If this ever triggers, it should be investigated further."); - Logger.Log("WARNING: One of the difficulties in a beatmap was detached from its set. Please save a copy of logs and report this to devs.", LoggingTarget.Database, LogLevel.Important); + Logger.Log("WARNING: One of the difficulties in a beatmap was detached from its set. Please save a copy of logs and report this to devs.", LoggingTarget.Database, + LogLevel.Important); d.Beatmaps.Add(existingBeatmap); } @@ -291,7 +292,21 @@ public static IDisposable QueryAsyncWithNotifications(this IRealmCollection + { + if (initial) + { + initial = false; + + // Realm might coalesce the initial callback, meaning we never receive a `ChangeSet` of `null` marking the first callback. + // Let's decouple it for simplicity in handling. + if (changes != null) + callback(sender, null); + } + + callback(sender, changes); + })); } ///