CB-3970: move error handlers closer to components (#1983)

* CB-3970: move error handlers closer to components

* CB-3970: handle errors of opening navNode

* CB-3970 fix: interrupt executor instead of throwing error
This commit is contained in:
Dmitriy Osipov
2023-09-07 14:42:42 +03:00
committed by GitHub
parent f479d8410a
commit ff32a5a577
6 changed files with 69 additions and 48 deletions
@@ -241,7 +241,7 @@ export class ConnectionNavNodeService extends Dependency {
connection = await this.connectionsManagerService.requireConnection(createConnectionParam(connection));
if (!connection?.connected) {
throw new Error('Connection not established');
ExecutorInterrupter.interrupt(contexts);
}
}
}
@@ -198,6 +198,15 @@ export class NotificationService {
console.error(exception);
}
throwSilently(exception: Error | GQLError | undefined | null): void {
this.logError({
title: '',
details: exception,
isSilent: true,
});
throw exception;
}
close(id: number, delayDeleting = true): void {
// TODO: emit event or something
@@ -153,6 +153,15 @@ export function useElementsTree(options: IOptions): IElementsTree {
options.expandStateGetters = useMemo(() => options.expandStateGetters || [], [...(options.expandStateGetters || [])]);
const state = options.localState || localTreeNodesState;
async function handleLoadChildren(id: string, manual: boolean): Promise<boolean> {
try {
return await options.loadChildren(id, manual);
} catch (exception: any) {
notificationService.logException(exception);
return false;
}
}
const functionsRef = useObjectRef({
async loadTree(nodeId: string) {
elementsTree.loading = true;
@@ -194,7 +203,7 @@ export function useElementsTree(options: IOptions): IElementsTree {
return;
}
const loaded = await options.loadChildren(child, false);
const loaded = await handleLoadChildren(child, false);
if (!loaded) {
const node = navNodeInfoResource.get(child);
@@ -530,7 +539,7 @@ export function useElementsTree(options: IOptions): IElementsTree {
if (!leaf && this.settings?.foldersTree && expandableOrExpanded) {
const nodeId = node.id;
const loaded = await options.loadChildren(node.id, true);
const loaded = await handleLoadChildren(node.id, false);
if (loaded) {
this.setFilter('');
options.folderExplorer.open(path, nodeId);
@@ -549,7 +558,7 @@ export function useElementsTree(options: IOptions): IElementsTree {
try {
if (state || (this.filtering && !treeNodeState.showInFilter)) {
state = await options.loadChildren(node.id, true);
state = await handleLoadChildren(node.id, true);
}
if (this.filtering) {
@@ -611,7 +620,7 @@ export function useElementsTree(options: IOptions): IElementsTree {
async loadPath(path: string[], lastNode?: string): Promise<string | undefined> {
let lastLoadedNode: string | undefined;
for (const nodeId of path) {
const loaded = await options.loadChildren(nodeId, false);
const loaded = await handleLoadChildren(nodeId, false);
if (!loaded) {
return lastLoadedNode;
@@ -72,53 +72,43 @@ export class NavigationTreeService extends View<string> {
await this.navNodeManagerService.navToNode(id, parentId);
}
async loadNestedNodes(id = ROOT_NODE_PATH, tryConnect?: boolean, notify = true): Promise<boolean> {
try {
if (this.isConnectionNode(id)) {
let connection = this.connectionInfoResource.getConnectionForNode(id);
async loadNestedNodes(id = ROOT_NODE_PATH, tryConnect?: boolean): Promise<boolean> {
if (this.isConnectionNode(id)) {
let connection = this.connectionInfoResource.getConnectionForNode(id);
if (connection) {
connection = await this.connectionInfoResource.load(createConnectionParam(connection));
} else {
return false;
}
if (!connection.connected) {
if (!tryConnect) {
return false;
}
try {
const connected = await this.tryInitConnection(createConnectionParam(connection));
if (!connected) {
return false;
}
} catch {
return false;
}
}
}
await this.navTreeResource.waitLoad();
if (tryConnect && this.navTreeResource.getException(id)) {
this.navTreeResource.markOutdated(id);
}
const parents = this.navNodeInfoResource.getParents(id);
if (parents.length > 0 && !this.navNodeInfoResource.has(id)) {
if (connection) {
connection = await this.connectionInfoResource.load(createConnectionParam(connection));
} else {
return false;
}
await this.navTreeResource.load(CachedResourcePageKey(CACHED_RESOURCE_DEFAULT_PAGE_OFFSET, this.navTreeResource.childrenLimit).setTarget(id));
return true;
} catch (exception: any) {
if (notify) {
this.notificationService.logException(exception);
if (!connection.connected) {
if (!tryConnect) {
return false;
}
const connected = await this.tryInitConnection(createConnectionParam(connection));
if (!connected) {
return false;
}
}
}
return false;
await this.navTreeResource.waitLoad();
if (tryConnect && this.navTreeResource.getException(id)) {
this.navTreeResource.markOutdated(id);
}
const parents = this.navNodeInfoResource.getParents(id);
if (parents.length > 0 && !this.navNodeInfoResource.has(id)) {
return false;
}
await this.navTreeResource.load(CachedResourcePageKey(CACHED_RESOURCE_DEFAULT_PAGE_OFFSET, this.navTreeResource.childrenLimit).setTarget(id));
return true;
}
selectNode(id: string, multiple?: boolean): void {
@@ -7,6 +7,7 @@
*/
import { useObjectRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import type { NavNode } from '@cloudbeaver/core-navigation-tree';
import { NavigationTreeService } from './NavigationTreeService';
@@ -22,13 +23,19 @@ const bindActions: Array<keyof INavigationTree> = ['handleOpen', 'handleSelect',
export function useNavigationTree(): INavigationTree {
const navigationTreeService = useService(NavigationTreeService);
const notificationService = useService(NotificationService);
return useObjectRef<INavigationTree>(
() => ({
navigationTreeService,
async handleOpen(node: NavNode, folder: boolean) {
if (!folder) {
await this.navigationTreeService.navToNode(node.id, node.parentId);
try {
await this.navigationTreeService.navToNode(node.id, node.parentId);
} catch (exception: any) {
notificationService.logException(exception);
throw exception;
}
}
},
handleSelect(node: NavNode, state: boolean) {
@@ -30,6 +30,7 @@ import {
getRealExecutionContextId,
} from '@cloudbeaver/core-connections';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { NodeManagerUtils } from '@cloudbeaver/core-navigation-tree';
import type { ISqlEditorTabState } from './ISqlEditorTabState';
@@ -50,6 +51,7 @@ export const SqlEditorOverlay = observer<Props>(function SqlEditorOverlay({ stat
const translate = useTranslate();
const sqlEditorService = useService(SqlEditorService);
const sqlDataSourceService = useService(SqlDataSourceService);
const notificationService = useService(NotificationService);
const dataSource = sqlDataSourceService.get(state.editorId);
const executionContextId = dataSource?.executionContext?.id;
const executionContext = dataSource?.executionContext;
@@ -77,7 +79,11 @@ export const SqlEditorOverlay = observer<Props>(function SqlEditorOverlay({ stat
}
async function init() {
await sqlEditorService.initEditorConnection(state);
try {
await sqlEditorService.initEditorConnection(state);
} catch (exception: any) {
notificationService.logException(exception);
}
}
const dataContainer = getComputed(() =>