diff --git a/Fauna.Test/Client.Tests.cs b/Fauna.Test/Client.Tests.cs index 73ff5607..f92fd2a5 100644 --- a/Fauna.Test/Client.Tests.cs +++ b/Fauna.Test/Client.Tests.cs @@ -1,4 +1,5 @@ using Fauna.Constants; +using Fauna.Exceptions; using Fauna.Serialization; using NUnit.Framework; using System.Buffers; @@ -85,13 +86,13 @@ public async Task CreateClientError() try { - var r = await c.QueryAsync( + var r = await c.QueryAsync( new QueryExpr(new QueryLiteral($"let x = {expected}; abort(x)")), new QueryOptions { QueryTags = new Dictionary { { "foo", "bar" }, { "baz", "luhrmann" } } }); } - catch (FaunaAbortException ex) + catch (AbortException ex) { - var abortData = ex.GetData(); + var abortData = ex.GetData(); Assert.AreEqual("abort", ex.QueryFailure?.ErrorInfo.Code); Assert.IsInstanceOf(abortData); Assert.AreEqual(expected, abortData); @@ -132,9 +133,9 @@ public async Task AbortReturnsQueryFailureAndThrows() var query = new QueryExpr(new QueryLiteral($"let x = {expected}; abort(x)")); var r = await c.QueryAsync(query); } - catch (FaunaAbortException ex) + catch (AbortException ex) { - var abortData = ex.GetData(); + var abortData = ex.GetData(); Assert.AreEqual("abort", ex.QueryFailure?.ErrorInfo.Code); Assert.IsInstanceOf(abortData); Assert.AreEqual(expected, abortData); diff --git a/Fauna.Test/Exceptions/AbortException.Tests.cs b/Fauna.Test/Exceptions/AbortException.Tests.cs new file mode 100644 index 00000000..2d65401c --- /dev/null +++ b/Fauna.Test/Exceptions/AbortException.Tests.cs @@ -0,0 +1,143 @@ +using Fauna.Exceptions; +using NUnit.Framework; + +namespace Fauna.Tests; + +[TestFixture] +public class AbortExceptionTests +{ + private class TestClass + { + public string Name { get; set; } + public int Age { get; set; } + + } + + [Test] + public void Ctor_InitializesPropertiesCorrectly() + { + var expectedQueryFailure = CreateQueryFailure(@"{{\""@int\"":\""123\""}}"); + var expectedMessage = "Test message"; + var expectedInnerException = new Exception("Inner exception"); + + var actual1 = new AbortException(expectedQueryFailure, expectedMessage); + var actual2 = new AbortException(expectedQueryFailure, expectedMessage, expectedInnerException); + + Assert.AreEqual(expectedQueryFailure.ErrorInfo.Abort, actual1.QueryFailure.ErrorInfo.Abort); + Assert.AreEqual(expectedMessage, actual1.Message); + + Assert.AreEqual(expectedQueryFailure.ErrorInfo.Abort, actual2.QueryFailure.ErrorInfo.Abort); + Assert.AreEqual(expectedMessage, actual2.Message); + Assert.AreEqual(expectedInnerException, actual2.InnerException); + } + + [Test] + public void GetData_WithIntData_ReturnsDeserializedObject() + { + var expected = 123; + var queryFailure = CreateQueryFailure(@$"{{\""@int\"":\""{expected}\""}}"); + var exception = new AbortException(queryFailure, "Test message"); + + var actual = exception.GetData(); + + Assert.IsNotNull(actual); + Assert.IsInstanceOf(actual); + Assert.AreEqual(expected, (int)actual!); + } + + + [Test] + public void GetDataT_WithIntData_ReturnsDeserializedTypedObject() + { + var expected = 123; + var queryFailure = CreateQueryFailure(@$"{{\""@int\"":\""{expected}\""}}"); + var exception = new AbortException(queryFailure, "Test message"); + + var actual = exception.GetData(); + + Assert.IsNotNull(actual); + Assert.AreEqual(expected, actual); + } + + [Test] + public void GetData_WithPocoData_ReturnsDeserializedObject() + { + var expected = new TestClass { Name = "John", Age = 105 }; + var queryFailure = CreateQueryFailure(@$"{{\""@object\"":{{\""Name\"":\""{expected.Name}\"",\""Age\"":{{\""@int\"":\""{expected.Age}\""}}}}}}"); + var exception = new AbortException(queryFailure, "Test message"); + + var actual = exception.GetData() as IDictionary; + + Assert.IsNotNull(actual); + Assert.AreEqual(expected.Name, actual["Name"]); + Assert.AreEqual(expected.Age, actual["Age"]); + } + + [Test] + public void GetDataT_WithPocoData_ReturnsDeserializedTypedObject() + { + var expected = new TestClass { Name = "John", Age = 105 }; + var queryFailure = CreateQueryFailure(@$"{{\""@object\"":{{\""Name\"":\""{expected.Name}\"",\""Age\"":{{\""@int\"":\""{expected.Age}\""}}}}}}"); + var exception = new AbortException(queryFailure, "Test message"); + + var actual = exception.GetData(); + + Assert.IsNotNull(actual); + Assert.AreEqual(expected.Name, actual.Name); + Assert.AreEqual(expected.Age, actual.Age); + } + + [Test] + public void GetData_WithNullAbortData_ReturnsNull() + { + var queryFailure = CreateQueryFailure(null); + var exception = new AbortException(queryFailure, "Test message"); + + var result = exception.GetData(); + + Assert.IsNull(result); + } + + [Test] + public void GetData_CachesDataCorrectly() + { + var mockData = new TestClass { Name = "John", Age = 105 }; + var queryFailure = CreateQueryFailure(@$"{{\""@object\"":{{\""Name\"":\""{mockData.Name}\"",\""Age\"":{{\""@int\"":\""{mockData.Age}\""}}}}}}"); + var exception = new AbortException(queryFailure, "Test message"); + + var callResult1 = exception.GetData(); + var typedCallResult1 = exception.GetData(); + var callResult2 = exception.GetData(); + var typedCallResult2 = exception.GetData(); + + Assert.AreSame(callResult1, callResult2); + Assert.AreSame(typedCallResult1, typedCallResult2); + Assert.AreNotSame(callResult1, typedCallResult1); + Assert.AreNotSame(callResult2, typedCallResult2); + } + + private QueryFailure CreateQueryFailure(string abortData) + { + var rawResponseText = $@"{{ + ""error"": {{ + ""code"": ""abort"", + ""message"": ""Query aborted."", + ""abort"": ""{abortData}"" + }}, + ""summary"": ""error: Query aborted."", + ""txn_ts"": 1702346199930000, + ""stats"": {{ + ""compute_ops"": 1, + ""read_ops"": 0, + ""write_ops"": 0, + ""query_time_ms"": 105, + ""contention_retries"": 0, + ""storage_bytes_read"": 261, + ""storage_bytes_write"": 0, + ""rate_limits_hit"": [] + }}, + ""schema_version"": 0 + }}"; + return new QueryFailure(rawResponseText); + } +} \ No newline at end of file diff --git a/Fauna/Client/Client.cs b/Fauna/Client/Client.cs index fc1bb4c3..d9fdd040 100644 --- a/Fauna/Client/Client.cs +++ b/Fauna/Client/Client.cs @@ -1,4 +1,5 @@ using Fauna.Constants; +using Fauna.Exceptions; using Fauna.Serialization; namespace Fauna; @@ -34,7 +35,7 @@ public async Task> QueryAsync( { if (query == null) { - throw new FaunaClientException("Query cannot be null"); + throw new ClientException("Query cannot be null"); } var finalOptions = QueryOptions.GetFinalQueryOptions(_config.DefaultQueryOptions, queryOptions); @@ -51,29 +52,35 @@ public async Task> QueryAsync( throw failure.ErrorInfo.Code switch { - // Authentication Errors - "unauthorized" => new FaunaServiceException(FormatMessage("Unauthorized"), failure), + // Auth Errors + "unauthorized" => new AuthenticationException(failure, FormatMessage("Unauthorized")), + "forbidden" => new AuthorizationException(failure, FormatMessage("Forbidden")), // Query Errors - "invalid_query" => new FaunaQueryCheckException(FormatMessage("Invalid Query"), failure), - "invalid_argument" => new FaunaQueryRuntimeException(FormatMessage("Invalid Argument"), failure), - "abort" => new FaunaAbortException(FormatMessage("Abort"), failure), + "invalid_query" or + "invalid_function_definition" or + "invalid_identifier" or + "invalid_syntax" or + "invalid_type" => new QueryCheckException(failure, FormatMessage("Invalid Query")), + "invalid_argument" => new QueryRuntimeException(failure, FormatMessage("Invalid Argument")), + "abort" => new AbortException(failure, FormatMessage("Abort")), // Request/Transaction Errors - "invalid_request" => new FaunaInvalidRequestException(FormatMessage("Invalid Request"), failure), - "contended_transaction" => new FaunaContendedTransactionException(FormatMessage("Contended Transaction"), failure), + "invalid_request" => new InvalidRequestException(failure, FormatMessage("Invalid Request")), + "contended_transaction" => new ContendedTransactionException(failure, FormatMessage("Contended Transaction")), // Capacity Errors - "limit_exceeded" => new FaunaThrottlingException(FormatMessage("Limit Exceeded"), failure), - "time_limit_exceeded" => new FaunaQueryTimeoutException(FormatMessage("Time Limit Exceeded"), failure), + "limit_exceeded" => new ThrottlingException(failure, FormatMessage("Limit Exceeded")), + "time_limit_exceeded" => new QueryTimeoutException(failure, FormatMessage("Time Limit Exceeded")), // Server/Network Errors - "internal_error" => new FaunaServiceException(FormatMessage("Internal Error"), failure), - "timeout" => new FaunaQueryTimeoutException(FormatMessage("Timeout"), failure), - "bad_gateway" => new FaunaNetworkException(FormatMessage("Bad Gateway")), - "gateway_timeout" => new FaunaNetworkException(FormatMessage("Gateway Timeout")), + "internal_error" => new ServiceException(failure, FormatMessage("Internal Error")), + "timeout" or + "time_out" => new QueryTimeoutException(failure, FormatMessage("Timeout")), + "bad_gateway" => new NetworkException(FormatMessage("Bad Gateway")), + "gateway_timeout" => new NetworkException(FormatMessage("Gateway Timeout")), - _ => new FaunaBaseException(FormatMessage("Unexpected Error")), + _ => new FaunaException(FormatMessage("Unexpected Error")), }; } else diff --git a/Fauna/Client/Connection.cs b/Fauna/Client/Connection.cs index 0d45b87d..3858b6ce 100644 --- a/Fauna/Client/Connection.cs +++ b/Fauna/Client/Connection.cs @@ -1,6 +1,7 @@ -using System.Net.Http.Headers; -using System.Security.Authentication; +using Fauna.Exceptions; +using System.Net.Http.Headers; using System.Text.Json; +using AuthenticationException = System.Security.Authentication.AuthenticationException; namespace Fauna; @@ -50,46 +51,42 @@ public async Task DoPostAsync( } catch (HttpRequestException ex) { - throw new FaunaNetworkException(FormatMessage("Network Error", ex.Message), ex); - } - catch (TimeoutException ex) - { - throw new FaunaClientException(FormatMessage("Operation Timed Out", ex.Message), ex); + throw new NetworkException(FormatMessage("Network Error", ex.Message), ex); } catch (TaskCanceledException ex) { if (!ex.CancellationToken.IsCancellationRequested) { - throw new FaunaClientException(FormatMessage("Operation Canceled", ex.Message), ex); + throw new ClientException(FormatMessage("Operation Canceled", ex.Message), ex); } else { - throw new FaunaClientException(FormatMessage("Operation Timed Out", ex.Message), ex); + throw new ClientException(FormatMessage("Operation Timed Out", ex.Message), ex); } } catch (ArgumentNullException ex) { - throw new FaunaClientException(FormatMessage("Null Argument", ex.Message), ex); + throw new ClientException(FormatMessage("Null Argument", ex.Message), ex); } catch (InvalidOperationException ex) { - throw new FaunaClientException(FormatMessage("Invalid Operation", ex.Message), ex); + throw new ClientException(FormatMessage("Invalid Operation", ex.Message), ex); } catch (JsonException ex) { - throw new FaunaProtocolException(FormatMessage("Response Parsing Failed", ex.Message), ex); + throw new ProtocolException(FormatMessage("Response Parsing Failed", ex.Message), ex); } catch (AuthenticationException ex) { - throw new FaunaClientException(FormatMessage("Authentication Failed", ex.Message), ex); + throw new ClientException(FormatMessage("Authentication Failed", ex.Message), ex); } catch (NotSupportedException ex) { - throw new FaunaClientException(FormatMessage("Not Supported Operation", ex.Message), ex); + throw new ClientException(FormatMessage("Not Supported Operation", ex.Message), ex); } catch (Exception ex) { - throw new FaunaBaseException(FormatMessage("Unexpected Error", ex.Message), ex); + throw new FaunaException(FormatMessage("Unexpected Error", ex.Message), ex); } } } diff --git a/Fauna/Exceptions/AbortException.cs b/Fauna/Exceptions/AbortException.cs new file mode 100644 index 00000000..aa539c49 --- /dev/null +++ b/Fauna/Exceptions/AbortException.cs @@ -0,0 +1,69 @@ +using Fauna.Serialization; + +namespace Fauna.Exceptions; + +/// +/// Represents an exception that occurs when the FQL `abort` function is called. +/// This exception captures the data provided during the abort operation. +/// +public class AbortException : QueryRuntimeException +{ + private readonly Dictionary cache = new(); + private static readonly Type NonTypedKey = typeof(object); + + /// + /// Initializes a new instance of the class with a specified error message and query failure details. + /// + /// The object containing details about the query failure. + /// The error message that explains the reason for the exception. + public AbortException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + /// + /// Initializes a new instance of the class with a specified error message, a reference to the inner exception, and query failure details. + /// + /// The object containing details about the query failure. + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. + public AbortException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } + + /// + /// Retrieves the deserialized data associated with the abort operation as an object. + /// + /// The deserialized data as an object, or null if no data is available. + public object? GetData() + { + if (!cache.TryGetValue(NonTypedKey, out var cachedData)) + { + var abortDataString = QueryFailure.ErrorInfo.Abort.ToString(); + if (!string.IsNullOrEmpty(abortDataString)) + { + cachedData = Serializer.Deserialize(abortDataString); + cache[NonTypedKey] = cachedData; + } + } + return cachedData; + } + + /// + /// Retrieves the deserialized data associated with the abort operation as a specific type. + /// + /// The type to which the data should be deserialized. + /// The deserialized data as the specified type, or null if no data is available. + public T? GetData() + { + var typeKey = typeof(T); + if (!cache.TryGetValue(typeKey, out var cachedData)) + { + var abortDataString = QueryFailure.ErrorInfo.Abort.ToString(); + if (!string.IsNullOrEmpty(abortDataString)) + { + T? deserializedResult = Serializer.Deserialize(abortDataString); + cache[typeKey] = deserializedResult; + return deserializedResult; + } + } + return (T?)cachedData; + } +} diff --git a/Fauna/Exceptions/AuthenticationException.cs b/Fauna/Exceptions/AuthenticationException.cs new file mode 100644 index 00000000..023d6e7b --- /dev/null +++ b/Fauna/Exceptions/AuthenticationException.cs @@ -0,0 +1,10 @@ +namespace Fauna.Exceptions; + +public class AuthenticationException : ServiceException +{ + public AuthenticationException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public AuthenticationException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} \ No newline at end of file diff --git a/Fauna/Exceptions/AuthorizationException.cs b/Fauna/Exceptions/AuthorizationException.cs new file mode 100644 index 00000000..03303748 --- /dev/null +++ b/Fauna/Exceptions/AuthorizationException.cs @@ -0,0 +1,10 @@ +namespace Fauna.Exceptions; + +public class AuthorizationException : ServiceException +{ + public AuthorizationException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public AuthorizationException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} \ No newline at end of file diff --git a/Fauna/Exceptions/ClientException.cs b/Fauna/Exceptions/ClientException.cs new file mode 100644 index 00000000..b152c853 --- /dev/null +++ b/Fauna/Exceptions/ClientException.cs @@ -0,0 +1,13 @@ +namespace Fauna.Exceptions; + +/// +/// Represents exception encountered prior to sending the request to Fauna. +/// +public class ClientException : FaunaException +{ + public ClientException(string message) + : base(message) { } + + public ClientException(string message, Exception innerException) + : base(message, innerException) { } +} diff --git a/Fauna/Exceptions/ContendedTransactionException.cs b/Fauna/Exceptions/ContendedTransactionException.cs new file mode 100644 index 00000000..94ca1534 --- /dev/null +++ b/Fauna/Exceptions/ContendedTransactionException.cs @@ -0,0 +1,14 @@ +namespace Fauna.Exceptions; + +/// +/// Represents an exception that occurs when a transaction is aborted due to concurrent modification. +/// This exception is considered retryable after a suitable delay. +/// +public class ContendedTransactionException : ServiceException, IRetryableException +{ + public ContendedTransactionException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public ContendedTransactionException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/FaunaAbortException.cs b/Fauna/Exceptions/FaunaAbortException.cs deleted file mode 100644 index 21d06ad0..00000000 --- a/Fauna/Exceptions/FaunaAbortException.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Fauna.Serialization; - -namespace Fauna; - -/// -/// Represents an exception that occurs when the FQL `abort` function is called. -/// This exception captures the data provided during the abort operation. -/// -public class FaunaAbortException : FaunaQueryRuntimeException -{ - private readonly Lazy deserializedData; - - /// - /// Initializes a new instance of the FaunaAbortException class with a specified error message, a reference to the inner exception, and query failure details. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception. - /// The QueryFailure object containing details about the query failure. - public FaunaAbortException(string message, QueryFailure queryFailure) - : base(message, queryFailure) => deserializedData = new(DeserializeAbortData); - - /// - /// Initializes a new instance of the FaunaAbortException class with a specified error message, a reference to the inner exception, and query failure details. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception. - /// The QueryFailure object containing details about the query failure. - public FaunaAbortException(string message, Exception innerException, QueryFailure queryFailure) - : base(message, innerException, queryFailure) => deserializedData = new(DeserializeAbortData); - - /// - /// Retrieves the deserialized abort data as an object. - /// - /// The deserialized abort data, or null if the data is not available. - public object? GetData() => deserializedData.Value; - - /// - /// Retrieves the deserialized abort data as a specific type. - /// - /// The type to which the data should be deserialized. - /// The deserialized abort data as type T, or default if the data is not available or cannot be cast to type T. - public T? GetData() => deserializedData.Value is T data ? data : default; - - private object? DeserializeAbortData() - { - var abortDataString = QueryFailure.ErrorInfo.Abort?.ToString(); - return !string.IsNullOrEmpty(abortDataString) ? Serializer.Deserialize(abortDataString) : null; - } -} diff --git a/Fauna/Exceptions/FaunaBaseException.cs b/Fauna/Exceptions/FaunaBaseException.cs deleted file mode 100644 index 58927c91..00000000 --- a/Fauna/Exceptions/FaunaBaseException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Fauna; - -/// -/// Represents the base exception class for all exceptions specific to Fauna interactions. -/// -public class FaunaBaseException : Exception -{ - public FaunaBaseException() { } - - public FaunaBaseException(string message) : base(message) { } - - public FaunaBaseException(string message, Exception innerException) - : base(message, innerException) { } -} diff --git a/Fauna/Exceptions/FaunaClientException.cs b/Fauna/Exceptions/FaunaClientException.cs deleted file mode 100644 index 4e2631a0..00000000 --- a/Fauna/Exceptions/FaunaClientException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Fauna; - -/// -/// Represents exception encountered prior to sending the request to Fauna. -/// -public class FaunaClientException : FaunaBaseException -{ - public FaunaClientException(string message) - : base(message) { } - - public FaunaClientException(string message, Exception innerException) - : base(message, innerException) { } -} diff --git a/Fauna/Exceptions/FaunaContendedTransactionException.cs b/Fauna/Exceptions/FaunaContendedTransactionException.cs deleted file mode 100644 index a64e56e9..00000000 --- a/Fauna/Exceptions/FaunaContendedTransactionException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Fauna; - -/// -/// Represents an exception that occurs when a transaction is aborted due to concurrent modification. -/// This exception is considered retryable after a suitable delay. -/// -public class FaunaContendedTransactionException : FaunaServiceException, IFaunaRetryableException -{ - public FaunaContendedTransactionException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaContendedTransactionException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaException.cs b/Fauna/Exceptions/FaunaException.cs new file mode 100644 index 00000000..deff5c81 --- /dev/null +++ b/Fauna/Exceptions/FaunaException.cs @@ -0,0 +1,14 @@ +namespace Fauna.Exceptions; + +/// +/// Represents the base exception class for all exceptions specific to Fauna interactions. +/// +public class FaunaException : Exception +{ + public FaunaException() { } + + public FaunaException(string message) : base(message) { } + + public FaunaException(string message, Exception innerException) + : base(message, innerException) { } +} diff --git a/Fauna/Exceptions/FaunaInvalidRequestException.cs b/Fauna/Exceptions/FaunaInvalidRequestException.cs deleted file mode 100644 index 4594390f..00000000 --- a/Fauna/Exceptions/FaunaInvalidRequestException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Fauna; - -/// -/// Represents exceptions caused by invalid requests to Fauna. -/// -public class FaunaInvalidRequestException : FaunaServiceException -{ - public FaunaInvalidRequestException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaInvalidRequestException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaNetworkException.cs b/Fauna/Exceptions/FaunaNetworkException.cs deleted file mode 100644 index c1d9815e..00000000 --- a/Fauna/Exceptions/FaunaNetworkException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Fauna; - -/// -/// Represents network-related exceptions thrown inside Connection, indicating no request was made. -/// -public class FaunaNetworkException : FaunaBaseException, IFaunaRetryableException -{ - public FaunaNetworkException(string message) - : base(message) { } - - public FaunaNetworkException(string message, Exception innerException) - : base(message, innerException) { } -} diff --git a/Fauna/Exceptions/FaunaProtocolException.cs b/Fauna/Exceptions/FaunaProtocolException.cs deleted file mode 100644 index 76e74ce6..00000000 --- a/Fauna/Exceptions/FaunaProtocolException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Fauna; - -/// -/// Represents exceptions when a response does not match the wire protocol. -/// -public class FaunaProtocolException : FaunaBaseException -{ - public FaunaProtocolException(string message) - : base(message) { } - - public FaunaProtocolException(string message, Exception innerException) - : base(message, innerException) { } -} diff --git a/Fauna/Exceptions/FaunaQueryCheckException.cs b/Fauna/Exceptions/FaunaQueryCheckException.cs deleted file mode 100644 index 95c1da3d..00000000 --- a/Fauna/Exceptions/FaunaQueryCheckException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Fauna; - -public class FaunaQueryCheckException : FaunaServiceException -{ - public FaunaQueryCheckException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaQueryCheckException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaQueryRuntimeException.cs b/Fauna/Exceptions/FaunaQueryRuntimeException.cs deleted file mode 100644 index e2d8b2a3..00000000 --- a/Fauna/Exceptions/FaunaQueryRuntimeException.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Fauna; - -/// -/// An error response that is the result of the query failing during execution. QueryRuntimeError's occur when a bug in your query causes an invalid execution to be requested. -/// -public class FaunaQueryRuntimeException : FaunaServiceException -{ - public FaunaQueryRuntimeException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaQueryRuntimeException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaQueryTimeoutException.cs b/Fauna/Exceptions/FaunaQueryTimeoutException.cs deleted file mode 100644 index 4d91bd94..00000000 --- a/Fauna/Exceptions/FaunaQueryTimeoutException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Fauna; - -public class FaunaQueryTimeoutException : FaunaServiceException -{ - public FaunaQueryTimeoutException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaQueryTimeoutException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaThrottlingException.cs b/Fauna/Exceptions/FaunaThrottlingException.cs deleted file mode 100644 index 41c7ebef..00000000 --- a/Fauna/Exceptions/FaunaThrottlingException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Fauna; - -/// -/// Represents an exception that indicates some capacity limit was exceeded and thus the request could not be served. -/// This exception is considered retryable after a suitable delay. -/// -public class FaunaThrottlingException : FaunaServiceException, IFaunaRetryableException -{ - public FaunaThrottlingException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaThrottlingException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/FaunaWriteConstraintException.cs b/Fauna/Exceptions/FaunaWriteConstraintException.cs deleted file mode 100644 index bf5da44b..00000000 --- a/Fauna/Exceptions/FaunaWriteConstraintException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Fauna; - -public class FaunaWriteConstraintException : FaunaQueryRuntimeException -{ - public FaunaWriteConstraintException(string message, QueryFailure? queryFailure = null) - : base(message, queryFailure) { } - - public FaunaWriteConstraintException(string message, Exception innerException, QueryFailure? queryFailure = null) - : base(message, innerException, queryFailure) { } -} diff --git a/Fauna/Exceptions/IFaunaRetryableException.cs b/Fauna/Exceptions/IRetryableException.cs similarity index 68% rename from Fauna/Exceptions/IFaunaRetryableException.cs rename to Fauna/Exceptions/IRetryableException.cs index 8427ba2a..0538eb26 100644 --- a/Fauna/Exceptions/IFaunaRetryableException.cs +++ b/Fauna/Exceptions/IRetryableException.cs @@ -1,9 +1,9 @@ -namespace Fauna; +namespace Fauna.Exceptions; /// /// Represents an interface for exceptions that are potentially recoverable through retrying the failed operation. /// -public interface IFaunaRetryableException +public interface IRetryableException { } diff --git a/Fauna/Exceptions/InvalidRequestException.cs b/Fauna/Exceptions/InvalidRequestException.cs new file mode 100644 index 00000000..2d50d051 --- /dev/null +++ b/Fauna/Exceptions/InvalidRequestException.cs @@ -0,0 +1,13 @@ +namespace Fauna.Exceptions; + +/// +/// Represents exceptions caused by invalid requests to Fauna. +/// +public class InvalidRequestException : ServiceException +{ + public InvalidRequestException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public InvalidRequestException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/NetworkException.cs b/Fauna/Exceptions/NetworkException.cs new file mode 100644 index 00000000..e32a9161 --- /dev/null +++ b/Fauna/Exceptions/NetworkException.cs @@ -0,0 +1,13 @@ +namespace Fauna.Exceptions; + +/// +/// Represents network-related exceptions thrown inside Connection, indicating no request was made. +/// +public class NetworkException : FaunaException, IRetryableException +{ + public NetworkException(string message) + : base(message) { } + + public NetworkException(string message, Exception innerException) + : base(message, innerException) { } +} diff --git a/Fauna/Exceptions/ProtocolException.cs b/Fauna/Exceptions/ProtocolException.cs new file mode 100644 index 00000000..427d7afa --- /dev/null +++ b/Fauna/Exceptions/ProtocolException.cs @@ -0,0 +1,13 @@ +namespace Fauna.Exceptions; + +/// +/// Represents exceptions when a response does not match the wire protocol. +/// +public class ProtocolException : FaunaException +{ + public ProtocolException(string message) + : base(message) { } + + public ProtocolException(string message, Exception innerException) + : base(message, innerException) { } +} diff --git a/Fauna/Exceptions/QueryCheckException.cs b/Fauna/Exceptions/QueryCheckException.cs new file mode 100644 index 00000000..7ed9c40c --- /dev/null +++ b/Fauna/Exceptions/QueryCheckException.cs @@ -0,0 +1,10 @@ +namespace Fauna.Exceptions; + +public class QueryCheckException : ServiceException +{ + public QueryCheckException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public QueryCheckException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/QueryRuntimeException.cs b/Fauna/Exceptions/QueryRuntimeException.cs new file mode 100644 index 00000000..4feb006c --- /dev/null +++ b/Fauna/Exceptions/QueryRuntimeException.cs @@ -0,0 +1,13 @@ +namespace Fauna.Exceptions; + +/// +/// An error response that is the result of the query failing during execution. QueryRuntimeError's occur when a bug in your query causes an invalid execution to be requested. +/// +public class QueryRuntimeException : ServiceException +{ + public QueryRuntimeException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public QueryRuntimeException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/QueryTimeoutException.cs b/Fauna/Exceptions/QueryTimeoutException.cs new file mode 100644 index 00000000..ad0d95e0 --- /dev/null +++ b/Fauna/Exceptions/QueryTimeoutException.cs @@ -0,0 +1,10 @@ +namespace Fauna.Exceptions; + +public class QueryTimeoutException : ServiceException +{ + public QueryTimeoutException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public QueryTimeoutException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/FaunaServiceException.cs b/Fauna/Exceptions/ServiceException.cs similarity index 56% rename from Fauna/Exceptions/FaunaServiceException.cs rename to Fauna/Exceptions/ServiceException.cs index d308caf6..5c5bb078 100644 --- a/Fauna/Exceptions/FaunaServiceException.cs +++ b/Fauna/Exceptions/ServiceException.cs @@ -1,36 +1,30 @@ -namespace Fauna; +namespace Fauna.Exceptions; /// /// Represents an exception related to Fauna service errors, particularly for query failures. /// -public class FaunaServiceException : FaunaBaseException +public class ServiceException : FaunaException { /// /// Gets the object associated with the exception. /// This object provides detailed information about the failure in the context of a Fauna query. /// - public QueryFailure QueryFailure { get; } + public QueryFailure QueryFailure { get; init; } /// - /// Initializes a new instance of the class with a specified error message and query failure details. + /// Initializes a new instance of the class with a specified query failure details and error message. /// - /// The error message that explains the reason for the exception. /// The object containing details about the query failure. - public FaunaServiceException(string message, QueryFailure queryFailure) - : base(message) - { - QueryFailure = queryFailure; - } + /// The error message that explains the reason for the exception. + public ServiceException(QueryFailure queryFailure, string message) + : base(message) => QueryFailure = queryFailure; /// - /// Initializes a new instance of the class with a specified error message, a reference to the inner exception, and query failure details. + /// Initializes a new instance of the class with a specified query failure details, error message, and a reference to the inner exception. /// + /// The object containing details about the query failure. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, represented by an object. - /// The object containing details about the query failure. - public FaunaServiceException(string message, Exception innerException, QueryFailure queryFailure) - : base(message, innerException) - { - QueryFailure = queryFailure; - } + public ServiceException(QueryFailure queryFailure, string message, Exception innerException) + : base(message, innerException) => QueryFailure = queryFailure; } diff --git a/Fauna/Exceptions/ThrottlingException.cs b/Fauna/Exceptions/ThrottlingException.cs new file mode 100644 index 00000000..fca6584c --- /dev/null +++ b/Fauna/Exceptions/ThrottlingException.cs @@ -0,0 +1,14 @@ +namespace Fauna.Exceptions; + +/// +/// Represents an exception that indicates some capacity limit was exceeded and thus the request could not be served. +/// This exception is considered retryable after a suitable delay. +/// +public class ThrottlingException : ServiceException, IRetryableException +{ + public ThrottlingException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public ThrottlingException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +} diff --git a/Fauna/Exceptions/WriteConstraintException.cs b/Fauna/Exceptions/WriteConstraintException.cs new file mode 100644 index 00000000..fdbc9d9d --- /dev/null +++ b/Fauna/Exceptions/WriteConstraintException.cs @@ -0,0 +1,10 @@ +namespace Fauna.Exceptions; + +public class WriteConstraintException : QueryRuntimeException +{ + public WriteConstraintException(QueryFailure queryFailure, string message) + : base(queryFailure, message) { } + + public WriteConstraintException(QueryFailure queryFailure, string message, Exception innerException) + : base(queryFailure, message, innerException) { } +}