From ff67e675a2404bcd4f168f13efff04b64060d22e Mon Sep 17 00:00:00 2001 From: mario4tier Date: Fri, 21 Jun 2024 23:02:11 -0400 Subject: [PATCH] VSCode extension - Minor fixes to error reporting. --- .../vscode-extension/src/BackendSync.ts | 38 ++++++++++---- .../vscode-extension/src/SuibaseExec.ts | 51 +++++++++++-------- update | 2 +- 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/typescript/vscode-extension/src/BackendSync.ts b/typescript/vscode-extension/src/BackendSync.ts index 71379931..c8045387 100644 --- a/typescript/vscode-extension/src/BackendSync.ts +++ b/typescript/vscode-extension/src/BackendSync.ts @@ -40,14 +40,13 @@ class BackendWorkdirTracking { export class BackendSync { private static sInstance?: BackendSync; - private mWorkdir: string; // Last known active workdir. One of "localnet", "mainnet", "testnet", "devnet". private mWorkdirTrackings: BackendWorkdirTracking[] = []; // One instance per workdir, align with WORKDIRS_KEYS. private mForceRefreshOnNextReconnect: boolean; // Force some refresh when there was a lost of backend connection. private activeWorkdir: string = WORKDIRS_KEYS[WORKDIR_IDX_TESTNET]; + private consecutiveNotRespondingCount = 0; // Singleton private constructor() { - this.mWorkdir = ""; this.mForceRefreshOnNextReconnect = false; // Create one instance of BackendWorkdirTracking for each element in WORKDIRS_KEYS. @@ -91,9 +90,6 @@ export class BackendSync { return BackendSync.sInstance; } - public get workdir(): string { - return this.mWorkdir; - } public handleViewMessage(message: any): void { try { @@ -249,6 +245,8 @@ export class BackendSync { const msg = new UpdateVersions(WEBVIEW_BACKEND, workdirIdx, undefined); const sb = SuibaseExec.getInstance(); + let isUnknownErr = false; + if (sb === undefined) { msg.setSetupIssue("Internal error. Shell commands failed."); } else if ((await sb.isGitInstalled()) === false) { @@ -267,18 +265,35 @@ export class BackendSync { // Started, but need a moment for the backend to init/respond. msg.setSetupIssue("Suibase backend connecting..."); } else { - // Did not start this time, but assumes the caller will retry, so - // report as still "starting" for now... - msg.setSetupIssue("Suibase backend starting..."); + isUnknownErr = true; } } else { - // Unknown cause... a temporary connectivity hiccup? - msg.setSetupIssue("Suibase backend not responding"); + isUnknownErr = true; + } + + if (isUnknownErr) { + // Report as "connecting" at first, and "not responding" after a while. + this.incrementNotRespondingCount(msg); + } else { + this.clearNotRespondingCount(); } BaseWebview.broadcastMessage(msg); } + private clearNotRespondingCount() { + this.consecutiveNotRespondingCount = 0; + } + + private incrementNotRespondingCount(msg: UpdateVersions) { + this.consecutiveNotRespondingCount++; + if (this.consecutiveNotRespondingCount > 60) { + msg.setSetupIssue("Suibase backend not responding"); + } else { + msg.setSetupIssue("Suibase backend connecting..."); + } + } + private reportSetupIssue(issueMsg: string) { this.mForceRefreshOnNextReconnect = true; @@ -306,6 +321,9 @@ export class BackendSync { } if (data) { + // The backend did respond with something... + this.clearNotRespondingCount(); + try { //console.log("update versions: ", JSON.stringify(data)); // This is an example of data: diff --git a/typescript/vscode-extension/src/SuibaseExec.ts b/typescript/vscode-extension/src/SuibaseExec.ts index eb677b04..5b0d53b7 100644 --- a/typescript/vscode-extension/src/SuibaseExec.ts +++ b/typescript/vscode-extension/src/SuibaseExec.ts @@ -13,7 +13,9 @@ import * as vscode from "vscode"; import * as cp from "child_process"; //import WebSocket from "ws"; import * as OS from "os"; +import * as fs from "fs/promises"; +// Execute the shell command and return its output. This is a blocking call. const execShell = (cmd: string) => new Promise((resolve, reject) => { cp.exec(cmd, (err, out) => { @@ -24,14 +26,20 @@ const execShell = (cmd: string) => }); }); -const execShellBackground = (cmd: string) => +// Execute the shell command in the background. +// +// This is a non-blocking call. +// +// It is assumed the caller does not depend on the command output +// to verify its success. +const execShellBackground = (cmd: string): Promise => // eslint-disable-next-line @typescript-eslint/no-unused-vars - new Promise((resolve, _reject) => { + new Promise((resolve) => { cp.exec(cmd, (err, stdout, stderr) => { if (err) { - console.warn(err); + console.warn(err,`${stdout}${stderr}`); } - resolve(stdout ? stdout : stderr); + resolve(); }); }); @@ -122,7 +130,7 @@ export class SuibaseExec { if (result.startsWith("rustc") && !result.includes("error")) { return true; } - } catch (error) { + } catch (error: any) { console.error("rustc not installed"); } return false; @@ -142,28 +150,28 @@ export class SuibaseExec { return false; } + public canonicalPath(pathname: string): string { + // Expand the pathname to its absolute path. + // This function must always resolve its promise. + if (pathname.startsWith("~")) { + pathname = pathname.replace(/^~/, SuibaseExec.homedir); + } + return pathname; + } + public async fileExists(pathname: string): Promise { // Returns true if the file exists on the filesystem. // Returns false on any error. // // This function must always resolve its promise. - pathname = pathname.replace("~", SuibaseExec.homedir); try { - let result = await execShell(`ls ${pathname}`); - result = result.toLowerCase(); - if ( - !result.includes(pathname) || - result.includes("cannot access") || - result.includes("no such") || - result.includes("not found") - ) { - console.error(`File ${pathname} not found`); - return false; - } - } catch (error) { - return false; + // Attempt to access the file + await fs.access(this.canonicalPath(pathname)); + return true; // If no error is thrown, the file exists + } catch (error: any) { + // console.error(`File ${pathname} not found:`, error.message); + return false; // If an error is thrown, the file does not exist } - return true; } public async isSuibaseInstalled(): Promise { @@ -255,7 +263,8 @@ export class SuibaseExec { if (!suibaseRunning) { // Start suibase daemon - void execShellBackground("~/suibase/scripts/common/run-daemon.sh suibase"); + const pathname = this.canonicalPath("~/suibase/scripts/common/run-daemon.sh"); + void execShellBackground( `${pathname} suibase` ); // Check for up to ~5 seconds that it is started. let attempts = 10; diff --git a/update b/update index 24f9382b..ea47ae37 100755 --- a/update +++ b/update @@ -16,7 +16,7 @@ _CUR_VER=$(echo "$_LOCALNET_CMD_OUTPUT" | { head -n 1; cat >/dev/null 2>&1; } | # Check if there are significant local changes. If any, protect the user # from doing further git operations. # shellcheck disable=SC2126 -if [ ! "$(git status --porcelain | grep -vE "Cargo.lock|Move.lock|\?\?|Cargo.toml|Move.toml|Suibase.toml|package.json" | wc -l)" -eq "0" ]; then +if [ ! "$(git status --porcelain | grep -vE "Cargo.lock|Move.lock|\?\?|Cargo.toml|Move.toml|Suibase.toml|package.json|index.js|update" | wc -l)" -eq "0" ]; then if [ -n "$_CUR_VER" ]; then echo "Current version $_CUR_VER" echo