Files
mxaccessgw/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardCircuitConnectionTracker.cs
T
Joseph Doherty db7833609d fix(dashboard): debounced off-dispatcher Browse search, bounded disposal, circuit-aware polling
- Search: the oninput setter scanned the whole Galaxy synchronously per
  keystroke. It now debounces 150ms, runs on the thread pool with
  cancellation (newer keystroke supersedes), and reads a shared singleton
  DashboardBrowseSearchIndex of pre-lowercased references keyed on the
  Galaxy cache Sequence.
- Disposal: DisposeAsync awaited both loops unbounded and the loops caught
  only OCE. Loops now handle faults per iteration (poll faults surface in
  _readError, deploy-notifier faults in a retrying warning), mutate the tree
  on the dispatcher, drain concurrently with a 5s bound, and the CTSs are
  disposed in finally.
- Circuits: DisconnectedCircuitRetentionPeriod is 30s (was the 3 min
  default) and a scoped DashboardCircuitConnectionTracker (CircuitHandler)
  lets the 2s ReadBulk poll skip ticks while the browser is disconnected.
- Reads pass a per-page viewer id to the live-data per-viewer share.
2026-10-22 06:25:46 -04:00

43 lines
1.6 KiB
C#

using Microsoft.AspNetCore.Components.Server.Circuits;
namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
/// <summary>
/// Per-circuit view of whether the browser is still attached. Registered scoped, so a
/// page injecting it sees its own circuit, and also registered as that circuit's
/// <see cref="CircuitHandler"/> so Blazor drives it.
/// </summary>
/// <remarks>
/// A closed or backgrounded browser tab leaves its circuit alive, disconnected, for
/// <see cref="DashboardServiceCollectionExtensions.DisconnectedCircuitRetention"/>
/// before Blazor disposes it, and every timer on the page keeps running in that
/// window. The Browse page's two-second <c>ReadBulk</c> poll is the costly one — it
/// drives the shared dashboard worker — so it skips its tick while
/// <see cref="IsConnected"/> is false and resumes on reconnect.
/// </remarks>
public sealed class DashboardCircuitConnectionTracker : CircuitHandler
{
private volatile bool _connected = true;
/// <summary>
/// Gets a value indicating whether the circuit's browser connection is up. True
/// until Blazor reports the connection down, and also outside a circuit (prerender),
/// where no handler callbacks ever arrive.
/// </summary>
public bool IsConnected => _connected;
/// <inheritdoc />
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
_connected = true;
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
_connected = false;
return Task.CompletedTask;
}
}