Kept the app responsive while a backup copies the index (#1062)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-10-15 17:50:44 +02:00
1 parent 936043319c
commit 65857ca845
5 files changed
+64 -28

No files matched your search

@@ -24,6 +24,11 @@ When working on these, keep in mind:
- **Let every probe in `GetDisplayInfo()` catch its own failure.** When the method throws, the page
replaces the *entire* block with the fallback client, so one unreadable value costs all the others
as well.
- **SQLite runs its async methods synchronously.** `Microsoft.Data.Sqlite`, and EF Core on top of it,
only looks asynchronous: the calling thread does all the work. A statement which may take long, such
as `VACUUM` or a check of the whole database, runs in `Task.Run` inside the client, as
`BackupToDirectoryAsync` does. Otherwise a click in the user interface which reaches it freezes the
whole window until the statement is done.
- **Raw SQL against SQLite goes through `context.Database.GetDbConnection()`**, not through
`SqlQueryRaw<T>`: that one expects a column named `Value` and wraps the statement, so a `PRAGMA`
never works with it.
@@ -590,9 +590,14 @@ public sealed partial class SqliteIndexStoreClientImplementation(string name, st
/// GetDbConnection. The connections of the context share one cache, and a shared cache locks
/// whole tables: reading the whole database for the copy would hold back every writer until the
/// copy is done. Without pooling, nothing keeps the copy open afterward, so the backup can
/// delete it on every OS.
/// delete it on every OS.<br/><br/>
///
/// SQLite runs its async methods synchronously, and copying and checking a large index takes a
/// while. The copy therefore runs on a thread of its own, so that it never holds up its caller.
/// </remarks>
public override async Task<string> BackupToDirectoryAsync(string targetDirectory, CancellationToken token)
public override Task<string> BackupToDirectoryAsync(string targetDirectory, CancellationToken token) => Task.Run(() => this.CopyAndCheckAsync(targetDirectory, token), token);
private async Task<string> CopyAndCheckAsync(string targetDirectory, CancellationToken token)
{
Directory.CreateDirectory(targetDirectory);
var targetPath = Path.Join(targetDirectory, DATABASE_FILENAME);