fix(siteeventlog)+fix(host): purge startup yield + auto_vacuum reality (arch-review 2026-08-19 P4-5 + P4-6)
P4-5: EventLogPurgeService.ExecuteAsync now yields (Task.Yield()) before running the initial RunPurge(), making "the purge never runs synchronously on the caller's thread" a property of the method itself rather than an artifact of .NET 8+'s BackgroundService scheduling (verified empirically not to reproduce the literal "StartAsync blocks" symptom on this repo's net10.0 target — a 1.5s synchronous Thread.Sleep in ExecuteAsync still lets StartAsync return in ~2ms). Proven instead via a reflection-invoked ExecuteAsync test that bypasses BackgroundService's Task.Run wrapper, which is timing-independent. Also: a throwing isActive predicate now fails CLOSED (logged as inactive, at Warning) instead of silently claiming "active" — the predicate only affects the tick's log line since P4-4, but a throw must not masquerade as a successful check. P4-6: PRAGMA auto_vacuum = INCREMENTAL only takes effect on a table-less database, and LocalDbSchema.EnsureCreated (inside SqliteLocalDb's constructor) always creates LocalDb's own bookkeeping tables before SiteEventLogSchema.Apply ever gets a connection — so the pragma there had never once taken effect, in any real call path. Real fix per plan decision 2: SiteLocalDbSetup.EnsureAutoVacuumOnFreshFile pre-creates a genuinely fresh LocalDb file with the pragma set, called from SiteServiceRegistration.Configure BEFORE AddZbLocalDb's lazy singleton ever constructs SqliteLocalDb — no LocalDb API change needed. Only helps NEW site databases; an existing file (every node on the docker rig today) is left untouched rather than VACUUM'd, per the plan's explicit rejection of an unconditional VACUUM against a live ~1 GB file. The now-dead pragma call in SiteEventLogSchema.Apply is removed and its comment corrected. Tests proven to fail against the unfixed code (git-diff-and-restore, not stash — this repo shares one stash ref across all worktrees): ExecuteAsync_YieldsBeforeRunningTheInitial- PurgeSynchronously and RunPurge_ActiveNodeCheckThrows_TickLogsAsInactive_NotActive fail without the EventLogPurgeService fix; SiteLocalDbAutoVacuumTests fails to compile without EnsureAutoVacuumOnFreshFile. SiteEventLogging.Tests 112/112 and Host.Tests 526/526 green with the fix applied.
This commit is contained in:
@@ -36,15 +36,24 @@ public static class SiteEventLogSchema
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(connection);
|
||||
|
||||
// auto_vacuum must be set before any table is created for it to take effect
|
||||
// on a fresh database. With INCREMENTAL mode, PRAGMA incremental_vacuum can
|
||||
// later reclaim free pages so the storage-cap purge can shrink the file.
|
||||
using (var pragmaCmd = connection.CreateCommand())
|
||||
{
|
||||
pragmaCmd.CommandText = "PRAGMA auto_vacuum = INCREMENTAL";
|
||||
pragmaCmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// arch-review 2026-08-19 P4-6: this method used to also set
|
||||
// "PRAGMA auto_vacuum = INCREMENTAL" here, on the theory that setting it right
|
||||
// before CREATE TABLE would make it take effect on a fresh database. That was
|
||||
// wrong in every real call path: SQLite only honors an auto_vacuum change on a
|
||||
// database that has NO tables yet, and by the time this method runs — via the
|
||||
// Host's AddZbLocalDb onReady callback (SiteLocalDbSetup.OnReady) OR via
|
||||
// SiteEventLogger's own InitializeSchema fallback for directly-constructed
|
||||
// instances — the consolidated file already holds LocalDb's own bookkeeping
|
||||
// tables (SqliteLocalDb's constructor runs LocalDbSchema.EnsureCreated on its
|
||||
// master connection before either caller ever gets a connection). So the pragma
|
||||
// here had never once taken effect; it was a silent, permanent no-op. The real
|
||||
// fix now lives in Host/SiteLocalDbSetup.cs
|
||||
// (EnsureAutoVacuumOnFreshFile), which pre-creates a genuinely fresh LocalDb file
|
||||
// with the pragma set BEFORE AddZbLocalDb's lazy singleton ever constructs
|
||||
// SqliteLocalDb — and, being a Host-layer, one-time, pre-file-existence step, it
|
||||
// helps ONLY brand-new site databases; every file created before this fix shipped
|
||||
// stays auto_vacuum=NONE forever (see the PurgeByStorageCap remarks in
|
||||
// EventLogPurgeService for the operational consequence).
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
CREATE TABLE IF NOT EXISTS site_events (
|
||||
|
||||
Reference in New Issue
Block a user