Skip to content

Commit

Permalink
feat(sqllab): non-blocking persistence mode (apache#24539)
Browse files Browse the repository at this point in the history
Co-authored-by: Justin Park <justinpark@apache.org>
  • Loading branch information
justinpark and Justin Park authored Nov 20, 2023
1 parent b8327f2 commit 355adce
Show file tree
Hide file tree
Showing 20 changed files with 746 additions and 433 deletions.
297 changes: 53 additions & 244 deletions superset-frontend/src/SqlLab/actions/sqlLab.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ export const CREATE_DATASOURCE_STARTED = 'CREATE_DATASOURCE_STARTED';
export const CREATE_DATASOURCE_SUCCESS = 'CREATE_DATASOURCE_SUCCESS';
export const CREATE_DATASOURCE_FAILED = 'CREATE_DATASOURCE_FAILED';

export const SET_EDITOR_TAB_LAST_UPDATE = 'SET_EDITOR_TAB_LAST_UPDATE';

export const addInfoToast = addInfoToastAction;
export const addSuccessToast = addSuccessToastAction;
export const addDangerToast = addDangerToastAction;
Expand Down Expand Up @@ -160,6 +162,10 @@ export function updateQueryEditor(alterations) {
return { type: UPDATE_QUERY_EDITOR, alterations };
}

export function setEditorTabLastUpdate(timestamp) {
return { type: SET_EDITOR_TAB_LAST_UPDATE, timestamp };
}

export function scheduleQuery(query) {
return dispatch =>
SupersetClient.post({
Expand Down Expand Up @@ -237,44 +243,11 @@ export function startQuery(query) {
}

export function querySuccess(query, results) {
return function (dispatch) {
const sqlEditorId = results?.query?.sqlEditorId;
const sync =
sqlEditorId &&
!query.isDataPreview &&
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${sqlEditorId}`),
postPayload: { latest_query_id: query.id },
})
: Promise.resolve();

return sync
.then(() => dispatch({ type: QUERY_SUCCESS, query, results }))
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while storing the latest query id in the backend. ' +
'Please contact your administrator if this problem persists.',
),
),
),
);
};
return { type: QUERY_SUCCESS, query, results };
}

export function queryFailed(query, msg, link, errors) {
return function (dispatch) {
const sync =
!query.isDataPreview &&
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${query.sqlEditorId}`),
postPayload: { latest_query_id: query.id },
})
: Promise.resolve();

const eventData = {
has_err: true,
start_offset: query.startDttm,
Expand All @@ -295,22 +268,7 @@ export function queryFailed(query, msg, link, errors) {
});
});

return (
sync
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while storing the latest query id in the backend. ' +
'Please contact your administrator if this problem persists.',
),
),
),
)
// We should always show the error message, even if we couldn't sync the
// state to the backend
.then(() => dispatch({ type: QUERY_FAILED, query, msg, link, errors }))
);
dispatch({ type: QUERY_FAILED, query, msg, link, errors });
};
}

Expand Down Expand Up @@ -557,14 +515,15 @@ export function addQueryEditor(queryEditor) {
? SupersetClient.post({
endpoint: '/tabstateview/',
postPayload: { queryEditor },
})
: Promise.resolve({ json: { id: shortid.generate() } });
}).then(({ json }) => ({ ...json, loaded: true }))
: Promise.resolve({ id: shortid.generate() });

return sync
.then(({ json }) => {
.then(({ id, loaded }) => {
const newQueryEditor = {
...queryEditor,
id: json.id.toString(),
id: id.toString(),
loaded,
};
return dispatch({
type: ADD_QUERY_EDITOR,
Expand Down Expand Up @@ -736,11 +695,6 @@ export function switchQueryEditor(queryEditor, displayLimit) {
schema: json.schema,
queryLimit: json.query_limit,
remoteId: json.saved_query?.id,
validationResult: {
id: null,
errors: [],
completed: false,
},
hideLeftBar: json.hide_left_bar,
};
dispatch(loadQueryEditor(loadedQueryEditor));
Expand Down Expand Up @@ -770,31 +724,10 @@ export function setActiveSouthPaneTab(tabId) {

export function toggleLeftBar(queryEditor) {
const hideLeftBar = !queryEditor.hideLeftBar;
return function (dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { hide_left_bar: hideLeftBar },
})
: Promise.resolve();

return sync
.then(() =>
dispatch({
type: QUERY_EDITOR_TOGGLE_LEFT_BAR,
queryEditor,
hideLeftBar,
}),
)
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while hiding the left bar. Please contact your administrator.',
),
),
),
);
return {
type: QUERY_EDITOR_TOGGLE_LEFT_BAR,
queryEditor,
hideLeftBar,
};
}

Expand Down Expand Up @@ -856,110 +789,26 @@ export function removeQuery(query) {
}

export function queryEditorSetDb(queryEditor, dbId) {
return function (dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { database_id: dbId },
})
: Promise.resolve();

return sync
.then(() => dispatch({ type: QUERY_EDITOR_SETDB, queryEditor, dbId }))
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab database ID. Please contact your administrator.',
),
),
),
);
};
return { type: QUERY_EDITOR_SETDB, queryEditor, dbId };
}

export function queryEditorSetSchema(queryEditor, schema) {
return function (dispatch) {
const sync =
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) &&
typeof queryEditor === 'object'
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { schema },
})
: Promise.resolve();

return sync
.then(() =>
dispatch({
type: QUERY_EDITOR_SET_SCHEMA,
queryEditor: queryEditor || {},
schema,
}),
)
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab schema. Please contact your administrator.',
),
),
),
);
return {
type: QUERY_EDITOR_SET_SCHEMA,
queryEditor: queryEditor || {},
schema,
};
}

export function queryEditorSetAutorun(queryEditor, autorun) {
return function (dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { autorun },
})
: Promise.resolve();

return sync
.then(() =>
dispatch({ type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun }),
)
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab autorun. Please contact your administrator.',
),
),
),
);
};
return { type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun };
}

export function queryEditorSetTitle(queryEditor, name, id) {
return function (dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${id}`),
postPayload: { label: name },
})
: Promise.resolve();

return sync
.then(() =>
dispatch({
type: QUERY_EDITOR_SET_TITLE,
queryEditor: { ...queryEditor, id },
name,
}),
)
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab name. Please contact your administrator.',
),
),
),
);
return {
type: QUERY_EDITOR_SET_TITLE,
queryEditor: { ...queryEditor, id },
name,
};
}

Expand Down Expand Up @@ -1029,32 +878,19 @@ export function updateSavedQuery(query, clientId) {
.then(() => dispatch(updateQueryEditor(query)));
}

export function queryEditorSetSql(queryEditor, sql) {
return { type: QUERY_EDITOR_SET_SQL, queryEditor, sql };
export function queryEditorSetSql(queryEditor, sql, queryId) {
return { type: QUERY_EDITOR_SET_SQL, queryEditor, sql, queryId };
}

export function formatQuery(queryEditor) {
return function (dispatch, getState) {
const { sql } = getUpToDateQuery(getState(), queryEditor);
return SupersetClient.post({
endpoint: `/api/v1/sqllab/format_sql/`,
body: JSON.stringify({ sql }),
headers: { 'Content-Type': 'application/json' },
}).then(({ json }) => {
dispatch(queryEditorSetSql(queryEditor, json.result));
});
};
}

export function queryEditorSetAndSaveSql(targetQueryEditor, sql) {
export function queryEditorSetAndSaveSql(targetQueryEditor, sql, queryId) {
return function (dispatch, getState) {
const queryEditor = getUpToDateQuery(getState(), targetQueryEditor);
// saved query and set tab state use this action
dispatch(queryEditorSetSql(queryEditor, sql));
dispatch(queryEditorSetSql(queryEditor, sql, queryId));
if (isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)) {
return SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { sql, latest_query_id: queryEditor.latestQueryId },
postPayload: { sql, latest_query_id: queryId },
}).catch(() =>
dispatch(
addDangerToast(
Expand All @@ -1071,59 +907,32 @@ export function queryEditorSetAndSaveSql(targetQueryEditor, sql) {
};
}

export function queryEditorSetQueryLimit(queryEditor, queryLimit) {
return function (dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { query_limit: queryLimit },
})
: Promise.resolve();
export function formatQuery(queryEditor) {
return function (dispatch, getState) {
const { sql } = getUpToDateQuery(getState(), queryEditor);
return SupersetClient.post({
endpoint: `/api/v1/sqllab/format_sql/`,
body: JSON.stringify({ sql }),
headers: { 'Content-Type': 'application/json' },
}).then(({ json }) => {
dispatch(queryEditorSetSql(queryEditor, json.result));
});
};
}

return sync
.then(() =>
dispatch({
type: QUERY_EDITOR_SET_QUERY_LIMIT,
queryEditor,
queryLimit,
}),
)
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab name. Please contact your administrator.',
),
),
),
);
export function queryEditorSetQueryLimit(queryEditor, queryLimit) {
return {
type: QUERY_EDITOR_SET_QUERY_LIMIT,
queryEditor,
queryLimit,
};
}

export function queryEditorSetTemplateParams(queryEditor, templateParams) {
return function (dispatch) {
dispatch({
type: QUERY_EDITOR_SET_TEMPLATE_PARAMS,
queryEditor,
templateParams,
});
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
postPayload: { template_params: templateParams },
})
: Promise.resolve();

return sync.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while setting the tab template parameters. ' +
'Please contact your administrator.',
),
),
),
);
return {
type: QUERY_EDITOR_SET_TEMPLATE_PARAMS,
queryEditor,
templateParams,
};
}

Expand Down
Loading

0 comments on commit 355adce

Please sign in to comment.