mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 10:12:54 +08:00
Fix realm refetch operations potentially being unsafe
As seen in test failure https://github.com/ppy/osu/runs/6357384721?check_suite_focus=true.
This commit is contained in:
parent
87f6f74795
commit
33f024212f
@ -344,6 +344,26 @@ namespace osu.Game.Database
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write changes to realm.
|
||||
/// </summary>
|
||||
/// <param name="action">The work to run.</param>
|
||||
public T Write<T>(Func<Realm, T> action)
|
||||
{
|
||||
if (ThreadSafety.IsUpdateThread)
|
||||
{
|
||||
total_writes_update.Value++;
|
||||
return Realm.Write(action);
|
||||
}
|
||||
else
|
||||
{
|
||||
total_writes_async.Value++;
|
||||
|
||||
using (var realm = getRealmInstance())
|
||||
return realm.Write(action);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write changes to realm.
|
||||
/// </summary>
|
||||
|
@ -45,11 +45,16 @@ namespace osu.Game.Stores
|
||||
// This method should be removed as soon as all the surrounding pieces support non-detached operations.
|
||||
if (!item.IsManaged)
|
||||
{
|
||||
var managed = Realm.Realm.Find<TModel>(item.ID);
|
||||
managed.Realm.Write(() => operation(managed));
|
||||
// Importantly, begin the realm write *before* re-fetching, else the update realm may not be in a consistent state
|
||||
// (ie. if an async import finished very recently).
|
||||
Realm.Realm.Write(realm =>
|
||||
{
|
||||
var managed = Realm.Realm.Find<TModel>(item.ID);
|
||||
operation(managed);
|
||||
|
||||
item.Files.Clear();
|
||||
item.Files.AddRange(managed.Files.Detach());
|
||||
item.Files.Clear();
|
||||
item.Files.AddRange(managed.Files.Detach());
|
||||
});
|
||||
}
|
||||
else
|
||||
operation(item);
|
||||
@ -165,7 +170,9 @@ namespace osu.Game.Stores
|
||||
|
||||
public bool Delete(TModel item)
|
||||
{
|
||||
return Realm.Run(realm =>
|
||||
// Importantly, begin the realm write *before* re-fetching, else the update realm may not be in a consistent state
|
||||
// (ie. if an async import finished very recently).
|
||||
return Realm.Write(realm =>
|
||||
{
|
||||
if (!item.IsManaged)
|
||||
item = realm.Find<TModel>(item.ID);
|
||||
@ -173,14 +180,16 @@ namespace osu.Game.Stores
|
||||
if (item?.DeletePending != false)
|
||||
return false;
|
||||
|
||||
realm.Write(r => item.DeletePending = true);
|
||||
item.DeletePending = true;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void Undelete(TModel item)
|
||||
{
|
||||
Realm.Run(realm =>
|
||||
// Importantly, begin the realm write *before* re-fetching, else the update realm may not be in a consistent state
|
||||
// (ie. if an async import finished very recently).
|
||||
Realm.Write(realm =>
|
||||
{
|
||||
if (!item.IsManaged)
|
||||
item = realm.Find<TModel>(item.ID);
|
||||
@ -188,7 +197,7 @@ namespace osu.Game.Stores
|
||||
if (item?.DeletePending != true)
|
||||
return;
|
||||
|
||||
realm.Write(r => item.DeletePending = false);
|
||||
item.DeletePending = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user