mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 21:02:54 +08:00
Allow realm migration to run again if interrupted halfway
This commit is contained in:
parent
37b74aafcc
commit
66c5d77d63
@ -27,7 +27,9 @@ namespace osu.Game.Database
|
||||
{
|
||||
internal class EFToRealmMigrator : CompositeDrawable
|
||||
{
|
||||
public bool FinishedMigrating { get; private set; }
|
||||
public Task<bool> MigrationCompleted => migrationCompleted.Task;
|
||||
|
||||
private readonly TaskCompletionSource<bool> migrationCompleted = new TaskCompletionSource<bool>();
|
||||
|
||||
[Resolved]
|
||||
private DatabaseContextFactory efContextFactory { get; set; } = null!;
|
||||
@ -99,6 +101,17 @@ namespace osu.Game.Database
|
||||
{
|
||||
using (var ef = efContextFactory.Get())
|
||||
{
|
||||
realmContextFactory.Write(realm =>
|
||||
{
|
||||
// Before beginning, ensure realm is in an empty state.
|
||||
// Migrations which are half-completed could lead to issues if the user tries a second time.
|
||||
// Note that we only do this for beatmaps and scores since the other migrations are yonks old.
|
||||
realm.RemoveAll<BeatmapSetInfo>();
|
||||
realm.RemoveAll<BeatmapInfo>();
|
||||
realm.RemoveAll<BeatmapMetadata>();
|
||||
realm.RemoveAll<ScoreInfo>();
|
||||
});
|
||||
|
||||
migrateSettings(ef);
|
||||
migrateSkins(ef);
|
||||
migrateBeatmaps(ef);
|
||||
@ -114,7 +127,7 @@ namespace osu.Game.Database
|
||||
Logger.Log("Your development database has been fully migrated to realm. If you switch back to a pre-realm branch and need your previous database, rename the backup file back to \"client.db\".\n\nNote that doing this can potentially leave your file store in a bad state.", level: LogLevel.Important);
|
||||
}, TaskCreationOptions.LongRunning).ContinueWith(t =>
|
||||
{
|
||||
FinishedMigrating = true;
|
||||
migrationCompleted.SetResult(true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -149,14 +162,6 @@ namespace osu.Game.Database
|
||||
{
|
||||
log($"Found {count} beatmaps in EF");
|
||||
|
||||
// only migrate data if the realm database is empty.
|
||||
// note that this cannot be written as: `realm.All<BeatmapSetInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
||||
if (realm.All<BeatmapSetInfo>().Any(s => !s.Protected))
|
||||
{
|
||||
log("Skipping migration as realm already has beatmaps loaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
var transaction = realm.BeginWrite();
|
||||
int written = 0;
|
||||
|
||||
@ -229,7 +234,6 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
log($"Successfully migrated {count} beatmaps to realm");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -280,13 +284,6 @@ namespace osu.Game.Database
|
||||
{
|
||||
log($"Found {count} scores in EF");
|
||||
|
||||
// only migrate data if the realm database is empty.
|
||||
if (realm.All<ScoreInfo>().Any())
|
||||
{
|
||||
log("Skipping migration as realm already has scores loaded");
|
||||
}
|
||||
else
|
||||
{
|
||||
var transaction = realm.BeginWrite();
|
||||
int written = 0;
|
||||
|
||||
@ -343,7 +340,6 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
log($"Successfully migrated {count} scores to realm");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -74,11 +74,22 @@ namespace osu.Game.Screens
|
||||
base.OnEntering(last);
|
||||
|
||||
LoadComponentAsync(precompiler = CreateShaderPrecompiler(), AddInternal);
|
||||
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
||||
|
||||
// A non-null context factory means there's still content to migrate.
|
||||
if (efContextFactory != null)
|
||||
{
|
||||
LoadComponentAsync(realmMigrator = new EFToRealmMigrator(), AddInternal);
|
||||
realmMigrator.MigrationCompleted.ContinueWith(_ => Schedule(() =>
|
||||
{
|
||||
// Delay initial screen loading to ensure that the migration is in a complete and sane state
|
||||
// before the intro screen may import the game intro beatmap.
|
||||
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
||||
}
|
||||
|
||||
LoadComponentAsync(spinner = new LoadingSpinner(true, true)
|
||||
{
|
||||
@ -96,7 +107,7 @@ namespace osu.Game.Screens
|
||||
|
||||
private void checkIfLoaded()
|
||||
{
|
||||
if (loadableScreen.LoadState != LoadState.Ready || !precompiler.FinishedCompiling || realmMigrator?.FinishedMigrating == false)
|
||||
if (loadableScreen?.LoadState != LoadState.Ready || !precompiler.FinishedCompiling)
|
||||
{
|
||||
Schedule(checkIfLoaded);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user