Skip to content

Commit

Permalink
Handle RPC errors within the connections UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
dfalbel committed Feb 27, 2024
1 parent 5143bd2 commit 88a4686
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
10 changes: 10 additions & 0 deletions extensions/positron-connections/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
"command": "positron.connections.closeConnection",
"title": "%commands.closeConnection.title%",
"icon": "$(debug-disconnect)"
},
{
"command": "positron.connections.refresh",
"title": "%commands.refresh.title%",
"icon": "$(refresh)"
}
],
"menus": {
Expand All @@ -62,6 +67,11 @@
"group": "inline",
"when": "viewItem == database"
},
{
"command": "positron.connections.refresh",
"group": "inline",
"when": "viewItem == database"
},
{
"command": "positron.connections.previewTable",
"group": "inline",
Expand Down
3 changes: 2 additions & 1 deletion extensions/positron-connections/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"view.welcome": "No database connections are currently active.",
"commands.previewTable.title": "Preview Table",
"commands.previewTable.category": "Connections",
"commands.closeConnection.title": "Close Connection"
"commands.closeConnection.title": "Close Connection",
"commands.refresh.title": "Refresh connection"
}
63 changes: 58 additions & 5 deletions extensions/positron-connections/src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class ConnectionItem {
return '';
}

async contains_data(): Promise<boolean> {
async contains_data(): Promise<boolean | undefined> {
return false;
}
}
Expand Down Expand Up @@ -74,6 +74,10 @@ export class ConnectionItemNode extends ConnectionItem {

const response = await this.client.performRpc({ msg_type: 'icon_request', path: this.path }) as any;

if (response.error) {
vscode.window.showErrorMessage(`Error getting icon for '${this.name}': ${response.error.message}`);
}

if (response.icon) {
this.iconPath = vscode.Uri.file(response.icon);
return this.iconPath;
Expand All @@ -84,13 +88,19 @@ export class ConnectionItemNode extends ConnectionItem {
}

override async contains_data() {
if (this.containsData) {
if (this.containsData !== undefined) {
return this.containsData;
}

const response = await this.client.performRpc({ msg_type: 'contains_data_request', path: this.path }) as any;
this.containsData = response.contains_data as boolean;

// on error we return 'undefined', a falsy value. Users can decide if that should fail or
// if the it can continue.
if (response.error) {
vscode.window.showErrorMessage(`Error checking if '${this.name}' contains data: ${response.error.message}`);
}

this.containsData = response.contains_data;
return this.containsData;
}

Expand All @@ -100,7 +110,12 @@ export class ConnectionItemNode extends ConnectionItem {
// does not contain data.
throw new Error('This item does not contain data');
}
await this.client.performRpc({ msg_type: 'preview_table', table: this.name, path: this.path });

const response = await this.client.performRpc({ msg_type: 'preview_table', table: this.name, path: this.path }) as any;

if (response.error) {
vscode.window.showErrorMessage(`Error previewing '${this.name}': ${response.error.message}`);
}
}
}

Expand Down Expand Up @@ -179,7 +194,15 @@ export class ConnectionItemsProvider implements vscode.TreeDataProvider<Connecti

treeItem.iconPath = await this.getTreeItemIcon(item);

if (await item.contains_data()) {
const contains_data = await item.contains_data();

if (contains_data === undefined) {
// There was an error determining if the object contains data. We set the collapsible
// state to None to prevent the user from trying to expand the item.
return this.errorTreeItem(item.name, 'Error determining if the item contains data');
}

if (contains_data) {
// if the item contains data, we set the contextValue enabling the UI for previewing the data
treeItem.contextValue = 'table';
}
Expand Down Expand Up @@ -208,6 +231,22 @@ export class ConnectionItemsProvider implements vscode.TreeDataProvider<Connecti
return icon;
}

errorTreeItem(name: string, message: string): vscode.TreeItem {
const treeItem = new vscode.TreeItem(name, vscode.TreeItemCollapsibleState.None);
treeItem.description = 'Error loading item. Click to retry.';
treeItem.tooltip = message;
treeItem.command = {
command: 'positron.connections.refresh',
title: 'Refresh',
};
treeItem.iconPath = new vscode.ThemeIcon('error', new vscode.ThemeColor('errorForeground'));
return treeItem;
}

public refresh() {
this._onDidChangeTreeData.fire(undefined);
}

/**
* Adds a connection to the pane.
*
Expand Down Expand Up @@ -257,6 +296,13 @@ export class ConnectionItemsProvider implements vscode.TreeDataProvider<Connecti
// The node is a view or a table so we want to get the fields on it.
if (await element.contains_data()) {
const response = await element.client.performRpc({ msg_type: 'fields_request', table: element.name, path: element.path }) as any;

if (response.error) {
// throwing an error here, triggers vscode to automatically show an error
// notification and continue.
throw new Error(`Error getting list of objects. Try refreshing the connection. Error message: ${response.error.message}`);
}

const fields = response.fields as Array<{ name: string; dtype: string }>;
return fields.map((field) => {
return new ConnectionItemField(field.name, field.dtype, element.client);
Expand All @@ -266,6 +312,13 @@ export class ConnectionItemsProvider implements vscode.TreeDataProvider<Connecti
// The node is a database, schema, or catalog, so we want to get the next set of elements in
// the tree.
const response = await element.client.performRpc({ msg_type: 'tables_request', name: element.name, kind: element.kind, path: element.path }) as any;

if (response.error) {
// throwing an error here, triggers vscode to automatically show an error
// notification and continue.
throw new Error(`Error getting list of objects. Try Refreshing the connection. Error message: ${response.error.message}`);
}

const children = response.tables as Array<{ name: string; kind: string }>;
return children.map((obj) => {
const path = [...element.path, { name: obj.name, kind: obj.kind }];
Expand Down
6 changes: 6 additions & 0 deletions extensions/positron-connections/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,10 @@ export function activate(context: vscode.ExtensionContext) {
(item: ConnectionItemDatabase) => {
item.close();
}));

context.subscriptions.push(
vscode.commands.registerCommand('positron.connections.refresh',
() => {
connectionProvider.refresh();
}));
}

0 comments on commit 88a4686

Please sign in to comment.