chore(deps): pin ZB.MOM.WW.LocalDb 0.3.8 (scadaproj#57)

LocalDb 0.3.8 ends open sync streams on ApplicationStopping and refuses
new ones Unavailable while stopping (lmxopcua#906, library side). The
host-side ShutdownStreamCancellationInterceptor (#140) stays.

GracefulStopWithOpenSyncStreamTests' positive control passed the stop
in ~900 ms under 0.3.8, because the library alone now ends the stream.
The control registers LocalDbSyncService without the host lifetime (the
0.3.7 behaviour), so it still reproduces the 8 s drain; verified it
fails on 0.3.8 without that change.

Release build 0 warnings. Host.Tests 733/733, IntegrationTests 133/133
(incl. the LocalDb site-pair convergence tests), Communication.Tests
843/843, HealthMonitoring.Tests 131/131, SiteEventLogging.Tests 118/118.

Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
Joseph Doherty
2026-11-13 07:08:59 -05:00
parent 1a6108c402
commit 8e32f3538c
2 changed files with 20 additions and 4 deletions
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -46,7 +47,8 @@ namespace ZB.MOM.WW.ScadaBridge.IntegrationTests;
/// <para>
/// The second test is the positive control: the same stack as it was before the fix — the Akka service
/// seen by the host as a plain <see cref="IHostedService"/> (so its shutdown runs only in
/// <c>StopAsync</c>) and no stream interceptor — reproduces the bug: the stop waits out the whole
/// <c>StopAsync</c>), no stream interceptor, and the LocalDb sync service built without the host
/// lifetime (LocalDb 0.3.8 would otherwise end the stream itself) — reproduces the bug: the stop waits out the whole
/// shutdown timeout and the cluster is left only after the drain. Without it, a fast stop in the first
/// test could be a harness that never held a stream open at all.
/// </para>
@@ -197,6 +199,20 @@ public sealed class GracefulStopWithOpenSyncStreamTests
});
builder.Services.AddSingleton(db);
builder.Services.AddZbLocalDbReplication(ReplicationConfig(peerAddress: null));
if (!withFix)
{
// From LocalDb 0.3.8 the library itself ends open sync streams on ApplicationStopping
// (scadaproj#57), which would hide the drain in this control. Re-register the service
// WITHOUT the host lifetime, i.e. the 0.3.7 behaviour, so the control still reproduces
// the bug the host-side fix guards against.
builder.Services.Replace(ServiceDescriptor.Singleton(sp => new LocalDbSyncService(
sp.GetRequiredService<ILocalDb>(),
sp.GetRequiredService<IOptions<ReplicationOptions>>(),
sp.GetRequiredService<ILoggerFactory>(),
sp.GetService<LocalDbMetrics>(),
sp.GetService<ISyncStatus>(),
lifetime: null)));
}
// The production AkkaHostedService, registered the way Program/SiteServiceRegistration do.
// Role "StopProbe" (neither Central nor Site) makes StartAsync register only the dead-letter