diff --git a/xmcl-electron-app/main/ElectronLauncherApp.ts b/xmcl-electron-app/main/ElectronLauncherApp.ts index 0b6d82f95..a4ce308ae 100644 --- a/xmcl-electron-app/main/ElectronLauncherApp.ts +++ b/xmcl-electron-app/main/ElectronLauncherApp.ts @@ -131,6 +131,8 @@ export default class ElectronLauncherApp extends LauncherApp { code = NetworkErrorCode.NETWORK_CHANGED } else if (e.message === 'net::PROXY_CONNECTION_FAILED') { code = NetworkErrorCode.PROXY_CONNECTION_FAILED + } else if (e.message === 'net::ERR_UNEXPECTED') { + code = NetworkErrorCode.CONNECTION_RESET } if (code) { // expected exceptions diff --git a/xmcl-runtime/service/ServiceStateContainer.ts b/xmcl-runtime/service/ServiceStateContainer.ts index d37baea2c..16c14cc65 100644 --- a/xmcl-runtime/service/ServiceStateContainer.ts +++ b/xmcl-runtime/service/ServiceStateContainer.ts @@ -88,6 +88,10 @@ export class ServiceStateContainer implements ServiceStateContext { try { this.semaphore += 1 for (const [c] of this.#clients) { + if (c.isDestroyed()) { + this.untrack(c) + continue + } c.send('state-validating', { id: this.id, semaphore: this.semaphore }) } return await action @@ -95,6 +99,10 @@ export class ServiceStateContainer implements ServiceStateContext { this.semaphore -= 1 if (this.semaphore === 0) { for (const [c] of this.#clients) { + if (c.isDestroyed()) { + this.untrack(c) + continue + } c.send('state-validating', { id: this.id, semaphore: this.semaphore }) } } diff --git a/xmcl-runtime/sql/SqliteWASMDriver.ts b/xmcl-runtime/sql/SqliteWASMDriver.ts index a51ac191f..3699a7bd7 100644 --- a/xmcl-runtime/sql/SqliteWASMDriver.ts +++ b/xmcl-runtime/sql/SqliteWASMDriver.ts @@ -1,6 +1,8 @@ import { CompiledQuery, DatabaseConnection, Driver, QueryResult, SelectQueryNode } from 'kysely' import type { Database } from 'node-sqlite3-wasm' +import { SQLite3Error } from 'node-sqlite3-wasm' import { SqliteWASMDialectDatabaseConfig, SqliteWASMDialectWorkerConfig } from './SqliteWASMDialectConfig' +import { Exception } from '@xmcl/runtime-api' declare module 'node-sqlite3-wasm' { interface Statement { @@ -56,7 +58,7 @@ export class SqliteWASMDriver extends AbstractSqliteDriver { readonly #config: SqliteWASMDialectDatabaseConfig #db?: Database - #connection?: DatabaseConnection + #connection?: SqliteConnection constructor(config: SqliteWASMDialectDatabaseConfig) { super() @@ -76,17 +78,23 @@ export class SqliteWASMDriver extends AbstractSqliteDriver { } async destroy(): Promise { + this.#connection?.dispose() this.#db?.close() } } class SqliteConnection implements DatabaseConnection { readonly #db: Database + #disposed = false constructor(db: Database) { this.#db = db } + dispose() { + this.#disposed = true + } + executeQuery(compiledQuery: CompiledQuery): Promise> { const { sql, parameters } = compiledQuery const stmt = this.#db.prepare(sql) @@ -110,6 +118,11 @@ class SqliteConnection implements DatabaseConnection { : undefined, rows: [], }) + } catch (e) { + if (this.#disposed && e instanceof SQLite3Error) { + return Promise.reject(new Exception({ type: 'sqlite3Exception' }, e.message, { cause: e })) + } + return Promise.reject(e) } finally { stmt.finalize() }