fix(communication): streaming endpoint lookups are generation-fenced and cannot strand their in-flight guards (review 2026-10-21 03/R-2 follow-up)
This commit is contained in:
@@ -374,6 +374,8 @@ public class DebugStreamBridgeActor : ReceiveActor, IWithTimers
|
||||
_resolveInFlight = false;
|
||||
if (_stopped) return;
|
||||
ApplyResolvedEndpoints(msg);
|
||||
// A stream was opened while the lookup ran (generation moved on): don't open a second.
|
||||
if (msg.Generation != _streamGeneration) return;
|
||||
OpenGrpcStream();
|
||||
});
|
||||
|
||||
@@ -649,16 +651,24 @@ public class DebugStreamBridgeActor : ReceiveActor, IWithTimers
|
||||
|
||||
_resolveInFlight = true;
|
||||
var resolver = _endpointResolver;
|
||||
var generation = _streamGeneration;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
using var cts = new CancellationTokenSource(EndpointResolveTimeout);
|
||||
// CTS creation inside the try: any fault must still report back, or the in-flight
|
||||
// guards would never release.
|
||||
CancellationTokenSource? cts = null;
|
||||
try
|
||||
{
|
||||
return new SiteStreamEndpointsResolved(await resolver(cts.Token).ConfigureAwait(false), null);
|
||||
cts = new CancellationTokenSource(EndpointResolveTimeout);
|
||||
return new SiteStreamEndpointsResolved(await resolver(cts.Token).ConfigureAwait(false), null, generation);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new SiteStreamEndpointsResolved(null, ex);
|
||||
return new SiteStreamEndpointsResolved(null, ex, generation);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cts?.Dispose();
|
||||
}
|
||||
}).PipeTo(Self);
|
||||
}
|
||||
|
||||
@@ -479,6 +479,8 @@ public sealed class SiteAlarmAggregatorActor : ReceiveActor, IWithTimers
|
||||
_resolveInFlight = false;
|
||||
if (_stopped) return;
|
||||
ApplyResolvedEndpoints(msg);
|
||||
// A stream was opened while the lookup ran (generation moved on): don't open a second.
|
||||
if (msg.Generation != _streamGeneration) return;
|
||||
OpenGrpcStream();
|
||||
});
|
||||
|
||||
@@ -933,17 +935,25 @@ public sealed class SiteAlarmAggregatorActor : ReceiveActor, IWithTimers
|
||||
_openInFlight = true;
|
||||
var resolver = _endpointResolver;
|
||||
var lifetime = _lifetimeCts?.Token ?? CancellationToken.None;
|
||||
var generation = _streamGeneration;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(lifetime);
|
||||
cts.CancelAfter(EndpointResolveTimeout);
|
||||
// CTS creation inside the try: any fault must still report back, or the in-flight
|
||||
// guards would never release.
|
||||
CancellationTokenSource? cts = null;
|
||||
try
|
||||
{
|
||||
return new SiteStreamEndpointsResolved(await resolver(cts.Token).ConfigureAwait(false), null);
|
||||
cts = CancellationTokenSource.CreateLinkedTokenSource(lifetime);
|
||||
cts.CancelAfter(EndpointResolveTimeout);
|
||||
return new SiteStreamEndpointsResolved(await resolver(cts.Token).ConfigureAwait(false), null, generation);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new SiteStreamEndpointsResolved(null, ex);
|
||||
return new SiteStreamEndpointsResolved(null, ex, generation);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cts?.Dispose();
|
||||
}
|
||||
}).PipeTo(Self);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user