-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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: initial work to make v1 API compatible with SIP-40 and SIP-41 #13960
feat: initial work to make v1 API compatible with SIP-40 and SIP-41 #13960
Conversation
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.
So in this case, you've got the DatabaseTestConnectionFailedError
that test_connection
can raise. Should this be something that extends a SupersetErrorException
or should it be caught in the handle_exception
wrapper and then return a response with a constructed SupersetError of type TEST_CONNECTION_PORT_CLOSED_ERROR
or TEST_CONNECTION_HOST_DOWN_ERROR
?
Codecov Report
@@ Coverage Diff @@
## master #13960 +/- ##
==========================================
+ Coverage 78.37% 78.70% +0.32%
==========================================
Files 935 936 +1
Lines 47375 47407 +32
Branches 5973 5956 -17
==========================================
+ Hits 37131 37310 +179
+ Misses 10097 9954 -143
+ Partials 147 143 -4
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Right, I actually have another PR where I started doing that: class DatabaseTestConnectionFailedError(SupersetErrorsException):
message = _("Connection failed, please check your connection settings") This way it will expose the proper errors (and additional errors that I'm adding, eg, |
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.
Sometime ago @john-bodley proposed to use this Flask capability: https://flask.palletsprojects.com/en/1.1.x/errorhandling/#registering. I like the idea, and it seems doable, that way we would not need to implement our own decorator for error handling
superset/views/base_api.py
Outdated
logger.warning(ex) | ||
return json_errors_response( | ||
errors=[ | ||
SupersetError( |
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.
Are we always going to throw HTTP 500 on these? would it make sense that the exception itself could identify the HTTP status 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.
I don't think that command exceptions should have HTTP status codes, they should care only about business logic and be decoupled from the API.
Ideally the API layer should do the mapping between command exceptions to SupersetError(s)Exception
. The reason why I added CommandInvalidError
and CommandException
is so we can gradually implement that mapping, while in the meantime any non-covered command exceptions return a 500.
I agree, I love that pattern. Let me give it a try, it might be easier since we register the error handler and then we can gradually change the APIs to raise |
d77fe8b
to
c11d9d1
Compare
d49b790
to
cded967
Compare
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 all makes sense to me, stamping from the frontend perspective
"message": "Could not load database driver: BaseEngineSpec", | ||
"errors": [ | ||
{ | ||
"message": "Could not load database driver: BaseEngineSpec", |
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 guess ideally in the future these messages will become actual errors with details on how to resolve them in the documentation
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.
Right, we're going to work on all the messaging in the test connection flow and add database flow.
…pache#13960) * WIP * Use errorhandler * Add response schema * Fix status on HTTPException * s/found/encountered/g * Fix test * Fix lint * Fix lint and test
…pache#13960) * WIP * Use errorhandler * Add response schema * Fix status on HTTPException * s/found/encountered/g * Fix test * Fix lint * Fix lint and test
SUMMARY
This PR is a first step in making the v1 API compatible with SIP-40 and SIP-41.
Currently, the API returns exceptions using helper methods from Flask-AppBuilder, eg:
These responses are simple JSON payloads, not compatible with the standard error format introduced in SIP-40. For example, when adding a database with a non-existent driver (
foo://
) this is returned:And this is the message displayed in the frontend (in a toast):
To conform with SIP-41 I added
a new decorator calledan error handler that captures exceptions and formats them according to SIP-40. This allows us to simplify the API logic, removing the need to capture exceptions when running commands (see the newhandle_exception
test_connection
method in this PR).With the decorator, the backend now returns:
And the message is displayed correctly in the frontend as before, in a toast, without requiring any modifications:
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
See above.
TEST PLAN
Will add unit tests, I wanted to discuss this first.
ADDITIONAL INFORMATION