Store: Error handling for setObject (#23650)

* Error handling for setObject to store

* Update public/app/core/store.ts

Co-Authored-By: kay delaney <45561153+kaydelaney@users.noreply.github.com>

* Update public/app/features/explore/RichHistory/RichHistory.tsx

Co-Authored-By: kay delaney <45561153+kaydelaney@users.noreply.github.com>

* Move setState outside of try-catch block

Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
This commit is contained in:
Ivana Huckova 2020-04-20 15:13:02 +02:00 committed by GitHub
parent 4ea41dc19d
commit 174ee95153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 33 deletions

View File

@ -24,7 +24,11 @@ export class LocalStorageValueProvider<T> extends PureComponent<Props<T>, State<
onSaveToStore = (value: T) => { onSaveToStore = (value: T) => {
const { storageKey } = this.props; const { storageKey } = this.props;
store.setObject(storageKey, value); try {
store.setObject(storageKey, value);
} catch (error) {
console.error(error);
}
this.setState({ value }); this.setState({ value });
}; };

View File

@ -29,21 +29,19 @@ export class Store {
return ret; return ret;
} }
// Returns true when successfully stored /* Returns true when successfully stored, throws error if not successfully stored */
setObject(key: string, value: any): boolean { setObject(key: string, value: any) {
let json; let json;
try { try {
json = JSON.stringify(value); json = JSON.stringify(value);
} catch (error) { } catch (error) {
console.error(`Could not stringify object: ${key}. [${error}]`); throw new Error(`Could not stringify object: ${key}. [${error}]`);
return false;
} }
try { try {
this.set(key, json); this.set(key, json);
} catch (error) { } catch (error) {
// Likely hitting storage quota // Likely hitting storage quota
console.error(`Could not save item in localStorage: ${key}. [${error}]`); throw new Error(`Could not save item in localStorage: ${key}. [${error}]`);
return false;
} }
return true; return true;
} }

View File

@ -345,18 +345,24 @@ export function updateHistory<T extends DataQuery = any>(
queries: T[] queries: T[]
): Array<HistoryItem<T>> { ): Array<HistoryItem<T>> {
const ts = Date.now(); const ts = Date.now();
let updatedHistory = history;
queries.forEach(query => { queries.forEach(query => {
history = [{ query, ts }, ...history]; updatedHistory = [{ query, ts }, ...updatedHistory];
}); });
if (history.length > MAX_HISTORY_ITEMS) { if (updatedHistory.length > MAX_HISTORY_ITEMS) {
history = history.slice(0, MAX_HISTORY_ITEMS); updatedHistory = updatedHistory.slice(0, MAX_HISTORY_ITEMS);
} }
// Combine all queries of a datasource type into one history // Combine all queries of a datasource type into one history
const historyKey = `grafana.explore.history.${datasourceId}`; const historyKey = `grafana.explore.history.${datasourceId}`;
store.setObject(historyKey, history); try {
return history; store.setObject(historyKey, updatedHistory);
return updatedHistory;
} catch (error) {
console.error(error);
return history;
}
} }
export function clearHistory(datasourceId: string) { export function clearHistory(datasourceId: string) {

View File

@ -2,7 +2,8 @@
import _ from 'lodash'; import _ from 'lodash';
// Services & Utils // Services & Utils
import { DataQuery, ExploreMode, dateTime, urlUtil } from '@grafana/data'; import { DataQuery, ExploreMode, dateTime, AppEvents, urlUtil } from '@grafana/data';
import appEvents from 'app/core/app_events';
import store from 'app/core/store'; import store from 'app/core/store';
import { serializeStateToUrlParam, SortOrder } from './explore'; import { serializeStateToUrlParam, SortOrder } from './explore';
import { getExploreDatasources } from '../../features/explore/state/selectors'; import { getExploreDatasources } from '../../features/explore/state/selectors';
@ -55,18 +56,17 @@ export function addToRichHistory(
return richHistory; return richHistory;
} }
let newHistory = [ let updatedHistory = [
{ queries: queriesToSave, ts, datasourceId, datasourceName, starred, comment, sessionName }, { queries: queriesToSave, ts, datasourceId, datasourceName, starred, comment, sessionName },
...queriesToKeep, ...queriesToKeep,
]; ];
/* Combine all queries of a datasource type into one rich history */ /* If updatedHistory is succesfully saved, return it. Otherwise return not updated richHistory. */
const isSaved = store.setObject(RICH_HISTORY_KEY, newHistory); try {
store.setObject(RICH_HISTORY_KEY, updatedHistory);
/* If newHistory is succesfully saved, return it. Otherwise return not updated richHistory. */ return updatedHistory;
if (isSaved) { } catch (error) {
return newHistory; appEvents.emit(AppEvents.alertError, [error]);
} else {
return richHistory; return richHistory;
} }
} }
@ -83,7 +83,7 @@ export function deleteAllFromRichHistory() {
} }
export function updateStarredInRichHistory(richHistory: RichHistoryQuery[], ts: number) { export function updateStarredInRichHistory(richHistory: RichHistoryQuery[], ts: number) {
const updatedQueries = richHistory.map(query => { const updatedHistory = richHistory.map(query => {
/* Timestamps are currently unique - we can use them to identify specific queries */ /* Timestamps are currently unique - we can use them to identify specific queries */
if (query.ts === ts) { if (query.ts === ts) {
const isStarred = query.starred; const isStarred = query.starred;
@ -93,8 +93,13 @@ export function updateStarredInRichHistory(richHistory: RichHistoryQuery[], ts:
return query; return query;
}); });
store.setObject(RICH_HISTORY_KEY, updatedQueries); try {
return updatedQueries; store.setObject(RICH_HISTORY_KEY, updatedHistory);
return updatedHistory;
} catch (error) {
appEvents.emit(AppEvents.alertError, [error]);
return richHistory;
}
} }
export function updateCommentInRichHistory( export function updateCommentInRichHistory(
@ -102,7 +107,7 @@ export function updateCommentInRichHistory(
ts: number, ts: number,
newComment: string | undefined newComment: string | undefined
) { ) {
const updatedQueries = richHistory.map(query => { const updatedHistory = richHistory.map(query => {
if (query.ts === ts) { if (query.ts === ts) {
const updatedQuery = Object.assign({}, query, { comment: newComment }); const updatedQuery = Object.assign({}, query, { comment: newComment });
return updatedQuery; return updatedQuery;
@ -110,14 +115,24 @@ export function updateCommentInRichHistory(
return query; return query;
}); });
store.setObject(RICH_HISTORY_KEY, updatedQueries); try {
return updatedQueries; store.setObject(RICH_HISTORY_KEY, updatedHistory);
return updatedHistory;
} catch (error) {
appEvents.emit(AppEvents.alertError, [error]);
return richHistory;
}
} }
export function deleteQueryInRichHistory(richHistory: RichHistoryQuery[], ts: number) { export function deleteQueryInRichHistory(richHistory: RichHistoryQuery[], ts: number) {
const updatedQueries = richHistory.filter(query => query.ts !== ts); const updatedHistory = richHistory.filter(query => query.ts !== ts);
store.setObject(RICH_HISTORY_KEY, updatedQueries); try {
return updatedQueries; store.setObject(RICH_HISTORY_KEY, updatedHistory);
return updatedHistory;
} catch (error) {
appEvents.emit(AppEvents.alertError, [error]);
return richHistory;
}
} }
export const sortQueries = (array: RichHistoryQuery[], sortOrder: SortOrder) => { export const sortQueries = (array: RichHistoryQuery[], sortOrder: SortOrder) => {

View File

@ -78,6 +78,10 @@ export function updatePanelEditorUIState(uiState: Partial<PanelEditorUIState>):
return (dispatch, getStore) => { return (dispatch, getStore) => {
const nextState = { ...getStore().panelEditor.ui, ...uiState }; const nextState = { ...getStore().panelEditor.ui, ...uiState };
dispatch(setPanelEditorUIState(nextState)); dispatch(setPanelEditorUIState(nextState));
store.setObject(PANEL_EDITOR_UI_STATE_STORAGE_KEY, nextState); try {
store.setObject(PANEL_EDITOR_UI_STATE_STORAGE_KEY, nextState);
} catch (error) {
console.error(error);
}
}; };
} }

View File

@ -114,7 +114,14 @@ class UnThemedRichHistory extends PureComponent<RichHistoryProps, RichHistorySta
}; };
onSelectDatasourceFilters = (value: SelectableValue[] | null) => { onSelectDatasourceFilters = (value: SelectableValue[] | null) => {
store.setObject(RICH_HISTORY_SETTING_KEYS.datasourceFilters, value); try {
store.setObject(RICH_HISTORY_SETTING_KEYS.datasourceFilters, value);
} catch (error) {
console.error(error);
}
/* Set data source filters to state even though they were not successfully saved in
* localStorage to allow interaction and filtering.
**/
this.setState({ datasourceFilters: value }); this.setState({ datasourceFilters: value });
}; };
@ -125,7 +132,7 @@ class UnThemedRichHistory extends PureComponent<RichHistoryProps, RichHistorySta
onChangeSortOrder = (sortOrder: SortOrder) => this.setState({ sortOrder }); onChangeSortOrder = (sortOrder: SortOrder) => this.setState({ sortOrder });
/* If user selects activeDatasourceOnly === true, set datasource filter to currently active datasource. /* If user selects activeDatasourceOnly === true, set datasource filter to currently active datasource.
* Filtering based on datasource won't be available. Otherwise set to null, as filtering will be * Filtering based on datasource won't be available. Otherwise set to null, as filtering will be
* available for user. * available for user.
*/ */
updateFilters() { updateFilters() {