fix(runtime): capture Sender before await in DriverInstanceActor subscribe (no-ActorContext race)
This commit is contained in:
@@ -327,7 +327,7 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
try
|
||||
{
|
||||
var results = await writable.WriteAsync(request, cts.Token).ConfigureAwait(false);
|
||||
var results = await writable.WriteAsync(request, cts.Token);
|
||||
if (results is { Count: 1 } && IsGoodStatus(results[0].StatusCode))
|
||||
{
|
||||
replyTo.Tell(new WriteAttributeResult(true, null));
|
||||
@@ -348,19 +348,24 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
|
||||
private async Task HandleSubscribeAsync(Subscribe msg)
|
||||
{
|
||||
// Capture Sender/Self BEFORE any await. The re-subscribe path below awaits
|
||||
// UnsubscribeAsync, and a real async backend can resume the continuation off Akka's
|
||||
// ActorContext — reading raw Sender/Self/Context past that point throws
|
||||
// NotSupportedException ("no active ActorContext"). Keep ConfigureAwait off the awaits
|
||||
// in this handler so continuations resume on the actor context.
|
||||
var replyTo = Sender;
|
||||
var self = Self;
|
||||
if (_driver is not ISubscribable subscribable)
|
||||
{
|
||||
Sender.Tell(new SubscriptionFailed("Driver does not implement ISubscribable"));
|
||||
replyTo.Tell(new SubscriptionFailed("Driver does not implement ISubscribable"));
|
||||
return;
|
||||
}
|
||||
if (_subscriptionHandle is not null)
|
||||
{
|
||||
// Subscribe-twice — drop the prior subscription before establishing the new one.
|
||||
await UnsubscribeAsync().ConfigureAwait(false);
|
||||
await UnsubscribeAsync();
|
||||
}
|
||||
|
||||
var replyTo = Sender;
|
||||
var self = Self;
|
||||
try
|
||||
{
|
||||
_dataChangeHandler = (_, args) => self.Tell(new DataChangeForward(args.FullReference, args.Snapshot));
|
||||
@@ -368,8 +373,7 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
|
||||
_subscriptionHandle = await subscribable
|
||||
.SubscribeAsync(msg.FullReferences, msg.PublishingInterval, cts.Token)
|
||||
.ConfigureAwait(false);
|
||||
.SubscribeAsync(msg.FullReferences, msg.PublishingInterval, cts.Token);
|
||||
|
||||
replyTo.Tell(new SubscriptionEstablished(_subscriptionHandle.DiagnosticId, msg.FullReferences.Count));
|
||||
_log.Info("DriverInstance {Id}: subscribed to {Count} refs ({Diag})",
|
||||
@@ -393,7 +397,7 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
await subscribable.UnsubscribeAsync(_subscriptionHandle, cts.Token).ConfigureAwait(false);
|
||||
await subscribable.UnsubscribeAsync(_subscriptionHandle, cts.Token);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user