-
Notifications
You must be signed in to change notification settings - Fork 2
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
feat(swap): Add code to ServiceError class [WEB-977] #654
base: main
Are you sure you want to change the base?
Conversation
0acaae1
to
191733e
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #654 +/- ##
==========================================
+ Coverage 87.79% 88.01% +0.21%
==========================================
Files 101 101
Lines 1631 1610 -21
Branches 239 232 -7
==========================================
- Hits 1432 1417 -15
+ Misses 190 186 -4
+ Partials 9 7 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
191733e
to
f0cd1e0
Compare
@@ -5,30 +5,43 @@ type IgnoredField = | |||
| 'prepareStackTrace' | |||
| 'stackTraceLimit'; | |||
|
|||
type ErrorCode = 'not-found' | 'bad-request' | 'internal-error' | 'rpc-error' | 'invalid-amount'; |
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 am not sure about the granularity here. eg an invalid address will lead to bad-request
at the moment, should this be invalid-address
instead?
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.
the problem with the current approach is that we cannot really change from a general code (bad-request
) to a more specific one (invalid-address
) because this could break consumers.
we could add a third property (detail
) which will be set for specific errors (eg invalid-amount
, invalid-address
) only? but this feels overly complicated
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.
TIL that there is a IETF RFC for exposing errors: https://datatracker.ietf.org/doc/html/rfc7807
will check if this makes sense in our case
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.
there even is a new RPC from 2023 that obsoletes the old one: https://datatracker.ietf.org/doc/html/rfc9457
but it seems like this standard is not widely used and the format feels specific to errors returned from an api (which makes sense for the rpc)
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 am leaning to use the following format:
{
type: 'NOT_FOUND' | 'BAD_REQUEST';
code: 'INVALID_AMOUNT' | 'INUSFFICIENT_LIQUIDITY' | undefined,
message: 'human readable explanation'
}
this would allow use to introduce specific error codes later on without breaking any consumer. (eg. adding a INVALID_ADDRESS
code)
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.
this would be kinda similar to what stripe/twilio/square does:
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.
Should we maybe just use numeric codes instead of keywords? Using keywords is an approach prone to collisions and the chances that we might need to change an old code (keyword) to be more/less explicit to accomodate a new error code is higher.
If we use numeric codes we can simply guarantee they wont change while we can still change the keywords/description to provide more context.
Sorry if i am expressing this concern a little bit late.
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.
Imagine using INVALID_AMOUNT
at this point for indicating that there was an issue with the swap amount. What if tomorrow we add another endpoint that requires amounts to be provided. At that point, the INVALID_AMOUNT
might apply to both cases, and it will not be possible to change this old code
(keyword). Maybe your idea is to reuse this keyword code
in all cases where it applies and then provide more info via the message
, but that will become tricky/not straightforward to explain in the docs for example.
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 agree that this could lead to keywords being less explicit than they could be bc of backwards compatibility, a number would allow you to clarify the "meaning" later on. but this also means that the number itself does not give you an idea about the error (without consulting documentation). to solve that you could provide constants with meaningful names, but then you kinda end up with the same problem of not being able to change the constant name 🙈
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.
about the second point i am not too concerned. i think it would be fine to return INVALID_AMOUNT
from a different endpoint as well. if the consumer wants to handle the error in a useful way, he needs to catch it where he calls the endpoint (and therefore knows what endpoint is called). why do you think this would need to be a different code?
f0cd1e0
to
31b3406
Compare
@@ -5,30 +5,43 @@ type IgnoredField = | |||
| 'prepareStackTrace' | |||
| 'stackTraceLimit'; | |||
|
|||
type ErrorCode = 'not-found' | 'bad-request' | 'internal-error' | 'rpc-error' | 'invalid-amount'; |
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 think NOT_FOUND
would be preferable
code: ErrorCode = 'bad-request', | ||
message = 'the request payload is not valid', |
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 think the message will specified more often than the code
code: ErrorCode = 'bad-request', | |
message = 'the request payload is not valid', | |
message = 'the request payload is not valid', | |
code: ErrorCode = 'bad-request', |
export default class ServiceError extends Error { | ||
static badRequest(message: string): ServiceError { | ||
return new ServiceError(message, 400); | ||
static badRequest( |
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.
could be interesting to add a code
method that you can chain:
throw ServiceError.badRequest('some message').code('INVALID_AMOUNT')
@@ -268,7 +273,7 @@ router.post( | |||
const result = openSwapDepositChannelSchema.safeParse(req.body); | |||
if (!result.success) { | |||
logger.info('received bad request for new swap', { body: req.body }); | |||
throw ServiceError.badRequest('invalid request body'); | |||
throw ServiceError.badRequest('bad-request', 'invalid request body'); |
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.
Could we provide more info as to which fields were invalid?
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 was looking into generating a message for zod validation errors yesterday but decided to not include that in this pr bc it was not trivial. but i agree that it would be nice to give a hint about the validation error later on 🙂
ServiceError.assert( | ||
swapDepositChannel || swap || failedSwap, | ||
'notFound', | ||
'not-found', |
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.
We could be more explicit: swap-not-found
@@ -5,30 +5,43 @@ type IgnoredField = | |||
| 'prepareStackTrace' | |||
| 'stackTraceLimit'; | |||
|
|||
type ErrorCode = 'not-found' | 'bad-request' | 'internal-error' | 'rpc-error' | 'invalid-amount'; |
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.
Should we maybe just use numeric codes instead of keywords? Using keywords is an approach prone to collisions and the chances that we might need to change an old code (keyword) to be more/less explicit to accomodate a new error code is higher.
If we use numeric codes we can simply guarantee they wont change while we can still change the keywords/description to provide more context.
Sorry if i am expressing this concern a little bit late.
@@ -5,30 +5,43 @@ type IgnoredField = | |||
| 'prepareStackTrace' | |||
| 'stackTraceLimit'; | |||
|
|||
type ErrorCode = 'not-found' | 'bad-request' | 'internal-error' | 'rpc-error' | 'invalid-amount'; |
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.
Imagine using INVALID_AMOUNT
at this point for indicating that there was an issue with the swap amount. What if tomorrow we add another endpoint that requires amounts to be provided. At that point, the INVALID_AMOUNT
might apply to both cases, and it will not be possible to change this old code
(keyword). Maybe your idea is to reuse this keyword code
in all cases where it applies and then provide more info via the message
, but that will become tricky/not straightforward to explain in the docs for example.
No description provided.