Skip to content

Fix Lite UI freeze during archival (#979)#982

Merged
erikdarlingdata merged 1 commit into
devfrom
feature/979-lite-archival-lock
May 22, 2026
Merged

Fix Lite UI freeze during archival (#979)#982
erikdarlingdata merged 1 commit into
devfrom
feature/979-lite-archival-lock

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Problem

Split out from #976. While Lite is connected to servers, tab navigation intermittently shows the spinning wheel or a 2–3 s delay, correlating with archival and worsening with more monitored servers.

ArchiveService.ArchiveOldDataAsync held DuckDB's exclusive write lock (DuckDbInitializer.s_dbLock) across the entire export-to-Parquet + DELETE loop. Export-to-Parquet (COPY … TO) only reads the database, but under the write lock it blocked every UI read for its full duration — and UI queries take a read lock with no timeout, so a tab switch froze until archival finished.

Change

In ArchiveOldDataAsync, per table:

  • Export-to-Parquet runs under a shared read lock — concurrent with the UI.
  • Only the DELETE takes the exclusive write lock, briefly.

Splitting the lock scopes is safe here: the DELETE only removes rows older than the cutoff, and collectors only ever insert "now"-stamped rows, so nothing archivable can land in the gap between the export and the delete.

ArchiveAllAndResetAsync (the size-triggered "export everything → reset database" path) is left unchanged — there the write lock also prevents collectors writing rows between the export snapshot and the reset, and it's the rare emergency path rather than the routine one.

Test plan

  • dotnet build Lite/PerformanceMonitorLite.csproj -c Debug — clean, 0 warnings.
  • Logic review: export is read-only (COPY … SELECT … TO), so a read lock is sufficient; only the DELETE mutates the file and keeps the exclusive lock.
  • Not yet smoke-tested against a live populated DuckDB with archival triggered — worth a manual pass before release.

🤖 Generated with Claude Code

…979)

ArchiveService.ArchiveOldDataAsync held DuckDB's exclusive write lock
across the entire export-to-Parquet + DELETE loop. Export-to-Parquet
(COPY ... TO) only reads the database, but running it under the write
lock blocked every UI query for the whole export - tab switches showed
the spinning wheel, and it got worse with more monitored servers.

Per table, export now runs under a shared read lock (concurrent with the
UI); only the DELETE takes the exclusive write lock, briefly. Safe to
split: the DELETE only removes rows older than the cutoff and collectors
only insert "now"-stamped rows, so nothing archivable lands in the gap
between the export and the delete.

ArchiveAllAndResetAsync (the size-triggered reset path) keeps its write
lock unchanged - there the lock also prevents collectors writing rows
between the export snapshot and the database reset.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit 5ee432a into dev May 22, 2026
2 checks passed
@erikdarlingdata erikdarlingdata deleted the feature/979-lite-archival-lock branch May 22, 2026 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant