mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 07:33:20 +08:00
Add helper method for safer realm Find<T>
This commit is contained in:
parent
88295a49aa
commit
6e11162ab1
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
@ -47,13 +48,16 @@ namespace osu.Game.Database
|
|||||||
// This method should be removed as soon as all the surrounding pieces support non-detached operations.
|
// This method should be removed as soon as all the surrounding pieces support non-detached operations.
|
||||||
if (!item.IsManaged)
|
if (!item.IsManaged)
|
||||||
{
|
{
|
||||||
// We use RealmLive here as it handled re-retrieval and refreshing of realm if required.
|
// Importantly, begin the realm write *before* re-fetching, else the update realm may not be in a consistent state
|
||||||
new RealmLive<TModel>(item.ID, Realm).PerformWrite(i =>
|
// (ie. if an async import finished very recently).
|
||||||
|
Realm.Realm.Write(realm =>
|
||||||
{
|
{
|
||||||
operation(i);
|
var managed = realm.FindWithRefresh<TModel>(item.ID);
|
||||||
|
Debug.Assert(managed != null);
|
||||||
|
operation(managed);
|
||||||
|
|
||||||
item.Files.Clear();
|
item.Files.Clear();
|
||||||
item.Files.AddRange(i.Files.Detach());
|
item.Files.AddRange(managed.Files.Detach());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8,6 +8,31 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
public static class RealmExtensions
|
public static class RealmExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Performs a <see cref="Realm.Find{T}(System.Nullable{long})"/>.
|
||||||
|
/// If a match was not found, a <see cref="Realm.Refresh"/> is performed before trying a second time.
|
||||||
|
/// This ensures that an instance is found even if the realm requested against was not in a consistent state.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="realm"></param>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T? FindWithRefresh<T>(this Realm realm, Guid id) where T : IRealmObject
|
||||||
|
{
|
||||||
|
var found = realm.Find<T>(id);
|
||||||
|
|
||||||
|
if (found == null)
|
||||||
|
{
|
||||||
|
// It may be that we access this from the update thread before a refresh has taken place.
|
||||||
|
// To ensure that behaviour matches what we'd expect (the object *is* available), force
|
||||||
|
// a refresh to bring in any off-thread changes immediately.
|
||||||
|
realm.Refresh();
|
||||||
|
found = realm.Find<T>(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a write operation against the provided realm instance.
|
/// Perform a write operation against the provided realm instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -41,24 +41,6 @@ namespace osu.Game.Database
|
|||||||
dataIsFromUpdateThread = ThreadSafety.IsUpdateThread;
|
dataIsFromUpdateThread = ThreadSafety.IsUpdateThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Construct a new instance of live realm data from an ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The ID of an already-persisting realm instance.</param>
|
|
||||||
/// <param name="realm">The realm factory the data was sourced from. May be null for an unmanaged object.</param>
|
|
||||||
public RealmLive(Guid id, RealmAccess realm)
|
|
||||||
: base(id)
|
|
||||||
{
|
|
||||||
data = retrieveFromID(realm.Realm);
|
|
||||||
|
|
||||||
if (data.IsNull())
|
|
||||||
throw new ArgumentException("Realm instance for provided ID could not be found.", nameof(id));
|
|
||||||
|
|
||||||
this.realm = realm;
|
|
||||||
|
|
||||||
dataIsFromUpdateThread = ThreadSafety.IsUpdateThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a read operation on this live object.
|
/// Perform a read operation on this live object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -80,7 +62,7 @@ namespace osu.Game.Database
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
perform(retrieveFromID(r));
|
perform(r.FindWithRefresh<T>(ID)!);
|
||||||
RealmLiveStatistics.USAGE_ASYNC.Value++;
|
RealmLiveStatistics.USAGE_ASYNC.Value++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -102,7 +84,7 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
return realm.Run(r =>
|
return realm.Run(r =>
|
||||||
{
|
{
|
||||||
var returnData = perform(retrieveFromID(r));
|
var returnData = perform(r.FindWithRefresh<T>(ID)!);
|
||||||
RealmLiveStatistics.USAGE_ASYNC.Value++;
|
RealmLiveStatistics.USAGE_ASYNC.Value++;
|
||||||
|
|
||||||
if (returnData is RealmObjectBase realmObject && realmObject.IsManaged)
|
if (returnData is RealmObjectBase realmObject && realmObject.IsManaged)
|
||||||
@ -159,25 +141,10 @@ namespace osu.Game.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataIsFromUpdateThread = true;
|
dataIsFromUpdateThread = true;
|
||||||
data = retrieveFromID(realm.Realm);
|
data = realm.Realm.FindWithRefresh<T>(ID)!;
|
||||||
|
|
||||||
RealmLiveStatistics.USAGE_UPDATE_REFETCH.Value++;
|
RealmLiveStatistics.USAGE_UPDATE_REFETCH.Value++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private T retrieveFromID(Realm realm)
|
|
||||||
{
|
|
||||||
var found = realm.Find<T>(ID);
|
|
||||||
|
|
||||||
if (found == null)
|
|
||||||
{
|
|
||||||
// It may be that we access this from the update thread before a refresh has taken place.
|
|
||||||
// To ensure that behaviour matches what we'd expect (the object *is* available), force
|
|
||||||
// a refresh to bring in any off-thread changes immediately.
|
|
||||||
realm.Refresh();
|
|
||||||
found = realm.Find<T>(ID)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class RealmLiveStatistics
|
internal static class RealmLiveStatistics
|
||||||
|
Loading…
Reference in New Issue
Block a user