-
-
Notifications
You must be signed in to change notification settings - Fork 275
Rewrite grid updating functionality #511
Conversation
…params if updated from Chart Studio
|
Thanks for this PR! High-level questions:
|
|
|
OK, thanks for the clarifications. I'm OK with the principles behind both answers. The answer to the second question implies a potentially-breaking change, but in the direction of correctness, so I'm in support. @n-riesco how do you feel about the code? |
|
I should note that the variable-columns-across-executions thing is actually much easier to do with non-SQL connection types like CSV and such, so it's not such an exotic case as I had first thought... |
|
@briandennis @nicolaskruchten I've just skimmed through the PR. I'll review it more carefully later. The main thing that has caught my eye is that some of the tests in https://github.com/plotly/falcon-sql-client/pull/511/files#diff-b5c6b550db1eb811e7de0d9a87f5a1eb have been updated to ignore the |
| return getGrid(fid, requestor); | ||
| }).then((res) => { | ||
| Logger.log(`Request to Plotly for fetching updated grid took ${process.hrtime(startTime)[0]} seconds`, 2); | ||
| return res.json(); |
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.
Test status before converting to JSON, otherwise the error will be reported as a failure to parse into JSON.
|
@n-riesco re ignoring Most of the omissions attempt to correct for quirks that are no longer the case. For example, Though, you're right that we should probably still be checking that |
| try { | ||
| return Object.keys(grid.cols) | ||
| .map(key => grid.cols[key]) | ||
| .sort((a, b) => a.order - b.order) |
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.
what's the content of order?
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 it's a zero based index representing the where the column lies from left to right
backend/persistent/plotly-api.js
Outdated
| const baseParams = { username, apiKey, accessToken }; | ||
|
|
||
| // fetch latest grid to get the source of truth | ||
| return getGrid(fid, requestor) |
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.
Potentially, this is a very expensive request, since it returns all the grid data, when we are only interested in column names, uid and order.
@tarzzz Is there any other way to get this information?
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.
good point! I believe the API supports GET for the /col endpoint
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 API does support GET /col. I can make that update.
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.
btw, our API is documented here: https://api.plot.ly/v2/grids/ ..
| return data; | ||
| } | ||
|
|
||
| const uids = extractOrderedUids(data); |
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 function orders uids by order.
Is this what we want?
Changing a query from select a,b to select b,a would break a plot.
Please, ignore this comment. I've checked and this is already the behaviour in master.
| } | ||
| return res.json(); | ||
| }).then(data => { | ||
| if (data.status) { |
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.
Elsewhere we throw an error, why not here?
This is done so that it behaves like plotlyAPIRequest.
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 status was being used by the tests so we just returned (https://github.com/plotly/falcon-sql-client/blob/dc4091249e48a10db12068abe1838900f36437a5/test/backend/QueryScheduler.spec.js#L629). Is it worth updating?
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.
| method: 'POST' | ||
| }).then((res) => { | ||
| if (res.status !== 200) { | ||
| return res; |
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.
throw?
|
Since I'm cranking through testing scenarios, I saw this UI issue which hopefully can be slid into this PR:
|
|
Second small UI thing: when creating a query from within Falcon, the initial "saved successfully" window doesn't include a link to the resulting dataset, which seems like a very natural thing to want to see there! |
|
|
||
| if (numColumns > uids.length) { | ||
| // repopulate existing columns | ||
| const putUrl = `${baseUrl}?uid=${uids.join(',')}`; |
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.
do we need to slice uids here?
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.
No, UIDs are shorter in length than numColumns. Not sure what we would slice it to.
| queryObject = { | ||
| fid, | ||
| uids, | ||
| refreshInterval, |
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.
why?
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 Brian just wanted to test that a default refresh interval was set even if one isn't sent with the request.
I can add it back in and make the assertion:
assert.deepEqual(
getQueries(),
[queryObject],
'Query has not been saved'
);would you prefer that?
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.
Yes, please. Otherwise I won't know if this PR changes Falcon's behaviour.
|
I have to take a break. I'm not done with the review yet. I want to understand why My worry is that this PR changes |
backend/persistent/QueryScheduler.js
Outdated
| }).then((res) => { | ||
| Logger.log(`Request to Plotly for fetching updated grid took ${process.hrtime(startTime)[0]} seconds`, 2); | ||
| if (res.status !== 200) { | ||
| return res.text(); |
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 is silencing the error we currently see in master
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 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.
@briandennis After more debugging, I have a better idea of what's happening.
Currently, master is failing because we get 400 Bad Request in https://github.com/plotly/falcon-sql-client/pull/511/files#diff-a353f58a9179598892ca8c2a867f4e2dR309
In master, this causes an exception in https://github.com/plotly/falcon-sql-client/pull/511/files#diff-a353f58a9179598892ca8c2a867f4e2dL384 because res in undefined.
In this PR, execution moves to https://github.com/plotly/falcon-sql-client/pull/511/files#diff-a353f58a9179598892ca8c2a867f4e2dR390 as if the grid hadn't been deleted.
test/backend/routes.queries.spec.js
Outdated
| return POST('queries', queryObject) | ||
| .then(assertResponseStatus(201)) | ||
| .then(getResponseJson).then(json2 => { | ||
| assert.deepEqual(json2, queryObject); |
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 is the only line that needed updating in this test.
Let's revert everything else.
test/backend/routes.queries.spec.js
Outdated
| .then(getResponseJson).then(json => { | ||
| assert.deepEqual(json, [queryObject]); | ||
| .then(getResponseJson).then((json) => { | ||
| assert.deepEqual(omit('uids', json), omit('uids', queryObject)); |
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 is the only line that needed updating in this test.
Let's revert everything else.
Re the uids, is it possible to correct te const uids above?
|
@briandennis At the moment, there are 3 tests failing in These failures are caused by changes in the The changes in To convince myself that this PR doesn't hide these failures:
|
backend/persistent/QueryScheduler.js
Outdated
| Logger.log(`Request to Plotly for creating a grid took ${process.hrtime(startTime)[0]} seconds`, 2); | ||
| Logger.log(`Grid ${fid} has been updated.`, 2); | ||
|
|
||
| if (res.status !== 200) { |
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 PR was OK without this change. The error is already thrown here.
Note that res here is undefined when the execution goes through https://github.com/plotly/falcon-sql-client/blob/7a7483790488f897362479c6280658ab24ee20e5/backend/persistent/QueryScheduler.js#L338 or https://github.com/plotly/falcon-sql-client/blob/7a7483790488f897362479c6280658ab24ee20e5/backend/persistent/QueryScheduler.js#L359
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.
@n-riesco without that change, wouldn't the error be swallowed if patchGrid responds non-200, but does not throw?
|
@mfix22 Since after this PR,
|
|
@n-riesco re errors on master: So sorry for headache from the |
|
@briandennis No worries (one can't make an omelette without breaking some eggs 😄 ). @mfix22 It's getting late for me. Tomorrow, I'll have a look again at the PR and test it a bit further. |
|
@n-riesco CI is failing on that same collaborator test. From the error message, it looks like it's responding with a Any idea why this might be? Do you think the way collaborator permissions are handled may have changed? |
|
@briandennis I'm taking that discussion to Slack. |
@nicolaskruchten @n-riesco I'm still doing some manual testing, but I wanted to get this in front of you for review since I don't foresee the crux of it changing much.
Overview
This PR makes a core change to the way grids are updated in Falcon. Because of how central an alteration this is, I'm going to go into some detail about how it's implemented to try and catch any misunderstandings or issues up front! Please let me know if any of this sounds incorrect or contrary to your understanding 🙂
Previous to this PR, the update functionality worked as follows:
uid's are passed in as a parameter toPOST /queriesupdateGridfunction is called which writes up touids.lengthcolumns of dataThis is problematic because it relies on clients (Chart Studio, Falcon scheduling UI) to handle column renaming, appending, and deleting by manually updating the grid themselves. The Falcon scheduling UI isn't doing any of this which is what led to the problems in #507. Chart Studio does handle these updates, but only if the query is rerun before syncing with Falcon.
To eliminate this reliance, the PR expands the update grid functionality to take care of these operations. The algorithm it uses mimics the requests used in Chart Studio which seems to optimize for preserving
uid's where possible (which is sensible since charts rely upon these)After this PR, the update functionality works as follows:
uidsuids, update the existing columns in place and append any additional ones requireduids, delete surplus columns and update the required existing columns in placeuids are equal and the existing columns can be updated in place as in the older versionBackwards Compatibility
Though not used directly anymore, the latest
uids are still stored with scheduled queries to support Old Falcon loading New Falcon yaml files. In cases we've found where this PR breaks from existing functionality, it does so by providing more data, not less. Regardless, I want to confirm the two main ones we're aware of aren't an issue:POST /queriesnow respond with the updated scheduled query rather than returning an empty objectuids (with respect to the number of columns returned in the current query) will still set the correct number of columns. For example, previously if in Chart Studio you had an existing single columned query (select a) and updated it to a multi columned query (select a, b) and hit sync with connector before rerunning the query, the grid would incorrectly update with only one column whereas now it will populate bothcloses #507