1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-03 19:22:56 +08:00

Merge pull request #31509 from bdach/local-metadata-cache-corruption

Refetch local metadata cache if corruption is detected
This commit is contained in:
Dean Herbert 2025-01-23 02:43:14 +09:00 committed by GitHub
commit bf23c67603
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 20 deletions

View File

@ -113,6 +113,31 @@ namespace osu.Game.Beatmaps
return queryCacheVersion2(db, beatmapInfo, out onlineMetadata);
}
}
onlineMetadata = null;
return false;
}
catch (SqliteException sqliteException)
{
onlineMetadata = null;
// There have been cases where the user's local database is corrupt.
// Let's attempt to identify these cases and re-initialise the local cache.
switch (sqliteException.SqliteErrorCode)
{
case 26: // SQLITE_NOTADB
case 11: // SQLITE_CORRUPT
// only attempt purge & re-download if there is no other refetch in progress
if (cacheDownloadRequest != null)
return false;
tryPurgeCache();
prepareLocalCache();
return false;
}
logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo} failed with unhandled sqlite error {sqliteException}.");
return false;
}
catch (Exception ex)
{
@ -120,9 +145,22 @@ namespace osu.Game.Beatmaps
onlineMetadata = null;
return false;
}
}
onlineMetadata = null;
return false;
private void tryPurgeCache()
{
log(@"Local metadata cache is corrupted; attempting purge.");
try
{
File.Delete(storage.GetFullPath(cache_database_name));
}
catch (Exception ex)
{
log($@"Failed to purge local metadata cache: {ex}");
}
log(@"Local metadata cache purged due to corruption.");
}
private SqliteConnection getConnection() =>

View File

@ -11,7 +11,6 @@ using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Development;
using osu.Framework.Extensions;
@ -414,18 +413,7 @@ namespace osu.Game.Database
/// Compact this realm.
/// </summary>
/// <returns></returns>
public bool Compact()
{
try
{
return Realm.Compact(getConfiguration());
}
// Catch can be removed along with entity framework. Is specifically to allow a failure message to arrive to the user (see similar catches in EFToRealmMigrator).
catch (AggregateException ae) when (RuntimeInfo.OS == RuntimeInfo.Platform.macOS && ae.Flatten().InnerException is TypeInitializationException)
{
return true;
}
}
public bool Compact() => Realm.Compact(getConfiguration());
/// <summary>
/// Run work on realm with a return value.
@ -721,11 +709,6 @@ namespace osu.Game.Database
return Realm.GetInstance(getConfiguration());
}
// Catch can be removed along with entity framework. Is specifically to allow a failure message to arrive to the user (see similar catches in EFToRealmMigrator).
catch (AggregateException ae) when (RuntimeInfo.OS == RuntimeInfo.Platform.macOS && ae.Flatten().InnerException is TypeInitializationException)
{
return Realm.GetInstance();
}
finally
{
if (tookSemaphoreLock)