You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the Tailcall application, errors can arise during both the validation phase and at runtime. These errors need to be displayed in various formats: on the command-line interface (CLI) and as a GraphQL response. The following RFC provides detailed guidance on how to architect and design our error management system.
Error Display
There are several ways we want to display errors to the user:
On the Console
For this purpose, we should implement a trait for errors:
The issue with this implementation is that it represents unchecked exceptions, which cannot be processed later. For example, if it's an HTTP error and we wish to retry, the error information would be entangled within the text, making further processing difficult.
The advantage of a general-purpose container is that we can easily implement the above display traits once and not worry about reimplementing them for every type of error.
Typed Errors
Ideally, each module should expose its own errors, allowing us to scope the errors to specific modules. For example, all HTTP errors would reside in http::error.rs, and all blueprint errors in blueprint::error.rs. This design ensures reusability, as we can issue the same error multiple times across our code without losing details, thanks to compiler enforcement.
However, there is a disadvantage. When a module uses multiple other modules, the errors it produces could be from any of them. This leaves us with two options: either perform a conversion from one type to another or create a wrapper type for the error.
Creating a wrapper is safer and more "correct," but it can quickly become unmanageable. Additionally, when refactoring code and changing modules, we would need to restructure the errors, which can be a significant challenge.
Error Monolith
An alternative is to create a large enum of errors that can be used throughout our application. This approach avoids the need for conversions but may result in multiple duplicate errors. To address this, we can group errors not by module but by logical separation.
Tooling to Simplify Error Management
There are tools like derive_more that can facilitate error transformation. Additionally, the ? operator in Rust automatically converts errors using into, easing the error handling process.
By considering these approaches, we can effectively manage errors in the Tailcall application, ensuring clarity and reusability while minimizing the challenges associated with error handling.
The text was updated successfully, but these errors were encountered:
In the Tailcall application, errors can arise during both the validation phase and at runtime. These errors need to be displayed in various formats: on the command-line interface (CLI) and as a GraphQL response. The following RFC provides detailed guidance on how to architect and design our error management system.
Error Display
There are several ways we want to display errors to the user:
On the Console
For this purpose, we should implement a trait for errors:
If the error implements this trait, it is console-friendly and can feature highlighted or colored text.
In the
errors
Field of a GraphQL ResponseThis is already supported by the trait
async_graphql::ErrorExtensions
. Any error that implements this trait will support richer error messages.In an External Telemetry System (To Be Considered)
We could implement a separate trait for this:
Untyped Error
We can define a general-purpose container for errors as follows:
The issue with this implementation is that it represents unchecked exceptions, which cannot be processed later. For example, if it's an HTTP error and we wish to retry, the error information would be entangled within the text, making further processing difficult.
The advantage of a general-purpose container is that we can easily implement the above display traits once and not worry about reimplementing them for every type of error.
Typed Errors
Ideally, each module should expose its own errors, allowing us to scope the errors to specific modules. For example, all HTTP errors would reside in
http::error.rs
, and all blueprint errors inblueprint::error.rs
. This design ensures reusability, as we can issue the same error multiple times across our code without losing details, thanks to compiler enforcement.However, there is a disadvantage. When a module uses multiple other modules, the errors it produces could be from any of them. This leaves us with two options: either perform a conversion from one type to another or create a wrapper type for the error.
Creating a wrapper is safer and more "correct," but it can quickly become unmanageable. Additionally, when refactoring code and changing modules, we would need to restructure the errors, which can be a significant challenge.
Error Monolith
An alternative is to create a large enum of errors that can be used throughout our application. This approach avoids the need for conversions but may result in multiple duplicate errors. To address this, we can group errors not by module but by logical separation.
Tooling to Simplify Error Management
There are tools like
derive_more
that can facilitate error transformation. Additionally, the?
operator in Rust automatically converts errors usinginto
, easing the error handling process.By considering these approaches, we can effectively manage errors in the Tailcall application, ensuring clarity and reusability while minimizing the challenges associated with error handling.
The text was updated successfully, but these errors were encountered: