I recently found out about a nuget called LanguageExt.Core
and why it is not so efficient to throw exceptions while handling them via middleware or so.
Speaking of it, I would like to know what is the best way to simply check if the result has faulted, so I can throw the exception in order to trigger Polly's retry pattern logic.
The best I could think of:
private async Task RunAsync(Uri uri)
{
await ConnectAsync(uri);
var result = await ConnectAsync(uri);
if (result.IsFaulted)
{
// Cannot access result.Exception because it's internal
}
_ = result.IfFail(ex =>
{
_logger.LogError(ex, "Error while connecting to the endpoint");
throw ex;
});
...
private async Task<Result<Unit>> ConnectAsync(Uri uri)
{
if (_ws is not null)
{
return new Result<Unit>(new InvalidOperationException("The websocket client is already connected"));
}
var ws = Options.ClientFactory();
try
{
using var connectTimeout = new CancellationTokenSource(Options.Timeout);
await ws.ConnectAsync(uri, connectTimeout.Token).ConfigureAwait(false);
}
catch
{
ws.Dispose();
return new Result<Unit>(new InvalidOperationException("Failed to connect to the endpoint"));
}
await _connectedEvent.InvokeAsync(new ConnectedEventArgs(uri));
_ws = ws;
IsRunning = true;
return Unit.Default;
}
Based on the comments it seems like that ConnectAsync
can fail with an InvalidOperationException
inside a Result
object. In this particular case the Result
's IsFaulted
is set to true
only if an IOE
is passed to the Result
's ctor.
So, if you want to perform a retry then you should define your policy something like this:
var retryPolicy = Policy<Result<Unit>>
.HandleResult(r => r.IsFaulted)
.WaitAndRetryAsync(...)