From dac643121ae7f946ededdbcd16f176b099ea1324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 7 Aug 2025 11:09:55 +0200 Subject: [PATCH] Fix metadata cache version queries failing hard if the image is corrupted This was not fatal but with this change it should recover in a slightly better way. Also incidentally fixes the cache refetch potentially being attempted twice by each of the two background population tasks that use it. --- .../Beatmaps/LocalCachedBeatmapMetadataSource.cs | 16 ++++++++++++---- .../Database/BackgroundDataStoreProcessor.cs | 14 +++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs index b759619c06..c591dac36f 100644 --- a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs @@ -238,12 +238,20 @@ namespace osu.Game.Beatmaps }); } - public int GetCacheVersion() + public bool IsAtLeastVersion(int version) { - using (var connection = getConnection()) + try { - connection.Open(); - return getCacheVersion(connection); + using (var connection = getConnection()) + { + connection.Open(); + return getCacheVersion(connection) >= version; + } + } + catch (SqliteException ex) when (ex.SqliteErrorCode == 26 || ex.SqliteErrorCode == 11) // SQLITE_NOTADB, SQLITE_CORRUPT + { + // if the database is corrupted then return `false` as the consumer may want to just refetch the db themselves + return false; } } diff --git a/osu.Game/Database/BackgroundDataStoreProcessor.cs b/osu.Game/Database/BackgroundDataStoreProcessor.cs index 23ae6b7351..b63c1e2888 100644 --- a/osu.Game/Database/BackgroundDataStoreProcessor.cs +++ b/osu.Game/Database/BackgroundDataStoreProcessor.cs @@ -72,12 +72,16 @@ namespace osu.Game.Database [Resolved] private OsuConfigManager config { get; set; } = null!; + private LocalCachedBeatmapMetadataSource localMetadataSource = null!; + protected virtual int TimeToSleepDuringGameplay => 30000; protected override void LoadComplete() { base.LoadComplete(); + localMetadataSource = new LocalCachedBeatmapMetadataSource(storage); + ProcessingTask = Task.Factory.StartNew(() => { Logger.Log("Beginning background data store processing.."); @@ -532,8 +536,6 @@ namespace osu.Game.Database private void backpopulateMissingSubmissionAndRankDates() { - var localMetadataSource = new LocalCachedBeatmapMetadataSource(storage); - if (!localMetadataSource.Available) { Logger.Log("Cannot backpopulate missing submission/rank dates because the local metadata cache is missing."); @@ -542,7 +544,7 @@ namespace osu.Game.Database try { - if (localMetadataSource.GetCacheVersion() < 2) + if (!localMetadataSource.IsAtLeastVersion(2)) { Logger.Log("Cannot backpopulate missing submission/rank dates because the local metadata cache is too old."); return; @@ -630,14 +632,12 @@ namespace osu.Game.Database private void backpopulateUserTags() { - var localMetadataSource = new LocalCachedBeatmapMetadataSource(storage); - - if (!localMetadataSource.Available || localMetadataSource.GetCacheVersion() < 3) + if (!localMetadataSource.Available || !localMetadataSource.IsAtLeastVersion(3)) { Logger.Log(@"Local metadata cache has too low version to backpopulate user tags, attempting refetch..."); localMetadataSource.FetchCache().WaitSafely(); - if (!localMetadataSource.Available || localMetadataSource.GetCacheVersion() < 3) + if (!localMetadataSource.Available || !localMetadataSource.IsAtLeastVersion(3)) { Logger.Log(@"Local metadata cache refetch failed. Aborting user tags backpopulation."); return;