1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-13 08:32:57 +08:00

Remove Task from the inner-most Import method in RealmArchiveModelImporter

One of my pending work items for post-realm merge.

The lowest-level import task is no longer asynchronous, as we don't want
it to span multiple threads to allow easier interaction with realm.
Removing the `Task` spec simplifies a heap of usages.

Individual usages should decide whether they want to run the import
asynchronously, by either using an alternative override or spooling up a
thread themselves.
This commit is contained in:
Dean Herbert 2022-01-25 15:23:51 +09:00
parent ae0fea8e26
commit 778d2a71b4
21 changed files with 57 additions and 62 deletions

View File

@ -685,7 +685,7 @@ namespace osu.Game.Tests.Database
[Test]
public void TestImportWithDuplicateBeatmapIDs()
{
RunTestWithRealmAsync(async (realm, storage) =>
RunTestWithRealm((realm, storage) =>
{
using var importer = new BeatmapModelManager(realm, storage);
using var store = new RulesetStore(realm, storage);
@ -718,7 +718,7 @@ namespace osu.Game.Tests.Database
}
};
var imported = await importer.Import(toImport);
var imported = importer.Import(toImport);
Assert.NotNull(imported);
Debug.Assert(imported != null);

View File

@ -91,7 +91,7 @@ namespace osu.Game.Tests.Online
addAvailabilityCheckStep("state importing", BeatmapAvailability.Importing);
AddStep("allow importing", () => beatmaps.AllowImport.SetResult(true));
AddUntilStep("wait for import", () => beatmaps.CurrentImportTask?.IsCompleted == true);
AddUntilStep("wait for import", () => beatmaps.CurrentImport != null);
addAvailabilityCheckStep("state locally available", BeatmapAvailability.LocallyAvailable);
}
@ -164,7 +164,7 @@ namespace osu.Game.Tests.Online
{
public TaskCompletionSource<bool> AllowImport = new TaskCompletionSource<bool>();
public Task<ILive<BeatmapSetInfo>> CurrentImportTask { get; private set; }
public ILive<BeatmapSetInfo> CurrentImport { get; private set; }
public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
@ -186,10 +186,10 @@ namespace osu.Game.Tests.Online
this.testBeatmapManager = testBeatmapManager;
}
public override async Task<ILive<BeatmapSetInfo>> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
public override ILive<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
{
await testBeatmapManager.AllowImport.Task.ConfigureAwait(false);
return await (testBeatmapManager.CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
testBeatmapManager.AllowImport.Task.WaitSafely();
return (testBeatmapManager.CurrentImport = base.Import(item, archive, lowPriority, cancellationToken));
}
}
}

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
@ -25,7 +24,7 @@ namespace osu.Game.Tests.Scores.IO
public class ImportScoreTest : ImportTest
{
[Test]
public async Task TestBasicImport()
public void TestBasicImport()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
{
@ -49,7 +48,7 @@ namespace osu.Game.Tests.Scores.IO
BeatmapInfo = beatmap.Beatmaps.First()
};
var imported = await LoadScoreIntoOsu(osu, toImport);
var imported = LoadScoreIntoOsu(osu, toImport);
Assert.AreEqual(toImport.Rank, imported.Rank);
Assert.AreEqual(toImport.TotalScore, imported.TotalScore);
@ -67,7 +66,7 @@ namespace osu.Game.Tests.Scores.IO
}
[Test]
public async Task TestImportMods()
public void TestImportMods()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
{
@ -85,7 +84,7 @@ namespace osu.Game.Tests.Scores.IO
Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() },
};
var imported = await LoadScoreIntoOsu(osu, toImport);
var imported = LoadScoreIntoOsu(osu, toImport);
Assert.IsTrue(imported.Mods.Any(m => m is OsuModHardRock));
Assert.IsTrue(imported.Mods.Any(m => m is OsuModDoubleTime));
@ -98,7 +97,7 @@ namespace osu.Game.Tests.Scores.IO
}
[Test]
public async Task TestImportStatistics()
public void TestImportStatistics()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
{
@ -120,7 +119,7 @@ namespace osu.Game.Tests.Scores.IO
}
};
var imported = await LoadScoreIntoOsu(osu, toImport);
var imported = LoadScoreIntoOsu(osu, toImport);
Assert.AreEqual(toImport.Statistics[HitResult.Perfect], imported.Statistics[HitResult.Perfect]);
Assert.AreEqual(toImport.Statistics[HitResult.Miss], imported.Statistics[HitResult.Miss]);
@ -133,7 +132,7 @@ namespace osu.Game.Tests.Scores.IO
}
[Test]
public async Task TestOnlineScoreIsAvailableLocally()
public void TestOnlineScoreIsAvailableLocally()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
{
@ -143,7 +142,7 @@ namespace osu.Game.Tests.Scores.IO
var beatmap = BeatmapImportHelper.LoadOszIntoOsu(osu, TestResources.GetQuickTestBeatmapForImport()).GetResultSafely();
await LoadScoreIntoOsu(osu, new ScoreInfo
LoadScoreIntoOsu(osu, new ScoreInfo
{
User = new APIUser { Username = "Test user" },
BeatmapInfo = beatmap.Beatmaps.First(),
@ -168,13 +167,14 @@ namespace osu.Game.Tests.Scores.IO
}
}
public static async Task<ScoreInfo> LoadScoreIntoOsu(OsuGameBase osu, ScoreInfo score, ArchiveReader archive = null)
public static ScoreInfo LoadScoreIntoOsu(OsuGameBase osu, ScoreInfo score, ArchiveReader archive = null)
{
// clone to avoid attaching the input score to realm.
score = score.DeepClone();
var scoreManager = osu.Dependencies.Get<ScoreManager>();
await scoreManager.Import(score, archive);
scoreManager.Import(score, archive);
return scoreManager.Query(_ => true);
}

View File

@ -147,7 +147,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded);
AddStep("import score", () => imported = scoreManager.Import(getScoreInfo(true)).GetResultSafely());
AddStep("import score", () => imported = scoreManager.Import(getScoreInfo(true)));
AddUntilStep("state is available", () => downloadButton.State.Value == DownloadState.LocallyAvailable);

View File

@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual.Menus
Queue<(IWorkingBeatmap working, TrackChangeDirection changeDirection)> trackChangeQueue = null;
// ensure we have at least two beatmaps available to identify the direction the music controller navigated to.
AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(TestResources.CreateTestBeatmapSetInfo()).WaitSafely(), 5);
AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(TestResources.CreateTestBeatmapSetInfo()), 5);
AddStep("import beatmap with track", () =>
{

View File

@ -8,7 +8,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Platform;
@ -158,7 +157,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
Debug.Assert(beatmap.BeatmapSet != null);
AddStep("import beatmap", () => imported = manager.Import(beatmap.BeatmapSet).GetResultSafely());
AddStep("import beatmap", () => imported = manager.Import(beatmap.BeatmapSet));
createPlaylistWithBeatmaps(() => imported.PerformRead(s => s.Beatmaps.Detach()));

View File

@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
beatmapSetInfo.Beatmaps.Add(beatmap);
}
manager.Import(beatmapSetInfo).WaitSafely();
manager.Import(beatmapSetInfo);
}
public override void SetUpSteps()

View File

@ -6,7 +6,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Extensions;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Utils;
@ -40,7 +39,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
var beatmapSet = TestResources.CreateTestBeatmapSetInfo();
manager.Import(beatmapSet).WaitSafely();
manager.Import(beatmapSet);
}
public override void SetUpSteps()

View File

@ -4,7 +4,6 @@
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
@ -125,7 +124,7 @@ namespace osu.Game.Tests.Visual.Navigation
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
},
}
}).GetResultSafely()?.Value;
})?.Value;
});
AddAssert($"import {i} succeeded", () => imported != null);

View File

@ -4,7 +4,6 @@
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
@ -60,7 +59,7 @@ namespace osu.Game.Tests.Visual.Navigation
Ruleset = new OsuRuleset().RulesetInfo
},
}
}).GetResultSafely()?.Value;
})?.Value;
});
}
@ -135,7 +134,7 @@ namespace osu.Game.Tests.Visual.Navigation
BeatmapInfo = beatmap.Beatmaps.First(),
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo,
User = new GuestUser(),
}).GetResultSafely().Value;
}).Value;
});
AddAssert($"import {i} succeeded", () => imported != null);

View File

@ -8,7 +8,6 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
@ -151,7 +150,7 @@ namespace osu.Game.Tests.Visual.Playlists
Debug.Assert(modifiedBeatmap.BeatmapInfo.BeatmapSet != null);
manager.Import(modifiedBeatmap.BeatmapInfo.BeatmapSet).WaitSafely();
manager.Import(modifiedBeatmap.BeatmapInfo.BeatmapSet);
});
// Create the room using the real beatmap values.
@ -196,7 +195,7 @@ namespace osu.Game.Tests.Visual.Playlists
Debug.Assert(originalBeatmap.BeatmapInfo.BeatmapSet != null);
manager.Import(originalBeatmap.BeatmapInfo.BeatmapSet).WaitSafely();
manager.Import(originalBeatmap.BeatmapInfo.BeatmapSet);
});
AddUntilStep("match has correct beatmap", () => realHash == match.Beatmap.Value.BeatmapInfo.MD5Hash);
@ -219,7 +218,7 @@ namespace osu.Game.Tests.Visual.Playlists
Debug.Assert(beatmap.BeatmapInfo.BeatmapSet != null);
importedBeatmap = manager.Import(beatmap.BeatmapInfo.BeatmapSet).GetResultSafely()?.Value.Detach();
importedBeatmap = manager.Import(beatmap.BeatmapInfo.BeatmapSet)?.Value.Detach();
});
private class TestPlaylistsRoomSubScreen : PlaylistsRoomSubScreen

View File

@ -180,7 +180,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep(@"Load new scores via manager", () =>
{
foreach (var score in generateSampleScores(beatmapInfo()))
scoreManager.Import(score).WaitSafely();
scoreManager.Import(score);
});
}

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
@ -184,7 +183,7 @@ namespace osu.Game.Tests.Visual.SongSelect
beatmap.DifficultyName = $"SR{i + 1}";
}
return Game.BeatmapManager.Import(beatmapSet).GetResultSafely()?.Value;
return Game.BeatmapManager.Import(beatmapSet)?.Value;
}
private bool ensureAllBeatmapSetsImported(IEnumerable<BeatmapSetInfo> beatmapSets) => beatmapSets.All(set => set != null);

View File

@ -8,7 +8,6 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
@ -260,7 +259,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import multi-ruleset map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(TestResources.CreateTestBeatmapSetInfo(rulesets: usableRulesets)).WaitSafely();
manager.Import(TestResources.CreateTestBeatmapSetInfo(rulesets: usableRulesets));
});
}
else
@ -675,7 +674,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import multi-ruleset map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(TestResources.CreateTestBeatmapSetInfo(3, usableRulesets)).WaitSafely();
manager.Import(TestResources.CreateTestBeatmapSetInfo(3, usableRulesets));
});
int previousSetID = 0;
@ -715,7 +714,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import multi-ruleset map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(TestResources.CreateTestBeatmapSetInfo(3, usableRulesets)).WaitSafely();
manager.Import(TestResources.CreateTestBeatmapSetInfo(3, usableRulesets));
});
DrawableCarouselBeatmapSet set = null;
@ -764,7 +763,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import huge difficulty count map", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
imported = manager.Import(TestResources.CreateTestBeatmapSetInfo(50, usableRulesets)).GetResultSafely()?.Value;
imported = manager.Import(TestResources.CreateTestBeatmapSetInfo(50, usableRulesets))?.Value;
});
AddStep("select the first beatmap of import", () => Beatmap.Value = manager.GetWorkingBeatmap(imported.Beatmaps.First()));
@ -873,7 +872,7 @@ namespace osu.Game.Tests.Visual.SongSelect
private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id));
private void importForRuleset(int id) => manager.Import(TestResources.CreateTestBeatmapSetInfo(3, rulesets.AvailableRulesets.Where(r => r.OnlineID == id).ToArray())).WaitSafely();
private void importForRuleset(int id) => manager.Import(TestResources.CreateTestBeatmapSetInfo(3, rulesets.AvailableRulesets.Where(r => r.OnlineID == id).ToArray()));
private void checkMusicPlaying(bool playing) =>
AddUntilStep($"music {(playing ? "" : "not ")}playing", () => music.IsPlaying == playing);
@ -903,7 +902,7 @@ namespace osu.Game.Tests.Visual.SongSelect
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
for (int i = 0; i < 10; i++)
manager.Import(TestResources.CreateTestBeatmapSetInfo(difficultyCountPerSet, usableRulesets)).WaitSafely();
manager.Import(TestResources.CreateTestBeatmapSetInfo(difficultyCountPerSet, usableRulesets));
});
}

View File

@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Ruleset = new OsuRuleset().RulesetInfo,
};
importedScores.Add(scoreManager.Import(score).GetResultSafely().Value);
importedScores.Add(scoreManager.Import(score).Value);
}
});

View File

@ -10,7 +10,6 @@ using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Audio;
using osu.Framework.Audio.Track;
using osu.Framework.Extensions;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Framework.Testing;
@ -105,7 +104,7 @@ namespace osu.Game.Beatmaps
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
b.BeatmapSet = beatmapSet;
var imported = beatmapModelManager.Import(beatmapSet).GetResultSafely();
var imported = beatmapModelManager.Import(beatmapSet);
if (imported == null)
throw new InvalidOperationException("Failed to import new beatmap");
@ -295,7 +294,7 @@ namespace osu.Game.Beatmaps
return beatmapModelManager.Import(archive, lowPriority, cancellationToken);
}
public Task<ILive<BeatmapSetInfo>?> Import(BeatmapSetInfo item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
public ILive<BeatmapSetInfo>? Import(BeatmapSetInfo item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
{
return beatmapModelManager.Import(item, archive, lowPriority, cancellationToken);
}

View File

@ -45,7 +45,7 @@ namespace osu.Game.Database
/// <param name="archive">An optional archive to use for model population.</param>
/// <param name="lowPriority">Whether this is a low priority import.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
Task<ILive<TModel>?> Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default);
ILive<TModel>? Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default);
/// <summary>
/// A user displayable name for the model type associated with this manager.

View File

@ -308,7 +308,7 @@ namespace osu.Game.Scoring
return scoreModelManager.Import(archive, lowPriority, cancellationToken);
}
public Task<ILive<ScoreInfo>> Import(ScoreInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
public ILive<ScoreInfo> Import(ScoreInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
{
return scoreModelManager.Import(item, archive, lowPriority, cancellationToken);
}

View File

@ -1024,11 +1024,11 @@ namespace osu.Game.Screens.Play
/// </summary>
/// <param name="score">The <see cref="Scoring.Score"/> to import.</param>
/// <returns>The imported score.</returns>
protected virtual async Task ImportScore(Score score)
protected virtual Task ImportScore(Score score)
{
// Replays are already populated and present in the game's database, so should not be re-imported.
if (DrawableRuleset.ReplayScore != null)
return;
return Task.CompletedTask;
LegacyByteArrayReader replayReader;
@ -1048,7 +1048,7 @@ namespace osu.Game.Screens.Play
// conflicts across various systems (ie. solo and multiplayer).
importableScore.OnlineID = -1;
var imported = await scoreManager.Import(importableScore, replayReader).ConfigureAwait(false);
var imported = scoreManager.Import(importableScore, replayReader);
imported.PerformRead(s =>
{
@ -1056,6 +1056,8 @@ namespace osu.Game.Screens.Play
score.ScoreInfo.Hash = s.Hash;
score.ScoreInfo.ID = s.ID;
});
return Task.CompletedTask;
}
/// <summary>

View File

@ -11,7 +11,6 @@ using JetBrains.Annotations;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Textures;
@ -151,7 +150,7 @@ namespace osu.Game.Skinning
Name = s.Name + @" (modified)",
Creator = s.Creator,
InstantiationInfo = s.InstantiationInfo,
}).GetResultSafely();
});
if (result != null)
{
@ -278,7 +277,7 @@ namespace osu.Game.Skinning
return skinModelManager.Import(archive, lowPriority, cancellationToken);
}
public Task<ILive<SkinInfo>> Import(SkinInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
public ILive<SkinInfo> Import(SkinInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
{
return skinModelManager.Import(item, archive, lowPriority, cancellationToken);
}

View File

@ -250,8 +250,10 @@ namespace osu.Game.Stores
return null;
}
var scheduledImport = Task.Factory.StartNew(async () => await Import(model, archive, lowPriority, cancellationToken).ConfigureAwait(false),
cancellationToken, TaskCreationOptions.HideScheduler, lowPriority ? import_scheduler_low_priority : import_scheduler).Unwrap();
var scheduledImport = Task.Factory.StartNew(() => Import(model, archive, lowPriority, cancellationToken),
cancellationToken,
TaskCreationOptions.HideScheduler,
lowPriority ? import_scheduler_low_priority : import_scheduler);
return await scheduledImport.ConfigureAwait(false);
}
@ -318,7 +320,7 @@ namespace osu.Game.Stores
/// <param name="archive">An optional archive to use for model population.</param>
/// <param name="lowPriority">Whether this is a low priority import.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
public virtual Task<ILive<TModel>?> Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
public virtual ILive<TModel>? Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
{
return Realm.Run(realm =>
{
@ -353,7 +355,7 @@ namespace osu.Game.Stores
transaction.Commit();
}
return Task.FromResult((ILive<TModel>?)existing.ToLive(Realm));
return existing.ToLive(Realm);
}
LogForModel(item, @"Found existing (optimised) but failed pre-check.");
@ -388,7 +390,7 @@ namespace osu.Game.Stores
existing.DeletePending = false;
transaction.Commit();
return Task.FromResult((ILive<TModel>?)existing.ToLive(Realm));
return existing.ToLive(Realm);
}
LogForModel(item, @"Found existing but failed re-use check.");
@ -414,7 +416,7 @@ namespace osu.Game.Stores
throw;
}
return Task.FromResult((ILive<TModel>?)item.ToLive(Realm));
return (ILive<TModel>?)item.ToLive(Realm);
});
}