mirror of
https://github.com/osukey/osukey.git
synced 2025-06-25 05:07:59 +09:00
Merge pull request #18731 from peppy/database-migration-reliability
Fix database migration potentially hard crashing during backup process without informing the user why
This commit is contained in:
commit
73ec43338a
@ -151,7 +151,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
Logger.Log($"Creating full EF database backup at {backupFilename}", LoggingTarget.Database);
|
Logger.Log($"Creating full EF database backup at {backupFilename}", LoggingTarget.Database);
|
||||||
|
|
||||||
using (var source = storage.GetStream(DATABASE_NAME))
|
using (var source = storage.GetStream(DATABASE_NAME, mode: FileMode.Open))
|
||||||
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
||||||
source.CopyTo(destination);
|
source.CopyTo(destination);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,28 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private void beginMigration()
|
private void beginMigration()
|
||||||
{
|
{
|
||||||
|
const string backup_folder = "backups";
|
||||||
|
|
||||||
|
string backupSuffix = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
||||||
|
|
||||||
|
// required for initial backup.
|
||||||
|
var realmBlockOperations = realm.BlockAllOperations();
|
||||||
|
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
realm.CreateBackup(Path.Combine(backup_folder, $"client.{backupSuffix}.realm"), realmBlockOperations);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Above call will dispose of the blocking token when done.
|
||||||
|
// Clean up here so we don't accidentally dispose twice.
|
||||||
|
realmBlockOperations = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
efContextFactory.CreateBackup(Path.Combine(backup_folder, $"client.{backupSuffix}.db"));
|
||||||
|
|
||||||
using (var ef = efContextFactory.Get())
|
using (var ef = efContextFactory.Get())
|
||||||
{
|
{
|
||||||
realm.Write(r =>
|
realm.Write(r =>
|
||||||
@ -182,7 +202,6 @@ namespace osu.Game.Database
|
|||||||
true);
|
true);
|
||||||
|
|
||||||
const string attachment_filename = "attach_me.zip";
|
const string attachment_filename = "attach_me.zip";
|
||||||
const string backup_folder = "backups";
|
|
||||||
|
|
||||||
var backupStorage = storage.GetStorageForDirectory(backup_folder);
|
var backupStorage = storage.GetStorageForDirectory(backup_folder);
|
||||||
|
|
||||||
@ -209,6 +228,9 @@ namespace osu.Game.Database
|
|||||||
// If we were to not do this, the migration would run another time the next time the user starts the game.
|
// If we were to not do this, the migration would run another time the next time the user starts the game.
|
||||||
deletePreRealmData();
|
deletePreRealmData();
|
||||||
|
|
||||||
|
// If something went wrong and the disposal token wasn't invoked above, ensure it is here.
|
||||||
|
realmBlockOperations?.Dispose();
|
||||||
|
|
||||||
migrationCompleted.SetResult(true);
|
migrationCompleted.SetResult(true);
|
||||||
efContextFactory.SetMigrationCompletion();
|
efContextFactory.SetMigrationCompletion();
|
||||||
});
|
});
|
||||||
|
@ -750,9 +750,9 @@ namespace osu.Game.Database
|
|||||||
private string? getRulesetShortNameFromLegacyID(long rulesetId) =>
|
private string? getRulesetShortNameFromLegacyID(long rulesetId) =>
|
||||||
efContextFactory?.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName;
|
efContextFactory?.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName;
|
||||||
|
|
||||||
public void CreateBackup(string backupFilename)
|
public void CreateBackup(string backupFilename, IDisposable? blockAllOperations = null)
|
||||||
{
|
{
|
||||||
using (BlockAllOperations())
|
using (blockAllOperations ?? BlockAllOperations())
|
||||||
{
|
{
|
||||||
Logger.Log($"Creating full realm database backup at {backupFilename}", LoggingTarget.Database);
|
Logger.Log($"Creating full realm database backup at {backupFilename}", LoggingTarget.Database);
|
||||||
|
|
||||||
@ -762,7 +762,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var source = storage.GetStream(Filename))
|
using (var source = storage.GetStream(Filename, mode: FileMode.Open))
|
||||||
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew))
|
||||||
source.CopyTo(destination);
|
source.CopyTo(destination);
|
||||||
return;
|
return;
|
||||||
|
@ -235,28 +235,6 @@ namespace osu.Game
|
|||||||
|
|
||||||
Decoder.RegisterDependencies(RulesetStore);
|
Decoder.RegisterDependencies(RulesetStore);
|
||||||
|
|
||||||
// Backup is taken here rather than in EFToRealmMigrator to avoid recycling realm contexts
|
|
||||||
// after initial usages below. It can be moved once a direction is established for handling re-subscription.
|
|
||||||
// See https://github.com/ppy/osu/pull/16547 for more discussion.
|
|
||||||
if (EFContextFactory != null)
|
|
||||||
{
|
|
||||||
const string backup_folder = "backups";
|
|
||||||
|
|
||||||
string migration = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
|
|
||||||
|
|
||||||
EFContextFactory.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.db"));
|
|
||||||
realm.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.realm"));
|
|
||||||
|
|
||||||
using (var source = Storage.GetStream("collection.db"))
|
|
||||||
{
|
|
||||||
if (source != null)
|
|
||||||
{
|
|
||||||
using (var destination = Storage.CreateFileSafely(Path.Combine(backup_folder, $"collection.{migration}.db")))
|
|
||||||
source.CopyTo(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies.CacheAs(Storage);
|
dependencies.CacheAs(Storage);
|
||||||
|
|
||||||
var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures")));
|
var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures")));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user