Drei Zähler für dieselbe Sache, und keiner davon offensichtlich falsch
Während eines Scans stand in der Mediathek 20, in der Verwaltung 14 und in der Seitenleiste 0. Die Verwaltung frischte alle fünf Runden auf, die Seitenleiste erst am Ende des Laufs. Jetzt laufen beide auf demselben Takt, alle drei Runden. Dazu: während ein Lauf läuft, sind Scannen, Metadaten auffrischen, Zurücksetzen und Entfernen gesperrt — die ersten beiden prallen am Server ab und sind nur verwirrend, die anderen beiden löschen Zeilen, während der Lauf welche schreibt. Umbenennen und Prüfung bleiben bedienbar. Die Sperre richtet sich nach dem Zustand, den der Server meldet, nicht nach dem Klick: wer die Seite neu lädt, während ein Lauf läuft, findet sie ebenfalls gesperrt vor. Die Reihenfolge der Mediatheken wird jetzt in der Seitenleiste umsortiert, über „Seitenleiste bearbeiten" neben der Überschrift. Sie wirkt dort, also gehört der Griff dorthin — vorher schob man in den Einstellungen und musste danach nachsehen, ob es das war, was man wollte. Der Zuordnungsdialog zeigt die Herkunft: Ordner, Zahl der Dateien und ein paar Namen. Liegt eine Zuordnung völlig daneben, sagt der angezeigte Titel nichts mehr darüber, welche Datei gemeint ist. Und SQLite läuft jetzt im WAL-Modus. In der Vorgabe sperrt ein Schreiber die ganze Datei: solange der Scan schrieb, kam keine Leseanfrage durch. Genau so sah es aus — Bilddialog und Protokoll liefen während eines Laufs sporadisch ins Leere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e1b3625809
commit
a22fa9b58e
@@ -20,7 +20,15 @@ pfade.EnsureExists();
|
||||
builder.Services.AddSingleton(pfade);
|
||||
builder.Services.AddSingleton(TimeProvider.System);
|
||||
|
||||
builder.Services.AddDbContext<FlaroContext>(o => o.UseSqlite($"Data Source={pfade.DatabaseFile}"));
|
||||
// **Mit Wartezeit statt sofortigem Abbruch.**
|
||||
//
|
||||
// SQLite lässt genau einen Schreiber zu. Ohne `Default Timeout` scheitert
|
||||
// jeder, der dazwischenkommt, auf der Stelle mit „database is locked" —
|
||||
// während eines Scans über tausende Dateien ist das jede zweite Anfrage aus
|
||||
// der Oberfläche. Dreissig Sekunden sind grosszügig; gebraucht werden
|
||||
// Millisekunden.
|
||||
builder.Services.AddDbContext<FlaroContext>(o =>
|
||||
o.UseSqlite($"Data Source={pfade.DatabaseFile};Default Timeout=30"));
|
||||
|
||||
builder.Services
|
||||
.AddAuthentication(TokenAuthenticationHandler.SchemeName)
|
||||
@@ -124,7 +132,28 @@ var app = builder.Build();
|
||||
// hochfährt, soll nicht erst eine Migration von Hand anstossen müssen.
|
||||
using (var bereich = app.Services.CreateScope())
|
||||
{
|
||||
await bereich.ServiceProvider.GetRequiredService<FlaroContext>().Database.MigrateAsync();
|
||||
var db = bereich.ServiceProvider.GetRequiredService<FlaroContext>();
|
||||
|
||||
// **WAL, und zwar vor der Migration.**
|
||||
//
|
||||
// In der Vorgabe („delete") sperrt ein Schreiber die ganze Datei: solange
|
||||
// der Scan schreibt, kommt *keine* Leseanfrage durch. Genau so sah es in
|
||||
// der Oberfläche aus — Bilddialog und Protokoll liefen während eines
|
||||
// Laufs sporadisch ins Leere. Mit WAL lesen beliebig viele weiter,
|
||||
// während einer schreibt.
|
||||
//
|
||||
// Die Einstellung hält sich in der Datei; einmal gesetzt bleibt sie. Sie
|
||||
// trotzdem bei jedem Start zu setzen kostet nichts und deckt den Fall ab,
|
||||
// dass jemand mit einer frischen Datei kommt.
|
||||
await db.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL;");
|
||||
|
||||
// Ohne das wartet SQLite nach jeder Schreibung auf die Platte. Mit WAL
|
||||
// ist „normal" die übliche Wahl: ein Absturz des Prozesses kostet nichts,
|
||||
// nur ein Stromausfall mitten im Schreiben könnte die letzte Transaktion
|
||||
// kosten — und die ist bei einem Medienserver ein Scanfortschritt.
|
||||
await db.Database.ExecuteSqlRawAsync("PRAGMA synchronous=NORMAL;");
|
||||
|
||||
await db.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
app.UseExceptionHandler();
|
||||
|
||||
Reference in New Issue
Block a user