From 4c3393d8b2725b6f3e89a4c17afb1bfca00a4f78 Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Fri, 9 Jan 2026 11:45:00 +0000 Subject: [PATCH] Fixed: - Databases now correctly closed after rebuilding. --- src/common/KeyValueDB.ts | 74 ++++++++++++++++++++--- src/lib | 2 +- src/modules/essential/ModuleKeyValueDB.ts | 11 ++-- src/modules/main/ModuleLiveSyncMain.ts | 2 + 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/common/KeyValueDB.ts b/src/common/KeyValueDB.ts index 732f059..ce9a229 100644 --- a/src/common/KeyValueDB.ts +++ b/src/common/KeyValueDB.ts @@ -1,5 +1,7 @@ import { deleteDB, type IDBPDatabase, openDB } from "idb"; import type { KeyValueDatabase } from "../lib/src/interfaces/KeyValueDatabase.ts"; +import { serialized } from "octagonal-wheels/concurrency/lock"; +import { Logger } from "octagonal-wheels/common/logger"; const databaseCache: { [key: string]: IDBPDatabase } = {}; export const OpenKeyValueDatabase = async (dbKey: string): Promise => { if (dbKey in databaseCache) { @@ -7,37 +9,89 @@ export const OpenKeyValueDatabase = async (dbKey: string): Promise | null = null; + const _openDB = () => { + return serialized("keyvaluedb-" + dbKey, async () => { + const dbInstance = await openDB(dbKey, 1, { + upgrade(db, _oldVersion, _newVersion, _transaction, _event) { + return db.createObjectStore(storeKey); + }, + blocking(currentVersion, blockedVersion, event) { + Logger( + `Blocking database open for ${dbKey}: currentVersion=${currentVersion}, blockedVersion=${blockedVersion}` + ); + databaseCache[dbKey]?.close(); + delete databaseCache[dbKey]; + }, + blocked(currentVersion, blockedVersion, event) { + Logger( + `Database open blocked for ${dbKey}: currentVersion=${currentVersion}, blockedVersion=${blockedVersion}` + ); + }, + terminated() { + Logger(`Database connection terminated for ${dbKey}`); + }, + }); + databaseCache[dbKey] = dbInstance; + return dbInstance; + }); + }; + const closeDB = () => { + if (db) { + db.close(); + delete databaseCache[dbKey]; + db = null; + } + }; + db = await _openDB(); return { async get(key: IDBValidKey): Promise { + if (!db) { + db = await _openDB(); + databaseCache[dbKey] = db; + } return await db.get(storeKey, key); }, async set(key: IDBValidKey, value: T) { + if (!db) { + db = await _openDB(); + databaseCache[dbKey] = db; + } return await db.put(storeKey, value, key); }, async del(key: IDBValidKey) { + if (!db) { + db = await _openDB(); + databaseCache[dbKey] = db; + } return await db.delete(storeKey, key); }, async clear() { + if (!db) { + db = await _openDB(); + databaseCache[dbKey] = db; + } return await db.clear(storeKey); }, async keys(query?: IDBValidKey | IDBKeyRange, count?: number) { + if (!db) { + db = await _openDB(); + databaseCache[dbKey] = db; + } return await db.getAllKeys(storeKey, query, count); }, close() { delete databaseCache[dbKey]; - return db.close(); + return closeDB(); }, async destroy() { delete databaseCache[dbKey]; - db.close(); - await deleteDB(dbKey); + // await closeDB(); + await deleteDB(dbKey, { + blocked() { + console.warn(`Database delete blocked for ${dbKey}`); + }, + }); }, }; }; diff --git a/src/lib b/src/lib index 1adec8f..bc761fc 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 1adec8f126aef7ba593e3d07ac0db923da5e5737 +Subproject commit bc761fcf579e3a9dee89d7679a56fa4bd56af176 diff --git a/src/modules/essential/ModuleKeyValueDB.ts b/src/modules/essential/ModuleKeyValueDB.ts index 7d835f1..3226203 100644 --- a/src/modules/essential/ModuleKeyValueDB.ts +++ b/src/modules/essential/ModuleKeyValueDB.ts @@ -50,27 +50,28 @@ export class ModuleKeyValueDB extends AbstractModule { return Promise.resolve(true); } _getSimpleStore(kind: string) { + const getDB = () => this.core.kvDB; const prefix = `${kind}-`; return { get: async (key: string): Promise => { - return await this.core.kvDB.get(`${prefix}${key}`); + return await getDB().get(`${prefix}${key}`); }, set: async (key: string, value: any): Promise => { - await this.core.kvDB.set(`${prefix}${key}`, value); + await getDB().set(`${prefix}${key}`, value); }, delete: async (key: string): Promise => { - await this.core.kvDB.del(`${prefix}${key}`); + await getDB().del(`${prefix}${key}`); }, keys: async ( from: string | undefined, to: string | undefined, count?: number | undefined ): Promise => { - const ret = this.core.kvDB.keys( + const ret = await getDB().keys( IDBKeyRange.bound(`${prefix}${from || ""}`, `${prefix}${to || ""}`), count ); - return (await ret) + return ret .map((e) => e.toString()) .filter((e) => e.startsWith(prefix)) .map((e) => e.substring(prefix.length)); diff --git a/src/modules/main/ModuleLiveSyncMain.ts b/src/modules/main/ModuleLiveSyncMain.ts index 22c5734..9aa5ff0 100644 --- a/src/modules/main/ModuleLiveSyncMain.ts +++ b/src/modules/main/ModuleLiveSyncMain.ts @@ -16,6 +16,7 @@ import { AbstractModule } from "../AbstractModule.ts"; import { EVENT_PLATFORM_UNLOADED } from "../../lib/src/PlatformAPIs/base/APIBase.ts"; import type { InjectableServiceHub } from "../../lib/src/services/InjectableServices.ts"; import type { LiveSyncCore } from "../../main.ts"; +import { initialiseWorkerModule } from "@/lib/src/worker/bgWorker.ts"; export class ModuleLiveSyncMain extends AbstractModule { async _onLiveSyncReady() { @@ -80,6 +81,7 @@ export class ModuleLiveSyncMain extends AbstractModule { } async _onLiveSyncLoad(): Promise { + initialiseWorkerModule(); await this.services.appLifecycle.onWireUpEvents(); // debugger; eventHub.emitEvent(EVENT_PLUGIN_LOADED, this.core);