Referring to Akka.Net documentation, using PipeTo()
is preferred when dealing with asynchronous jobs.
When dealing with a function that returns Task<T>
, I can handle the failure event, no problem.
The problem is, when dealing with a function that does not return any type, but only Task
, one still calls the PipeTo
function, but instead of having the overload which contains the failure handle, it now says the following: 'As this task has no result, only exceptions will be piped to the recipient.'.
Does this mean, if I have the following code:
public class RepositoryComponent : IRepositoryComponent
{
private SqlSettings _sqlSettings;
public RepositoryComponent(SqlSettings sqlSettings)
{
_sqlSettings = sqlSettings;
}
public async Task InsertJobAsync(RetryModel job)
{
try
{
await... //some logic
}
catch { throw; }
}
}
My actor:
public class RepositoryActor : ActorBase
{
private IRepositoryComponent _repoComponent;
private ActorSelection _retryActor;
public RepositoryActor(IRepositoryComponent repoComponent) : base()
{
_repoComponent = repoComponent;
}
public override void Listening()
{
Receive<RepositoryMessages.GenericRequestNoReturn>(x => InvokeRequest(x));
Receive<RepositoryMessages.GenericRequestWithResponseType>(x => InvokeRequestAndSendResponse(x));
}
private void InvokeRequest(RepositoryMessages.GenericRequestNoReturn msg)
{
try
{
//some logic with msg
_repoComponent.InsertJobAsync(new Core.Models.RetryModel()).PipeTo(Context.Self);
}
catch (Exception ex)
{
base.ExceptionHandling(ex);
}
}
}
In order to catch exceptions in the above actor, I need to add another Receive handler to cater for exceptions, as for example, below:
Receive<Exception>(x => SomeExceptionHandler(x));
Is this correct? If so, no need for the try {} catch {}
around my code block?
If you're calling your asynchronous operation with PipeTo
, it won't block your current code execution path. This means that the try/catch statement will never be executed (as success or failure of the task representing asynchronous operation will be redirected to Self
).
There are 2 ways to handle exceptions that may happen during async operation execution:
ReceiveAsync<>
instead of Receive<>
in combination with async lambda - this will allow you to simply await
for asynchronous operation to complete. You're free to use try/catch in this context, as it will work as expected. Keep in mind that this will keep your actor non-reentrant - it means, that the actor will not process any messages until current asynchronous operation completes.PipeTo
and add another Receive<>
handler in your logic - in case when a task wrapping asynchronous operation will fail, the exception will be wrapped into a message and redirected back to PipeTo
's target (Self
in your case). By default exceptions produced this way are wrapped in Status.Failure
message - in this case you'd need to add Receive<Status.Failure>
handler in your actor. You can also specify a custom message constructor used to handle PipeTo
failures i.e.: _repoComponent.InsertJobAsync(input).PipeTo(Context.Self, failure: exception => new MyErrorMessage(exception))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With