From f3122008017dc880ebf3d72cccf0f7847ec2f1ce Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 2 Jul 2026 16:49:11 -0700 Subject: [PATCH 1/3] Better debug logging for Bulldozer globalThis --- apps/bulldozer-js/src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bulldozer-js/src/index.ts b/apps/bulldozer-js/src/index.ts index 0ab786c7f..30df9a394 100644 --- a/apps/bulldozer-js/src/index.ts +++ b/apps/bulldozer-js/src/index.ts @@ -76,8 +76,9 @@ const bulldozerDb = declareBulldozerDatabase( }), { migrations: schema.migrations }, ); -await traceSpan("bulldozer-js.applyRemainingMigrations", async () => await bulldozerDb.applyRemainingMigrations()); (globalThis as any).bulldozerDb = bulldozerDb; +console.log("Stored bulldozerDb in globalThis for pid " + process.pid); +await traceSpan("bulldozer-js.applyRemainingMigrations", async () => await bulldozerDb.applyRemainingMigrations()); function jsonResponse(body: unknown, init?: ResponseInit) { return new Response(JSON.stringify(body), { From c21fa2ee8873f29d0fc656a2f83c36915dfe2844 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 2 Jul 2026 16:52:27 -0700 Subject: [PATCH 2/3] Improve info logging for globalThis object --- apps/bulldozer-js/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bulldozer-js/src/index.ts b/apps/bulldozer-js/src/index.ts index 30df9a394..9d8415050 100644 --- a/apps/bulldozer-js/src/index.ts +++ b/apps/bulldozer-js/src/index.ts @@ -77,7 +77,7 @@ const bulldozerDb = declareBulldozerDatabase( { migrations: schema.migrations }, ); (globalThis as any).bulldozerDb = bulldozerDb; -console.log("Stored bulldozerDb in globalThis for pid " + process.pid); +console.log(`Stored bulldozerDb in globalThis for pid ${process.pid}. Run \`kill -USR1 ${process.pid} && node inspect 127.0.0.1:9229\` and then \`exec("globalThis.bulldozerDb")\` to inspect it.`); await traceSpan("bulldozer-js.applyRemainingMigrations", async () => await bulldozerDb.applyRemainingMigrations()); function jsonResponse(body: unknown, init?: ResponseInit) { From d568752a3d74c29c6c3ee150da6eb73fefcf37d6 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 2 Jul 2026 17:04:15 -0700 Subject: [PATCH 3/3] getDebugInfo() for Bulldozer --- .../src/databases/bulldozer/index.ts | 13 +++++++++++++ apps/bulldozer-js/src/databases/index.ts | 1 + .../low-level/implementations/in-memory.ts | 9 ++++++++- .../instant-availability.test.ts | 10 ++++++++++ .../implementations/instant-availability.ts | 17 +++++++++++++++++ .../databases/low-level/implementations/lmdb.ts | 15 +++++++++++++++ .../src/databases/piledriver/index.ts | 14 ++++++++++++++ 7 files changed, 78 insertions(+), 1 deletion(-) diff --git a/apps/bulldozer-js/src/databases/bulldozer/index.ts b/apps/bulldozer-js/src/databases/bulldozer/index.ts index ec9044120..c286ef9e3 100644 --- a/apps/bulldozer-js/src/databases/bulldozer/index.ts +++ b/apps/bulldozer-js/src/databases/bulldozer/index.ts @@ -579,6 +579,7 @@ function createTablesStateFromMigrations(migrations: readonly BulldozerDatabaseM } export type BulldozerDatabase = { + getDebugInfo(): any, listTables(): BulldozerDatabaseTableDescriptor[], debugPiledriverSnapshot?(): Promise, debugLowLevelSnapshot?(): Promise, @@ -641,6 +642,18 @@ export function declareBulldozerDatabase(piledriverDatabase: PiledriverDatabase, }; return { + getDebugInfo() { + return { + backend: "bulldozer", + constructorArguments: { piledriverDatabase, options }, + piledriverDatabase, + rootKey, + getRoot, + setRoot, + tablesState, + currentOperation, + }; + }, listTables: () => Object.entries(tablesState.tables).map(([tableId, tableState]) => ({ tableId, inputTableIds: { ...tableState.inputTableIds }, diff --git a/apps/bulldozer-js/src/databases/index.ts b/apps/bulldozer-js/src/databases/index.ts index a8fdbc5be..68a48c417 100644 --- a/apps/bulldozer-js/src/databases/index.ts +++ b/apps/bulldozer-js/src/databases/index.ts @@ -1,6 +1,7 @@ export type DatabaseSeq = (readonly (string | number)[] & { __brand: "hexclave-low-level-kv-store-seq" }); export type Database = { + getDebugInfo(): any, /** * Returns a promise that resolves once it is guaranteed that queries made from this database client will see the * given seq. diff --git a/apps/bulldozer-js/src/databases/low-level/implementations/in-memory.ts b/apps/bulldozer-js/src/databases/low-level/implementations/in-memory.ts index ecb5e3ef7..4a889fffc 100644 --- a/apps/bulldozer-js/src/databases/low-level/implementations/in-memory.ts +++ b/apps/bulldozer-js/src/databases/low-level/implementations/in-memory.ts @@ -127,8 +127,15 @@ export function declareInMemoryLowLevelDatabase(dbId: string): LowLevelDatabase return result; }; - return { + getDebugInfo() { + return { + backend: "in-memory", + constructorArguments: { dbId }, + inMemoryLowLevelKvStores, + debugEntriesByStoreId, + }; + }, declareKvDump(dumpId) { return declareInMemoryLowLevelKvStoreOrDump("dump", JSON.stringify([dbId, dumpId])); }, diff --git a/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.test.ts b/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.test.ts index d8a013c2b..030d0c993 100644 --- a/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.test.ts +++ b/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.test.ts @@ -38,6 +38,16 @@ function createSlowSetDatabase() { }, }; const db: LowLevelDatabase = { + getDebugInfo() { + return { + backend: "slow-set-test", + releaseSets, + setCallCount, + committed, + seqToPromise, + initialSeq, + }; + }, declareKvStore: () => store, declareKvDump: () => { throw new Error("not implemented"); diff --git a/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.ts b/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.ts index 329a722c2..bafc6a592 100644 --- a/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.ts +++ b/apps/bulldozer-js/src/databases/low-level/implementations/instant-availability.ts @@ -243,6 +243,23 @@ export function declareInstantAvailabilityLowLevelDatabase(wrapped: LowLevelData }; return { + getDebugInfo() { + return { + backend: "instant-availability", + constructorArguments: { wrapped, options }, + wrapped, + dbId, + maxPendingSeqRecords, + initialSeq, + seqRecords, + createdSeqRecords, + underlyingAvailableSeqRecords, + pendingSeqRecords, + currentWriteGateOperation, + pendingSeqRecordsChanged, + cacheMaps, + }; + }, declareKvStore(id) { return declareStoreOrDump(wrapped.declareKvStore(id) as LowLevelKvStore & LowLevelKvDump); }, diff --git a/apps/bulldozer-js/src/databases/low-level/implementations/lmdb.ts b/apps/bulldozer-js/src/databases/low-level/implementations/lmdb.ts index 60c9699f3..845fc74b9 100644 --- a/apps/bulldozer-js/src/databases/low-level/implementations/lmdb.ts +++ b/apps/bulldozer-js/src/databases/low-level/implementations/lmdb.ts @@ -243,6 +243,21 @@ export function declareLmdbLowLevelDatabase(options: { path: string, dbId?: stri }; return { + getDebugInfo() { + return { + backend: "lmdb", + constructorArguments: options, + dbId, + simulateReadMissDelayMs, + root, + meta, + currentVersion, + debugEntriesByStoreId, + seqToAvailability, + seqToDurability, + initialSeq, + }; + }, declareKvDump(dumpId) { return declareLmdbLowLevelKvStoreOrDump("dump", dumpId); }, diff --git a/apps/bulldozer-js/src/databases/piledriver/index.ts b/apps/bulldozer-js/src/databases/piledriver/index.ts index 40adc875f..7deb2c670 100644 --- a/apps/bulldozer-js/src/databases/piledriver/index.ts +++ b/apps/bulldozer-js/src/databases/piledriver/index.ts @@ -287,6 +287,20 @@ export function declarePiledriverDatabase(lowLevelDb: LowLevelDatabase, options: }; return { + getDebugInfo() { + return { + backend: "piledriver", + constructorArguments: { lowLevelDb, options }, + lowLevelDb, + rootStore, + heapDump, + heapObjectsByObject, + heapObjectsByHeapKeyBase64, + heapObjectsByHeapKeyFinalizer, + heapKeysAndSeqByHeapObjects, + heapReadCacheDisabled: options.disableHeapReadCache === true, + }; + }, async getRootObject(key): Promise<{ object: PiledriverObject, seq: DatabaseSeq }> { return await traceSpan("bulldozer-js.piledriver.getRootObject", async () => { const { buffer, seq: rootSeq } = await rootStore.get(key);