-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Editoast error management #237
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: Leo Valais <[email protected]>
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a first round, hope you like it. I'm really worried by the complexity of this macro and if there would be some other solution.
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Thanks for all the corrections! I'll get back to this document when I have some time, hopefully in the next iteration :) |
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
I've added a bit of content, especially an implementation plan and details about how to forward Core errors. |
Signed-off-by: Leo Valais <[email protected]>
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
Co-authored-by: Serge Croisé <[email protected]>
Co-authored-by: Serge Croisé <[email protected]>
Co-authored-by: Serge Croisé <[email protected]>
Thanks for the corrections! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice introducing some new sections about "Issues of the old system" or "Implementation plan".
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Leo Valais <[email protected]>
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Leo Valais <[email protected]>
This looks mergeable as it is to me. @Khoyo: we discussed about Core errors with @flomonster yesterday and settled on wrapping the errors, but not parsing them. Lmk if it's ok. @Khoyo @woshilapin: do I drop the "Rejected Ideas" section or not? (Personally I don't care.) A final round of review would be much appreciated 🙏 |
Signed-off-by: Leo Valais <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, made a few more comments, I believe most of them are not fundamental so should not move things too much.
And for your questions, I'd prefer to keep "Rejected ideas", it's a good thing to keep these around so we avoid to reinvent things we might have explore in the past.
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
- Create a proc-macro `derive(ViewError)` which interfaces with `derive(thiserror::Error)`. | ||
- The `context` is empty by default but can be provided by the `impl ViewError`. The macro is also able to take context providers. | ||
- `ViewError`'s `#[source]`, `#[from]`, `source` and `backtrace` fields are never serialized, unless explicitly provided. This shouldn't be the case as it exposes editoast internals at the API level. | ||
- `derive(ViewError)` generates the `impl utoipa::ToSchema for T`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all our errors implements EditoastError
, can't we not do it with something like impl<T: EditoastError> utoipa::ToSchema for T
once and for all (and avoid to do that in the macro, and therefore, avoid also a lot of code generation?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there's a misunderstanding or just a typo here. All errors returned by endpoints implement trait ViewError
(trait EditoastError
is bound to disappear).
The problem is that impl ViewError
errors are not serialized in the response. They are converted into what is currently a struct InternalError
which has its own serialization. So we can't just #[derive(ToSchema)]
on a trait ViewError
since the generated schema is inferred from the "would-be" serialization of the type.
Instead, we want MyViewError::schema()
to return the schema of the error, but following the structure of InternalError
!
For example:
#[derive(ToSchema)]
struct MyViewError { cause: String }
MyViewError::schema()
shouldn't be:
type MyViewError = { cause: string };
but instead:
type MyViewError = {
status: 500,
error_type: 'editoast:MyViewError',
context: { cause: string },
message: string
}
We can't just impl<T: EditoastError> utoipa::ToSchema for T
: the function schema()
would build its result based on which information? (We don't necessarily have to generate the whole ToSchema
, but we do need to generate enough information at compile-time to build the schema. Rust doesn't have introspection.)
I realize all that is worth a section on this document to avoid confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
content/docs/reference/design-docs/editoast-errors/_index.en.md
Outdated
Show resolved
Hide resolved
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Co-authored-by: Jean SIMARD <[email protected]>
Co-authored-by: Jean SIMARD <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Co-authored-by: Jean SIMARD <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
Signed-off-by: Leo Valais <[email protected]>
@@ -45,7 +45,7 @@ weight: 80 | |||
- Create a proc-macro `derive(ViewError)` which interfaces with `derive(thiserror::Error)`. | |||
- The `context` is empty by default but can be provided by the `impl ViewError`. The macro is also able to take context providers. | |||
- `ViewError`'s `#[source]`, `#[from]`, `source` and `backtrace` fields are never serialized, unless explicitly provided. This shouldn't be the case as it exposes editoast internals at the API level. | |||
- `derive(ViewError)` generates the `impl utoipa::ToSchema for T`. | |||
- `impl utoipa::IntoResponses for T` (may be generated or inferred) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: Isn't it this?
- `impl utoipa::IntoResponses for T` (may be generated or inferred) | |
- `impl<T: ViewError> utoipa::IntoResponses for T` (may be generated or inferred) |
} | ||
``` | ||
|
||
making `serde` basically useless for our errors. On top of that, since by design the derive macros of `utoipa` (`ToSchema`, `IntoResponse` especially) interpret the type structure like `serde` would do, we can't rely on them either. Therefore we need a custom derive-macro to convey the structural information of the type at runtime. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we still want serde
, just not the automatic derive.
making `serde` basically useless for our errors. On top of that, since by design the derive macros of `utoipa` (`ToSchema`, `IntoResponse` especially) interpret the type structure like `serde` would do, we can't rely on them either. Therefore we need a custom derive-macro to convey the structural information of the type at runtime. | |
making `derive(serde::Serialize)` basically useless for our errors. ... |
Here are some ideas for not codegen the serialize implementation.
|
||
Another solution would be to shift our error definition paradigm and orient ourselves to a system without code generation (probably using a combination of traits and builders). This would imply to rewrite all our errors and their handling, which is costly 🤑🫰. We'd also have to get rid of the convenience of `thiserror`, a huge loss in terms of ergonomics. And that would break the consistency with the other sub-crates of editoast. | ||
|
||
The macro doesn't even have to be overly complex. The `trait ViewError` could be responsible of translating the static type definition into an associated constant, which would be used to compute data produced at runtime. (Ie. `impl axum::IntoResponse for T: ViewError` and `impl utoipa::IntoResponses for T: ViewError`.) This would reduce the amount of generated code, at the expense of more complex data manaipulation at runtime. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
The macro doesn't even have to be overly complex. The `trait ViewError` could be responsible of translating the static type definition into an associated constant, which would be used to compute data produced at runtime. (Ie. `impl axum::IntoResponse for T: ViewError` and `impl utoipa::IntoResponses for T: ViewError`.) This would reduce the amount of generated code, at the expense of more complex data manaipulation at runtime. | |
The macro doesn't even have to be overly complex. The `trait ViewError` could be responsible of translating the static type definition into an associated constant, which would be used to compute data produced at runtime. (Ie. `impl axum::IntoResponse for T: ViewError` and `impl utoipa::IntoResponses for T: ViewError`.) This would reduce the amount of generated code, at the expense of more complex data manipulation at runtime. |
|
||
The Core service is a bit special as it already returns errors with the common OSRD format. Since editoast doesn't really need to parse and recover from Core errors[^2], we don't need an exhaustive list of them. We still need to differentiate them from other editoast errors (let's not start tossing `InternalError` around again…) and to provide a key for the frontend to translate them. | ||
|
||
[^2]: Core errors will likely never be recoverable from either editoast or the frontend. For the latter, such errors are likely to be displayed as a generic "Internal error" message. So no translation is needed. For these reasons, we don't need to them in the OpenAPI. However, if in the future, we want editoast to actually parse Core errors, ensuring a proper mapping will still be possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[^2]: Core errors will likely never be recoverable from either editoast or the frontend. For the latter, such errors are likely to be displayed as a generic "Internal error" message. So no translation is needed. For these reasons, we don't need to them in the OpenAPI. However, if in the future, we want editoast to actually parse Core errors, ensuring a proper mapping will still be possible. | |
[^2]: Core errors will likely never be recoverable from either editoast or the frontend. For the latter, such errors are likely to be displayed as a generic "Internal error" message. So no translation is needed. For these reasons, we don't need to pass them in the OpenAPI. However, if in the future, we want editoast to actually parse Core errors, ensuring a proper mapping will still be possible. |
(j'avoue que ne n'ai pas trop compris la phrase)
Settling on this topic is necessary in order to go forward with the split in crates.