-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Version Information
Version of Akka.NET? 1.4.46, 1.5.0-alpha3
Which Akka.NET Modules? Akka.Actor
Describe the bug
When using the following ReceiveAsync statement, the Sender.Tell crashes with an System.NotSupportedException:
ReceiveAsync<SubscribeToEnvironment>(async cmd =>
{
// NOTE: can't throw here - one subscription failing shouldn't blow up any of the others
// create a ChannelReader, from which we'll create an IAsyncEnumerable in the service
var (reader, sink) = ChannelSink.AsReader<IEnvironmentEvent>(100, true, BoundedChannelFullMode.DropOldest)
.PreMaterialize(Context.Materializer());
var (sinkRefTask, killSwitch) = StreamRefs.SinkRef<IEnvironmentEvent>()
.ViaMaterialized(KillSwitches.Single<IEnvironmentEvent>(), Keep.Both)
.Via(cmd.CancellationToken.AsFlow<IEnvironmentEvent>())
.To(sink)
.Run(Context.Materializer());
try
{
using var cts = new CancellationTokenSource(_subscriptionTimeout);
var sinkRef = await sinkRefTask.WaitAsync(cts.Token).ConfigureAwait(false);
var resp = await _clusterStateActor.ExecuteCommand(
new SubscriptionCommands.SubscribeToClusterEvents(_subscriberId, cmd.EnvironmentId, sinkRef),
cts.Token).ConfigureAwait(false);
if (resp.Status == ResponseStatus.Success)
{
Sender.Tell(new SubscribeSuccess(cmd.EnvironmentId, reader));
}
else // no-ops are failures here - no guarantee that the new stream is going to run
{
// deliver SubscribeFailed to the client
Sender.Tell(new SubscribeFailed(cmd.EnvironmentId, resp.Message));
// kill the stream
killSwitch.Shutdown();
}
}
catch (Exception ex)
{
_log.Error(ex, "Failed to create subscription for [EnvironmentId: {0}]", cmd.EnvironmentId);
Sender.Tell(new SubscribeFailed(cmd.EnvironmentId, ex.Message));
killSwitch.Abort(ex);
}
});The exception thrown:
System.NotSupportedException: There is no active ActorContext, this is most likely due to use of async operations from within this actor.
at Akka.Actor.ActorBase.get_Context()
at Akka.Actor.ActorBase.get_Sender()
at OpsCenter.ClusterState.Subscriptions.SubscriptionManager.<.ctor>b__9_0(SubscribeToEnvironment cmd) in D:\Repositories\Petabridge\OpsCenter\opscenter-blazor-prototype\src\OpsCenter.ClusterState\Subscriptions\SubscriptionManager.cs:line 94
To Reproduce
Working on this - not sure which part is causing this. await-ing inside ReceiveAsync is pretty common and shouldn't cause issues. I'm wondering if it's WaitAsync combined with ConfigureAwait(false) that is causing the antecedent Task to execute outside of the actor's built-in scheduler.
Expected behavior
Actor should be executing with a valid IActorContext and should be able to access the Sender, Self,, Parent, and Children properties without throwing.
Actual behavior
Actor crashes upon accessing the Sender property.
Additional context
We dealt with lots of issues like this one back in the 2015 era of Akka.NET - so this it's something with the way this code works that is causing it to throw.