Commit Graph
10 Commits
Author SHA1 Message Date
JMR-devandCopilot 5aa7c30a6a Finalize DI: drop transitional VM ctor; harden disposal
Remove the transitional MainWindowViewModel(AppSettings, IStartupTracer) constructor and the _ownsServices flag now that every caller resolves the view model from the container; the container owns and disposes the hardware monitor (driver unload), so the view model no longer disposes it. Make HardwareMonitorService.Dispose idempotent with a _disposed guard, and run provider disposal in a finally block in MainWindow_Closed so the ring0 driver is always unloaded on real exit even if an earlier teardown step throws.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 15:25:39 -05:00
JMR-devandCopilot 50a07d5ce9 Extract IHardwareMonitorService, ILogger, IRemoteWebServer interfaces
Define interfaces over the three domain services that the view model hard-news
today (the testability blocker). Concrete types implement the new interfaces;
no wiring or behavior change yet.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-02 15:00:30 -05:00
JMR-devandClaude Opus 4.8 268f15a19e Extract TreeRebuildCoalescer from HardwareMonitorService
Moves the hardware-change debounce/coalescing worker (the dirty/queued flags
and re-queue logic) into a dedicated class with an injectable delay, so the
concurrency behavior can be unit-tested deterministically instead of living as
an untestable fire-and-forget block in the service. Behavior is unchanged.

Adds 3 tests (single rebuild after delay, burst coalesced to one, no rebuild
when closed) driven by a controllable delay gate.

199 tests pass (was 196).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 11:06:52 -05:00
JMR-dev f9edc1dc64 Fixes applied (14 of 15 findings — see note on R5)
Concurrency crashes
  - H1 HardwareMonitorService.RebuildTree now builds the tree under _updateLock, so it can't enumerate a hardware's _active HashSet while the update loop mutates it.
  - A1 AppSettings now guards every dictionary read/write (and snapshots in Save) with a lock — safe under concurrent access from the parallel discovery threads.
  - R2 Plumbed that same lock (HardwareMonitorService.SensorReadLock) into RemoteWebServer and wrapped the Prometheus sensor.Values enumeration with it.
  - L1 Computer — refactored Add into AddCore, which performs the cancellation/enabled re-check and the _groups insertion atomically under _lock. A deferred task can
  no longer add (and leak) a group after Close() drained the list; if it loses the race it closes the group instead.
  - M1 UpdateTimer_Tick now bails before/after the await when _isShuttingDown is set in MainWindow_Closed, so an in-flight tick won't touch the disposed
  view-model/Computer.

  Broken behavior
  - T1 Tray callback now decodes NOTIFYICON_VERSION_4 correctly (message = LOWORD(lParam), icon id = HIWORD(lParam)) — right-click menu and double-click work again.
  - M2 A transient update exception no longer calls _timer.Stop(); the loop keeps running.
  - H2 Newly discovered (deferred) storage devices get the current ForceDriveWakeup setting applied in HardwareChanged.
  - V2 Sensor items carry a parent reference; toggling IsVisible recomputes the parent group's visibility, so no empty group headers. (Strengthened the existing test
  that had skipped this assertion.)
  - H3 Tree-rebuild coalescing now uses a dirty flag with a re-check, so a change arriving during a rebuild isn't lost.
  - R4 Web routing matches endpoints exactly on the query-stripped path (Url.AbsolutePath), so static assets like metrics.html aren't hijacked.
  - L8 IntelCpu.Update skips the bus/core-clock math while TimeStampCounterFrequency is still 0 (deferred-TSC window), so clocks keep their prior value instead of
  reporting 0 MHz.
  - V1 Existing plot series keep their assigned color; only an explicit user pen color updates them (no per-tick color shifting).
  - M3 Runtime errors write to a dedicated runtime.log (once), instead of overwriting the shared startup.log.
  - T2 CreateSensorIcon returns IntPtr.Zero on DIB failure instead of the shared main-icon handle (which callers DestroyIcon).

  I also set _isOpen = false in HardwareMonitorService.Dispose so the rebuild guard actually holds during shutdown (the latent after-close-rebuild issue adjacent to
  H3
2026-05-30 22:56:25 -05:00
JMR-dev a1cffce9fd MVP port complete 2026-05-30 19:47:04 -05:00
JMR-dev f8b9949187 performance optimizations - TSC estimation moved off blocking path 2026-05-30 18:55:12 -05:00
JMR-dev c50757868f WIP - optimizing start times 2026-05-30 18:37:39 -05:00
JMR-dev 2c176e5dd7 WIP - optimizing start times 2026-05-30 17:45:37 -05:00
JMR-dev b744f70b0b WIP - optimizing start times 2026-05-30 15:11:32 -05:00
JMR-dev 45bf81ebfa WIP - have working UI for base functions 2026-05-30 14:01:22 -05:00