akka.net icon indicating copy to clipboard operation
akka.net copied to clipboard

Enhancement: create ActorTaskScheduler overload that schedules Task to dispatcher without blocking current actor

Open Aaronontheweb opened this issue 4 years ago • 3 comments

Version: 1.4.3 and later

An advanced feature - right now we support the ability to schedule a Task onto the current actor's dispatcher using the ActorTaskScheduler:

https://github.com/akkadotnet/akka.net/blob/03341fc2e2157620abf5986473faa5f235723ca4/src/core/Akka/Dispatch/ActorTaskScheduler.cs#L130-L164

One of the side effects of this method is that it blocks the current actor in order to run that Task.

I think it'd be worthwhile to add an overload that allows a task to be scheduled onto the current dispatcher, without impacting the current actor's ability to process its mailbox. That could make for some interesting scenarios in areas like IOT, where users often need to run actors on pinned or dedicated thread dispatchers.

Aaronontheweb avatar Mar 31 '20 15:03 Aaronontheweb

If I understand it right, the feature to schedule a task without suspending the mailbox needs to be implemented. Would the new overloaded method need to take in an optional behavior parameter to become stacked? This is in case if the actor only wants to process certain kinds of messages while the task is running.

yesh-nadella avatar Apr 06 '20 22:04 yesh-nadella

@yesh-nadella I wouldn't bother with the second part - I'd leave it at "scheduler on the same dispatcher as me but don't block me"

Aaronontheweb avatar Apr 06 '20 22:04 Aaronontheweb

@Aaronontheweb I would really like a feature like that. We often have cases were we have actors where we have async sequences of commands, most of the time these commands wait for something external to happen (e.g. some IO message from the network). So some of those async methods can take multiple seconds. But we also want to support querying of the state of the actor (e.g. progress). In this case something like:

Receive<Messages.Req>(r => {
    MyAsyncMethod().PipeTo(Sender, Self);
});

private async Task<string> MyAsyncMethod(Messages.Req) {
....
}

can be done. But the same thing can be expressed like that too:

ReceiveAsync<Messages.Req>(async r => {
     var resp = await MyAsyncMethod(r);
     Sender.Tell(resp);
});

private async Task<string> MyAsyncMethod(Messages.Req) {
....
}

with the distinction that the first thing allows user-messages while processing the task and the second does not. By integrating this behaviour into an enum and putting it in the ReceiveAsync API the intent can be much clearer documented.

swimmesberger avatar Jul 08 '22 19:07 swimmesberger