using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using ZB.MOM.WW.MxGateway.Server.Configuration;
namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
///
/// SignalR hub that pushes a fresh on every
/// snapshot refresh. New connections receive the effective configuration and the
/// current snapshot immediately via ; subsequent
/// refreshes are broadcast by without the
/// configuration, which is startup-static and serialized only once per connection.
///
///
/// Connections are counted into
/// so can stop building and broadcasting
/// snapshots while nobody is watching.
///
[Authorize(Policy = DashboardAuthenticationDefaults.HubClientsPolicy)]
public sealed class DashboardSnapshotHub(
IDashboardSnapshotService snapshotService,
DashboardSnapshotHubConnectionCounter connectionCounter) : Hub
{
/// Method name used to push snapshot updates to clients.
public const string SnapshotMessage = "SnapshotUpdated";
///
/// Method name of the one-per-connection effective-configuration push. Snapshot
/// ticks omit the configuration, so a client keeps the copy it got here.
///
public const string ConfigurationMessage = "ConfigurationUpdated";
///
/// Returns the effective gateway configuration — the same object
/// carries — for a client that needs it again.
///
/// The effective configuration.
public EffectiveGatewayConfiguration GetConfiguration() => snapshotService.GetSnapshot().Configuration;
///
public override async Task OnConnectedAsync()
{
// Count the viewer before seeding it, so the publisher resumes its tick
// no later than the first snapshot this connection renders.
connectionCounter.Increment();
DashboardSnapshot snapshot = snapshotService.GetSnapshot();
await Clients.Caller.SendAsync(ConfigurationMessage, snapshot.Configuration).ConfigureAwait(false);
await Clients.Caller.SendAsync(SnapshotMessage, snapshot).ConfigureAwait(false);
await base.OnConnectedAsync().ConfigureAwait(false);
}
///
public override async Task OnDisconnectedAsync(Exception? exception)
{
connectionCounter.Decrement();
await base.OnDisconnectedAsync(exception).ConfigureAwait(false);
}
}