Skip to content

New Job Monitor, Faster Exports, and UI Fixes#284

Merged
chvvkumar merged 26 commits into
mainfrom
dev
Jul 21, 2026
Merged

New Job Monitor, Faster Exports, and UI Fixes#284
chvvkumar merged 26 commits into
mainfrom
dev

Conversation

@chvvkumar

@chvvkumar chvvkumar commented Jul 19, 2026

Copy link
Copy Markdown
Owner

What's new

  • New global job monitor in the navigation bar.
  • View live transfer speed for WBPP copies.
  • WBPP export flow is now "Export For Stacking" with step-by-step guidance.
  • Open frame previews directly from the WBPP export quality table.
  • WBPP browser copy jobs continue even if the modal is closed.

What's fixed

  • Custom field save spinner no longer shifts controls.
  • Custom field boolean checkboxes no longer revert after saving.
  • Custom field save spinner is now a greyed-out control.
  • Idle activity checks stop when the browser tab is backgrounded.
  • Rejected WBPP copy starts are now properly toasted.

What's changed

  • Initial load of statistics page is significantly faster.
  • WBPP browser copy is up to 9x faster over SMB.
  • Scan and rebuild job status is now visible outside the Settings page.

chvvkumar added 20 commits July 18, 2026 12:39
File names in the WBPP quality table are now preview links, matching the
session frame table. Clicking one opens the shared FilePreviewModal, and the
arrow keys walk every row in the table's current sort order from the clicked
frame, so sorting by verdict lets you flip through all excluded frames in
sequence.

The modal gains an optional per-file metadata strip, passed as a generic
label/value array so it stays ignorant of WBPP concepts. The WBPP panel fills
it with a mirror of the table row: the verdict (with failure detail in the
tooltip), filter, the five quality metrics with the same baseline band colors
and failure marks, and the session date. With the master filter toggle off,
every strip reads Copy. Other callers of the modal pass nothing and are
unaffected.
…atus store so jobs are visible off the Settings page

Extracts rebuild polling out of ScanManager into store/rebuild.ts, and
promotes scan status/stop/refresh to module-level exports in
store/scan.ts. This lets an always-mounted job monitor read scan and
rebuild state and stop a scan from anywhere in the app, not only while
Settings is open. ScanManager keeps its existing wiring into the
dashboard ActivityFeed unchanged; behavior for scan/rebuild polling is
byte-for-byte the same, just relocated.
…rip progress

Adds the aggregation layer the nav-bar job monitor renders from: a single
monitorJobs() list combining the existing scan/rebuild/Celery activeJobs
registry with the WBPP browser copy job, and aggregateProgress() to reduce
that list to one strip-level fraction (mean of determinate jobs, null when
every running job is indeterminate so the strip falls back to a shimmer).
wireGlobalJobSources() replaces the per-page ScanManager wiring so jobs stay
visible across the whole app rather than only the page that started them.
… commit

The prior commit's staging accidentally swept in another in-progress change's
already-staged deletion of this file. Restoring it here so that work stays
untouched and can be committed on its own terms.
…ors store

Task 4 (shared activity-errors store) landed the replacement in b8ffb4a but a
concurrent commit from another in-progress task restored this file while
untangling an unrelated staging collision. Removing it now that the
replacement is confirmed in place and no code references it.
startWbppCopy silently no-oped when a copy was already running, which
would have been a dead end for future callers like the job monitor that
have no pre-check of their own. It now toasts the same way a failure
does, and state from the in-flight copy is proven to survive the
rejected call.

Also adds executable coverage for why the copy lives in a module-level
store: a fresh mount reflects an already-running copy's live progress
immediately, and the store keeps running independent of any component.
…tach test

The spy on runBrowserCopy was never restored, and the mock ignored the abort
signal, leaving store state dirty across tests (wbppCopyFinished remained 4,
stopWbppCopy was a no-op). Updated the mock to listen for abort events on
opts.signal and reject the promise when triggered, allowing stopWbppCopy to
properly clean up. Added mockRestore call to close the spy after test runs.
The abort-listener mock rejected with a plain Error("Aborted") instead of
the CopyCancelledError the real copy throws on cancellation, so the store's
catch treated the test's own cleanup as a genuine failure: it set an error
banner and fired an error toast that then leaked into whatever test ran
next. Reject with the real CopyCancelledError from wbppBrowserCopy instead,
drop the resolveCopy/rejectCopy captures nothing ever called, move the spy
restore into a finally so a failed assertion can't strand it, and drop the
dead try/catch around the cleanup await (startWbppCopy never rethrows).
startRebuildPolling from store/rebuild.ts had no callers, so the ambient
nav-bar job monitor only learned about a repair/retry/backfill/full-rebuild
task through its own 30s idle check. Call it once each maintenance action's
task starts successfully, so the shared store flips to "running" and the
2s poll kicks in immediately instead of leaving the job monitor stale for
up to half a minute. Drops the now-fixed import that ScanManager carried
without ever calling it.
JobMonitor's 30s idle timer fired its scan/rebuild status checks
regardless of tab visibility, burning a request every 30s on tabs left
open in the background. Skip the tick entirely when the document isn't
visible.
…ep by step

The export modal now works for SIRIL as well as WBPP, so the modal title
and the target page export menu item are renamed Export For Stacking. An
info popover next to the title walks through the process, and the sections
are numbered in click order: the library root picker moves out of the
footer into a Step 1 section, followed by the folders to copy and the
filter options. The stray session-count badge on the folders header is
gone, the quality table shows roughly twice as many rows, and the baseline
toggle is renamed Overall with hover text explaining that it only grades
cell colors against session stats or the rig's catalog history.

Also lets the job monitor's active-job status line wrap instead of
clipping the warning that closing the tab cancels the copy.
The in-browser copy used to stream one file at a time, which topped out
around 300 Mbps on a 2.5GbE link. Files now flow through a bounded pool
of eight concurrent copies, and each file is read in 16 MB slices with
explicit writes instead of piping the blob stream, cutting the per-chunk
IPC round trips that capped a single stream. Benchmarked against an SMB
source this saturates the link at roughly 2700 Mbps.

Abort still raises CopyCancelledError and stops new files from starting,
a failed file settles all in-flight writables before the run rejects, and
progress reporting is unchanged. New test suite covers correctness,
the pool bound, chunked writes, zero-byte files, abort, and failures.
The copy progress line used to show the current filename, which was
mostly clipped and said nothing about pace. It now shows the transfer
rate next to the file counts, computed over a rolling three second
window of completed files, as integer Mbps or one-decimal Gbps once
past a gigabit. The nav-bar job monitor picks up the same figure.

While a copy runs, the tab title mirrors the counts and speed so
progress stays visible from other tabs; the original title is restored
when the run finishes, fails, or is cancelled.
Faster Copies, Job Monitoring, and Export Improvements
@github-actions github-actions Bot changed the title Dev Faster WBPP Copy, Job Monitor, and Export Enhancements Jul 19, 2026
Cold /api/stats took around 31 seconds because several full-table
aggregates derived arcsec/px on the fly from raw_headers JSONB with a
per-row regex expression, a cost introduced by the arcsec normalization
work. The value is static per frame, so it is now stored as
images.arcsec_per_pixel at ingest: extract_metadata computes it for FITS
and XISF frames, the scan worker persists it, alembic 0021 adds the
column, and data migration v15 backfills existing rows from raw_headers.

The stats and analysis aggregates now read the column instead of
regex-parsing JSONB per row, so a cold Statistics or Analysis page load
drops to plain column aggregates and no longer hangs on Loading.
Fixed Slow Statistics Loading
@github-actions github-actions Bot changed the title Faster WBPP Copy, Job Monitor, and Export Enhancements Performance, Job Monitoring, and Export Flow Improvements Jul 19, 2026
Sync effect tracked saving() as well as props.value, so a finished
save re-ran it with the stale prop and clobbered the just-committed
value: the checkbox flicked back unchecked until a page reload.
Effect now fires only when props.value changes. Failed saves also
left the DOM checkbox out of sync with the committed value; onChange
now snaps it back and lets a successful save re-check it via signal.
Spinner rendered inline next to the checkbox/select, so in the
right-aligned cell it pushed the control ~18px left while a save was
in flight and snapped back on completion. Spinner is now absolutely
positioned outside the layout flow; controls stay put during saves.
Spinner mounted beside the control flashed on fast LAN saves and read
as a rendering artifact next to the checkbox. Saving feedback is now
the control itself greyed out (disabled at 40% opacity) with a
Saving... tooltip; nothing mounts or unmounts around it.
Improved Custom Field Saving and Display
@github-actions github-actions Bot changed the title Performance, Job Monitoring, and Export Flow Improvements New Job Monitor, Faster Exports, and UI Fixes Jul 21, 2026
@chvvkumar
chvvkumar merged commit abec89d into main Jul 21, 2026
8 checks passed
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