mishima-nexus-client-csharp/src/Robotico.Nexus.Client/NexusWireStatus.cs

69 lines
3.3 KiB
C#
Raw Normal View History

using Grpc.Core;
using Mishima.Nexus.Wire.V1;
using Robotico.Result.Errors;
namespace Robotico.Nexus.Client;
/// <summary>Maps <see cref="NexusStatus"/> wire envelopes and gRPC failures to <see cref="Robotico.Result.Result"/>.</summary>
internal static class NexusWireStatus
{
private const string OkCode = "OK";
/// <summary>Returns success when <paramref name="status"/> reports <c>OK</c>; otherwise a coded error.</summary>
internal static Robotico.Result.Result ToResult(NexusStatus? status)
{
if (status is null)
{
return Robotico.Result.Result.Error(NexusErrors.Error("Nexus response is missing a status envelope.", NexusErrors.WireFailed));
}
if (string.Equals(status.Code, OkCode, StringComparison.Ordinal))
{
return Robotico.Result.Result.Success();
}
string code = string.IsNullOrWhiteSpace(status.Code) ? NexusErrors.WireFailed : status.Code;
string message = string.IsNullOrWhiteSpace(status.Message) ? "Nexus call failed." : status.Message;
return Robotico.Result.Result.Error(NexusErrors.Error(message, code));
}
/// <summary>Maps status to <see cref="Robotico.Result.Result{T}"/>, carrying <paramref name="value"/> on success.</summary>
internal static Robotico.Result.Result<T> ToResult<T>(NexusStatus? status, T value)
{
Robotico.Result.Result plain = ToResult(status);
return plain.IsError(out IError? error) ? Robotico.Result.Result.Error<T>(error!) : Robotico.Result.Result.Success(value);
}
/// <summary>True when <paramref name="status"/> reports <c>OK</c>.</summary>
internal static bool IsOk(NexusStatus? status) =>
status is not null && string.Equals(status.Code, OkCode, StringComparison.Ordinal);
/// <summary>Maps a failed gRPC call into a coded <see cref="IError"/>.</summary>
internal static IError FromException(RpcException exception)
{
string code = exception.StatusCode switch
{
StatusCode.OK => NexusErrors.WireFailed,
StatusCode.Cancelled => NexusErrors.Unavailable,
StatusCode.Unknown => NexusErrors.WireFailed,
StatusCode.InvalidArgument => NexusErrors.InvalidArgument,
StatusCode.DeadlineExceeded => NexusErrors.Unavailable,
StatusCode.NotFound => NexusErrors.NotFound,
StatusCode.AlreadyExists => NexusErrors.AlreadyExists,
StatusCode.PermissionDenied => NexusErrors.WireFailed,
StatusCode.ResourceExhausted => NexusErrors.Unavailable,
StatusCode.FailedPrecondition => NexusErrors.InvalidArgument,
StatusCode.Aborted => NexusErrors.WireFailed,
StatusCode.OutOfRange => NexusErrors.InvalidArgument,
StatusCode.Unimplemented => NexusErrors.WireFailed,
StatusCode.Internal => NexusErrors.WireFailed,
StatusCode.Unavailable => NexusErrors.Unavailable,
StatusCode.DataLoss => NexusErrors.WireFailed,
StatusCode.Unauthenticated => NexusErrors.WireFailed,
_ => NexusErrors.WireFailed,
};
string detail = string.IsNullOrWhiteSpace(exception.Status.Detail) ? exception.Message : exception.Status.Detail;
return NexusErrors.Error($"gRPC call failed ({exception.StatusCode}): {detail}", code);
}
}