From 20041be27c3311b5ae0b2596a574c295e63ec1be Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 17 Nov 2025 23:55:55 +0100 Subject: [PATCH] Convert ReliableFileStorage to async --- .../Storage/ReliableFileStorageTests.cs | 94 +++++++++---------- .../Internal/DalamudConfiguration.cs | 20 ++-- Dalamud/Configuration/PluginConfigurations.cs | 9 +- Dalamud/EntryPoint.cs | 3 +- .../Windows/Data/Widgets/VfsWidget.cs | 4 +- Dalamud/Storage/ReliableFileStorage.cs | 49 +++++----- 6 files changed, 94 insertions(+), 85 deletions(-) diff --git a/Dalamud.Test/Storage/ReliableFileStorageTests.cs b/Dalamud.Test/Storage/ReliableFileStorageTests.cs index ff56293e0..8a955e430 100644 --- a/Dalamud.Test/Storage/ReliableFileStorageTests.cs +++ b/Dalamud.Test/Storage/ReliableFileStorageTests.cs @@ -31,19 +31,19 @@ public class ReliableFileStorageTests .Select( i => Parallel.ForEachAsync( Enumerable.Range(1, 100), - (j, _) => + async (j, _) => { if (i % 2 == 0) { // ReSharper disable once AccessToDisposedClosure - rfs.Instance.WriteAllText(tempFile, j.ToString()); + await rfs.Instance.WriteAllTextAsync(tempFile, j.ToString()); } else if (i % 3 == 0) { try { // ReSharper disable once AccessToDisposedClosure - rfs.Instance.ReadAllText(tempFile); + await rfs.Instance.ReadAllTextAsync(tempFile); } catch (FileNotFoundException) { @@ -54,8 +54,6 @@ public class ReliableFileStorageTests { File.Delete(tempFile); } - - return ValueTask.CompletedTask; }))); } @@ -112,41 +110,41 @@ public class ReliableFileStorageTests } [Fact] - public void Exists_WhenFileInBackup_ReturnsTrue() + public async Task Exists_WhenFileInBackup_ReturnsTrue() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); File.Delete(tempFile); Assert.True(rfs.Instance.Exists(tempFile)); } [Fact] - public void Exists_WhenFileInBackup_WithDifferentContainerId_ReturnsFalse() + public async Task Exists_WhenFileInBackup_WithDifferentContainerId_ReturnsFalse() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); File.Delete(tempFile); Assert.False(rfs.Instance.Exists(tempFile, Guid.NewGuid())); } [Fact] - public void WriteAllText_ThrowsIfPathIsEmpty() + public async Task WriteAllText_ThrowsIfPathIsEmpty() { using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.WriteAllText("", TestFileContent1)); + await Assert.ThrowsAsync(async () => await rfs.Instance.WriteAllTextAsync("", TestFileContent1)); } [Fact] - public void WriteAllText_ThrowsIfPathIsNull() + public async Task WriteAllText_ThrowsIfPathIsNull() { using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.WriteAllText(null!, TestFileContent1)); + await Assert.ThrowsAsync(async () => await rfs.Instance.WriteAllTextAsync(null!, TestFileContent1)); } [Fact] @@ -155,26 +153,26 @@ public class ReliableFileStorageTests var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); Assert.True(File.Exists(tempFile)); - Assert.Equal(TestFileContent1, rfs.Instance.ReadAllText(tempFile, forceBackup: true)); + Assert.Equal(TestFileContent1, await rfs.Instance.ReadAllTextAsync(tempFile, forceBackup: true)); Assert.Equal(TestFileContent1, await File.ReadAllTextAsync(tempFile)); } [Fact] - public void WriteAllText_SeparatesContainers() + public async Task WriteAllText_SeparatesContainers() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); var containerId = Guid.NewGuid(); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); - rfs.Instance.WriteAllText(tempFile, TestFileContent2, containerId); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent2, containerId); File.Delete(tempFile); - Assert.Equal(TestFileContent1, rfs.Instance.ReadAllText(tempFile, forceBackup: true)); - Assert.Equal(TestFileContent2, rfs.Instance.ReadAllText(tempFile, forceBackup: true, containerId)); + Assert.Equal(TestFileContent1, await rfs.Instance.ReadAllTextAsync(tempFile, forceBackup: true)); + Assert.Equal(TestFileContent2, await rfs.Instance.ReadAllTextAsync(tempFile, forceBackup: true, containerId)); } [Fact] @@ -183,7 +181,7 @@ public class ReliableFileStorageTests var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateFailedRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); Assert.True(File.Exists(tempFile)); Assert.Equal(TestFileContent1, await File.ReadAllTextAsync(tempFile)); @@ -195,38 +193,38 @@ public class ReliableFileStorageTests var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); - rfs.Instance.WriteAllText(tempFile, TestFileContent2); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent2); Assert.True(File.Exists(tempFile)); - Assert.Equal(TestFileContent2, rfs.Instance.ReadAllText(tempFile, forceBackup: true)); + Assert.Equal(TestFileContent2, await rfs.Instance.ReadAllTextAsync(tempFile, forceBackup: true)); Assert.Equal(TestFileContent2, await File.ReadAllTextAsync(tempFile)); } [Fact] - public void WriteAllText_SupportsNullContent() + public async Task WriteAllText_SupportsNullContent() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, null); + await rfs.Instance.WriteAllTextAsync(tempFile, null); Assert.True(File.Exists(tempFile)); - Assert.Equal("", rfs.Instance.ReadAllText(tempFile)); + Assert.Equal("", await rfs.Instance.ReadAllTextAsync(tempFile)); } [Fact] - public void ReadAllText_ThrowsIfPathIsEmpty() + public async Task ReadAllText_ThrowsIfPathIsEmpty() { using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText("")); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync("")); } [Fact] - public void ReadAllText_ThrowsIfPathIsNull() + public async Task ReadAllText_ThrowsIfPathIsNull() { using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText(null!)); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(null!)); } [Fact] @@ -236,40 +234,40 @@ public class ReliableFileStorageTests await File.WriteAllTextAsync(tempFile, TestFileContent1); using var rfs = CreateRfs(); - Assert.Equal(TestFileContent1, rfs.Instance.ReadAllText(tempFile)); + Assert.Equal(TestFileContent1, await rfs.Instance.ReadAllTextAsync(tempFile)); } [Fact] - public void ReadAllText_WhenFileMissingWithBackup_ReturnsContent() + public async Task ReadAllText_WhenFileMissingWithBackup_ReturnsContent() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); File.Delete(tempFile); - Assert.Equal(TestFileContent1, rfs.Instance.ReadAllText(tempFile)); + Assert.Equal(TestFileContent1, await rfs.Instance.ReadAllTextAsync(tempFile)); } [Fact] - public void ReadAllText_WhenFileMissingWithBackup_ThrowsWithDifferentContainerId() + public async Task ReadAllText_WhenFileMissingWithBackup_ThrowsWithDifferentContainerId() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); var containerId = Guid.NewGuid(); using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); File.Delete(tempFile); - Assert.Throws(() => rfs.Instance.ReadAllText(tempFile, containerId: containerId)); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(tempFile, containerId: containerId)); } [Fact] - public void ReadAllText_WhenFileMissing_ThrowsIfDbFailed() + public async Task ReadAllText_WhenFileMissing_ThrowsIfDbFailed() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateFailedRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText(tempFile)); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(tempFile)); } [Fact] @@ -278,7 +276,7 @@ public class ReliableFileStorageTests var tempFile = Path.Combine(CreateTempDir(), TestFileName); await File.WriteAllTextAsync(tempFile, TestFileContent1); using var rfs = CreateRfs(); - rfs.Instance.ReadAllText(tempFile, text => Assert.Equal(TestFileContent1, text)); + await rfs.Instance.ReadAllTextAsync(tempFile, text => Assert.Equal(TestFileContent1, text)); } [Fact] @@ -290,7 +288,7 @@ public class ReliableFileStorageTests var readerCalledOnce = false; using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText(tempFile, Reader)); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(tempFile, Reader)); return; @@ -303,7 +301,7 @@ public class ReliableFileStorageTests } [Fact] - public void ReadAllText_WithReader_WhenReaderThrows_ReadsContentFromBackup() + public async Task ReadAllText_WithReader_WhenReaderThrows_ReadsContentFromBackup() { var tempFile = Path.Combine(CreateTempDir(), TestFileName); @@ -311,10 +309,10 @@ public class ReliableFileStorageTests var assertionCalled = false; using var rfs = CreateRfs(); - rfs.Instance.WriteAllText(tempFile, TestFileContent1); + await rfs.Instance.WriteAllTextAsync(tempFile, TestFileContent1); File.Delete(tempFile); - rfs.Instance.ReadAllText(tempFile, Reader); + await rfs.Instance.ReadAllTextAsync(tempFile, Reader); Assert.True(assertionCalled); return; @@ -335,17 +333,17 @@ public class ReliableFileStorageTests var tempFile = Path.Combine(CreateTempDir(), TestFileName); await File.WriteAllTextAsync(tempFile, TestFileContent1); using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText(tempFile, _ => throw new FileNotFoundException())); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(tempFile, _ => throw new FileNotFoundException())); } [Theory] [InlineData(true)] [InlineData(false)] - public void ReadAllText_WhenFileDoesNotExist_Throws(bool forceBackup) + public async Task ReadAllText_WhenFileDoesNotExist_Throws(bool forceBackup) { var tempFile = Path.Combine(CreateTempDir(), TestFileName); using var rfs = CreateRfs(); - Assert.Throws(() => rfs.Instance.ReadAllText(tempFile, forceBackup)); + await Assert.ThrowsAsync(async () => await rfs.Instance.ReadAllTextAsync(tempFile, forceBackup)); } private static DisposableReliableFileStorage CreateRfs() diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 241a08d90..da0d7c2c6 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -503,13 +503,13 @@ internal sealed class DalamudConfiguration : IInternalDisposableService /// Path to read from. /// File storage. /// The deserialized configuration file. - public static DalamudConfiguration Load(string path, ReliableFileStorage fs) + public static async Task Load(string path, ReliableFileStorage fs) { DalamudConfiguration deserialized = null; try { - fs.ReadAllText(path, text => + await fs.ReadAllTextAsync(path, text => { deserialized = JsonConvert.DeserializeObject(text, SerializerSettings); @@ -580,8 +580,6 @@ internal sealed class DalamudConfiguration : IInternalDisposableService { this.Save(); this.isSaveQueued = false; - - Log.Verbose("Config saved"); } } @@ -630,16 +628,20 @@ internal sealed class DalamudConfiguration : IInternalDisposableService // Wait for previous write to finish this.writeTask?.Wait(); - this.writeTask = Task.Run(() => + this.writeTask = Task.Run(async () => { - Service.Get().WriteAllText( - this.configPath, - JsonConvert.SerializeObject(this, SerializerSettings)); + await Service.Get().WriteAllTextAsync( + this.configPath, + JsonConvert.SerializeObject(this, SerializerSettings)); + Log.Verbose("DalamudConfiguration saved"); }).ContinueWith(t => { if (t.IsFaulted) { - Log.Error(t.Exception, "Failed to save DalamudConfiguration to {Path}", this.configPath); + Log.Error( + t.Exception, + "Failed to save DalamudConfiguration to {Path}", + this.configPath); } }); diff --git a/Dalamud/Configuration/PluginConfigurations.cs b/Dalamud/Configuration/PluginConfigurations.cs index 8e32fa992..fa2969d31 100644 --- a/Dalamud/Configuration/PluginConfigurations.cs +++ b/Dalamud/Configuration/PluginConfigurations.cs @@ -2,6 +2,8 @@ using System.IO; using System.Reflection; using Dalamud.Storage; +using Dalamud.Utility; + using Newtonsoft.Json; namespace Dalamud.Configuration; @@ -9,6 +11,7 @@ namespace Dalamud.Configuration; /// /// Configuration to store settings for a dalamud plugin. /// +[Api13ToDo("Make this a service. We need to be able to dispose it reliably to write configs asynchronously. Maybe also let people write files with vfs.")] public sealed class PluginConfigurations { private readonly DirectoryInfo configDirectory; @@ -36,7 +39,7 @@ public sealed class PluginConfigurations public void Save(IPluginConfiguration config, string pluginName, Guid workingPluginId) { Service.Get() - .WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config), workingPluginId); + .WriteAllTextAsync(this.GetConfigFile(pluginName).FullName, SerializeConfig(config), workingPluginId).GetAwaiter().GetResult(); } /// @@ -52,12 +55,12 @@ public sealed class PluginConfigurations IPluginConfiguration? config = null; try { - Service.Get().ReadAllText(path.FullName, text => + Service.Get().ReadAllTextAsync(path.FullName, text => { config = DeserializeConfig(text); if (config == null) throw new Exception("Read config was null."); - }, workingPluginId); + }, workingPluginId).GetAwaiter().GetResult(); } catch (FileNotFoundException) { diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index 9fc09a56b..15077f3d8 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -144,7 +144,8 @@ public sealed class EntryPoint // Load configuration first to get some early persistent state, like log level var fs = new ReliableFileStorage(Path.GetDirectoryName(info.ConfigurationPath)!); - var configuration = DalamudConfiguration.Load(info.ConfigurationPath!, fs); + var configuration = DalamudConfiguration.Load(info.ConfigurationPath!, fs) + .GetAwaiter().GetResult(); // Set the appropriate logging level from the configuration if (!configuration.LogSynchronously) diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/VfsWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/VfsWidget.cs index f1f2476c9..f044b2989 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/VfsWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/VfsWidget.cs @@ -52,7 +52,7 @@ internal class VfsWidget : IDataWindowWidget for (var i = 0; i < this.reps; i++) { stopwatch.Restart(); - service.WriteAllBytes(path, data); + service.WriteAllBytesAsync(path, data).GetAwaiter().GetResult(); stopwatch.Stop(); acc += stopwatch.ElapsedMilliseconds; Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds); @@ -70,7 +70,7 @@ internal class VfsWidget : IDataWindowWidget for (var i = 0; i < this.reps; i++) { stopwatch.Restart(); - service.ReadAllBytes(path); + service.ReadAllBytesAsync(path).GetAwaiter().GetResult(); stopwatch.Stop(); acc += stopwatch.ElapsedMilliseconds; Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds); diff --git a/Dalamud/Storage/ReliableFileStorage.cs b/Dalamud/Storage/ReliableFileStorage.cs index 9791b9e45..d9f8526c3 100644 --- a/Dalamud/Storage/ReliableFileStorage.cs +++ b/Dalamud/Storage/ReliableFileStorage.cs @@ -1,5 +1,6 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Dalamud.Logging.Internal; using Dalamud.Utility; @@ -92,8 +93,9 @@ internal class ReliableFileStorage : IInternalDisposableService /// Path to write to. /// The contents of the file. /// Container to write to. - public void WriteAllText(string path, string? contents, Guid containerId = default) - => this.WriteAllText(path, contents, Encoding.UTF8, containerId); + /// A representing the asynchronous operation. + public async Task WriteAllTextAsync(string path, string? contents, Guid containerId = default) + => await this.WriteAllTextAsync(path, contents, Encoding.UTF8, containerId); /// /// Write all text to a file. @@ -102,10 +104,11 @@ internal class ReliableFileStorage : IInternalDisposableService /// The contents of the file. /// The encoding to write with. /// Container to write to. - public void WriteAllText(string path, string? contents, Encoding encoding, Guid containerId = default) + /// A representing the asynchronous operation. + public async Task WriteAllTextAsync(string path, string? contents, Encoding encoding, Guid containerId = default) { var bytes = encoding.GetBytes(contents ?? string.Empty); - this.WriteAllBytes(path, bytes, containerId); + await this.WriteAllBytesAsync(path, bytes, containerId); } /// @@ -114,7 +117,8 @@ internal class ReliableFileStorage : IInternalDisposableService /// Path to write to. /// The contents of the file. /// Container to write to. - public void WriteAllBytes(string path, byte[] bytes, Guid containerId = default) + /// A representing the asynchronous operation. + public Task WriteAllBytesAsync(string path, byte[] bytes, Guid containerId = default) { ArgumentException.ThrowIfNullOrEmpty(path); @@ -123,7 +127,7 @@ internal class ReliableFileStorage : IInternalDisposableService if (this.db == null) { FilesystemUtil.WriteAllBytesSafe(path, bytes); - return; + return Task.CompletedTask; } this.db.RunInTransaction(() => @@ -149,6 +153,8 @@ internal class ReliableFileStorage : IInternalDisposableService FilesystemUtil.WriteAllBytesSafe(path, bytes); }); } + + return Task.CompletedTask; } /// @@ -161,8 +167,8 @@ internal class ReliableFileStorage : IInternalDisposableService /// The container to read from. /// All text stored in this file. /// Thrown if the file does not exist on the filesystem or in the backup. - public string ReadAllText(string path, bool forceBackup = false, Guid containerId = default) - => this.ReadAllText(path, Encoding.UTF8, forceBackup, containerId); + public Task ReadAllTextAsync(string path, bool forceBackup = false, Guid containerId = default) + => this.ReadAllTextAsync(path, Encoding.UTF8, forceBackup, containerId); /// /// Read all text from a file. @@ -175,9 +181,9 @@ internal class ReliableFileStorage : IInternalDisposableService /// The container to read from. /// All text stored in this file. /// Thrown if the file does not exist on the filesystem or in the backup. - public string ReadAllText(string path, Encoding encoding, bool forceBackup = false, Guid containerId = default) + public async Task ReadAllTextAsync(string path, Encoding encoding, bool forceBackup = false, Guid containerId = default) { - var bytes = this.ReadAllBytes(path, forceBackup, containerId); + var bytes = await this.ReadAllBytesAsync(path, forceBackup, containerId); return encoding.GetString(bytes); } @@ -191,8 +197,9 @@ internal class ReliableFileStorage : IInternalDisposableService /// The container to read from. /// Thrown if the file does not exist on the filesystem or in the backup. /// Thrown here if the file and the backup fail their read. - public void ReadAllText(string path, Action reader, Guid containerId = default) - => this.ReadAllText(path, Encoding.UTF8, reader, containerId); + /// A representing the asynchronous operation. + public async Task ReadAllTextAsync(string path, Action reader, Guid containerId = default) + => await this.ReadAllTextAsync(path, Encoding.UTF8, reader, containerId); /// /// Read all text from a file, and automatically try again with the backup if the file does not exist or @@ -205,7 +212,8 @@ internal class ReliableFileStorage : IInternalDisposableService /// The container to read from. /// Thrown if the file does not exist on the filesystem or in the backup. /// Thrown here if the file and the backup fail their read. - public void ReadAllText(string path, Encoding encoding, Action reader, Guid containerId = default) + /// A representing the asynchronous operation. + public async Task ReadAllTextAsync(string path, Encoding encoding, Action reader, Guid containerId = default) { ArgumentException.ThrowIfNullOrEmpty(path); @@ -216,7 +224,7 @@ internal class ReliableFileStorage : IInternalDisposableService // 1.) Try without using the backup try { - var text = this.ReadAllText(path, encoding, false, containerId); + var text = await this.ReadAllTextAsync(path, encoding, false, containerId); reader(text); return; } @@ -233,7 +241,7 @@ internal class ReliableFileStorage : IInternalDisposableService // 2.) Try using the backup try { - var text = this.ReadAllText(path, encoding, true, containerId); + var text = await this.ReadAllTextAsync(path, encoding, true, containerId); reader(text); } catch (Exception ex) @@ -253,7 +261,7 @@ internal class ReliableFileStorage : IInternalDisposableService /// The container to read from. /// All bytes stored in this file. /// Thrown if the file does not exist on the filesystem or in the backup. - public byte[] ReadAllBytes(string path, bool forceBackup = false, Guid containerId = default) + public async Task ReadAllBytesAsync(string path, bool forceBackup = false, Guid containerId = default) { ArgumentException.ThrowIfNullOrEmpty(path); @@ -265,15 +273,12 @@ internal class ReliableFileStorage : IInternalDisposableService var normalizedPath = NormalizePath(path); var file = this.db.Table().FirstOrDefault(f => f.Path == normalizedPath && f.ContainerId == containerId); - if (file == null) - throw new FileNotFoundException(); - - return file.Data; + return file == null ? throw new FileNotFoundException() : file.Data; } // If the file doesn't exist, immediately check the backup db if (!File.Exists(path)) - return this.ReadAllBytes(path, true, containerId); + return await this.ReadAllBytesAsync(path, true, containerId); try { @@ -282,7 +287,7 @@ internal class ReliableFileStorage : IInternalDisposableService catch (Exception e) { Log.Error(e, "Failed to read file from disk, falling back to database"); - return this.ReadAllBytes(path, true, containerId); + return await this.ReadAllBytesAsync(path, true, containerId); } }