Обработка исключений с помощью akka.net PipeTo() для задачи
Ссылаясь на документацию Akka.Net, используя PipeTo()
предпочтительнее при работе с асинхронными заданиями.
При работе с функцией, которая возвращает Task<T>
Я могу обработать событие сбоя, нет проблем.
Проблема в том, что при работе с функцией, которая не возвращает никакого типа, а только Task
один еще зовет PipeTo
функции, но вместо перегрузки, содержащей дескриптор сбоя, теперь он говорит следующее: "Поскольку у этой задачи нет результата, получателю будут переданы только исключения.".
Означает ли это, если у меня есть следующий код:
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; }
}
}
Мой актер:
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);
}
}
}
Чтобы перехватывать исключения в вышеупомянутом акторе, мне нужно добавить другой обработчик получения для обработки исключений, как, например, ниже:
Receive<Exception>(x => SomeExceptionHandler(x));
Это правильно? Если это так, нет необходимости в try {} catch {}
вокруг моего блока кода?
1 ответ
Если вы вызываете свою асинхронную операцию с PipeTo
, он не заблокирует ваш текущий путь выполнения кода. Это означает, что оператор try/catch никогда не будет выполнен (поскольку успех или неудача задачи, представляющей асинхронную операцию, будут перенаправлены на Self
).
Есть 2 способа обработки исключений, которые могут произойти во время выполнения асинхронной операции:
- использование
ReceiveAsync<>
вместоReceive<>
в сочетании с асинхронной лямбда - это позволит вам простоawait
для завершения асинхронной операции. Вы можете использовать try/catch в этом контексте, так как он будет работать как положено. Имейте в виду, что это будет держать вашего актера не реентерабельным - это означает, что актер не будет обрабатывать никаких сообщений, пока текущая асинхронная операция не завершится. - Держать
PipeTo
и добавить ещеReceive<>
обработчик в вашей логике - в случае сбоя асинхронной операции переноса задачи исключение будет заключено в сообщение и перенаправлено обратно вPipeTo
цель (Self
в твоем случае). По умолчанию исключения, созданные таким способом, оборачиваются вStatus.Failure
сообщение - в этом случае вам нужно добавитьReceive<Status.Failure>
обработчик в вашем актере. Вы также можете указать собственный конструктор сообщений, используемый для обработкиPipeTo
неудачи то есть:_repoComponent.InsertJobAsync(input).PipeTo(Context.Self, failure: exception => new MyErrorMessage(exception))