From 71ed9d9f3d3c94f2bd78b9a4cca34edba2b9f8eb Mon Sep 17 00:00:00 2001 From: Ziya Suzen Date: Sun, 13 Oct 2024 02:32:12 +0100 Subject: [PATCH] Refactor JetStream method results to use NatsResult --- src/NATS.Client.Core/NatsResult.cs | 38 ++++++++++++++++++++++ src/NATS.Client.JetStream/NatsJSContext.cs | 29 ++++++++--------- 2 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 src/NATS.Client.Core/NatsResult.cs diff --git a/src/NATS.Client.Core/NatsResult.cs b/src/NATS.Client.Core/NatsResult.cs new file mode 100644 index 00000000..3b246aa6 --- /dev/null +++ b/src/NATS.Client.Core/NatsResult.cs @@ -0,0 +1,38 @@ +using System.Runtime.CompilerServices; + +namespace NATS.Client.Core; + +public readonly struct NatsResult +{ + private readonly T? _value; + private readonly Exception? _error; + + public NatsResult(T value) + { + _value = value; + _error = null; + } + + public NatsResult(Exception error) + { + _value = default; + _error = error; + } + + public T Value => _value ?? ThrowValueIsNotSetException(); + + public Exception Error => _error ?? ThrowErrorIsNotSetException(); + + public bool Success => _error == null; + + public static implicit operator NatsResult(T value) => new(value); + + public static implicit operator NatsResult(Exception error) => new(error); + + private static T ThrowValueIsNotSetException() => throw CreateInvalidOperationException("Result value is not set"); + + private static Exception ThrowErrorIsNotSetException() => throw CreateInvalidOperationException("Result error is not set"); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Exception CreateInvalidOperationException(string message) => new InvalidOperationException(message); +} diff --git a/src/NATS.Client.JetStream/NatsJSContext.cs b/src/NATS.Client.JetStream/NatsJSContext.cs index 3a1d6ac4..c90f225e 100644 --- a/src/NATS.Client.JetStream/NatsJSContext.cs +++ b/src/NATS.Client.JetStream/NatsJSContext.cs @@ -287,19 +287,16 @@ internal async ValueTask> JSRequestAsync(subject, request, cancellationToken).ConfigureAwait(false); - if (exception != null) + var result = await TryJSRequestAsync(subject, request, cancellationToken).ConfigureAwait(false); + if (!result.Success) { - throw exception; + throw result.Error; } - if (response != null) - return response.Value; - - throw new Exception("State error: No response received"); + return result.Value; } - internal async ValueTask<(NatsJSResponse?, Exception?)> TryJSRequestAsync( + internal async ValueTask>> TryJSRequestAsync( string subject, TRequest? request, CancellationToken cancellationToken = default) @@ -330,7 +327,7 @@ internal async ValueTask> JSRequestAsync> JSRequestAsync(default, error), default); + return new NatsJSResponse(default, error); } var jsonTypeInfo = NatsJSJsonSerializerContext.DefaultContext.GetTypeInfo(typeof(TResponse)); if (jsonTypeInfo == null) { - return (default, new NatsJSException($"Unknown response type {typeof(TResponse)}")); + return new NatsJSException($"Unknown response type {typeof(TResponse)}"); } var response = (TResponse?)jsonDocument.RootElement.Deserialize(jsonTypeInfo); if (msg.Error is { } messageError) { - return (default, messageError); + return messageError; } - return (new NatsJSResponse(response, default), default); + return new NatsJSResponse(response, default); } if (sub is NatsSubBase { EndReason: NatsSubEndReason.Exception, Exception: not null } sb) { - return (default, sb.Exception); + return sb.Exception; } if (sub.EndReason != NatsSubEndReason.None) { - return (default, new NatsJSApiNoResponseException(sub.EndReason)); + return new NatsJSApiNoResponseException(sub.EndReason); } - return (default, new NatsJSApiNoResponseException()); + return new NatsJSApiNoResponseException(); } private static void ConvertDomain(StreamSource streamSource)