fix(ultrawork): handle bun:sqlite import failure directly
Use the lazy bun:sqlite importer inside the deferred override microtask and keep the unavailable-runtime test on the rejected-import path. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test"
|
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"
|
||||||
import * as sharedModule from "../shared"
|
import * as loggerModule from "../shared/logger"
|
||||||
import {
|
import {
|
||||||
scheduleDeferredModelOverride,
|
scheduleDeferredModelOverride,
|
||||||
__setBunSqliteImporterForTesting,
|
|
||||||
__resetBunSqliteImporterForTesting,
|
__resetBunSqliteImporterForTesting,
|
||||||
|
__setBunSqliteImporterForTesting,
|
||||||
} from "./ultrawork-db-model-override"
|
} from "./ultrawork-db-model-override"
|
||||||
|
|
||||||
function flushMicrotasks(depth: number): Promise<void> {
|
function flushMicrotasks(depth: number): Promise<void> {
|
||||||
@@ -25,22 +25,22 @@ describe("scheduleDeferredModelOverride bun:sqlite unavailable", () => {
|
|||||||
let logCalls: Array<[string, Record<string, unknown>?]> = []
|
let logCalls: Array<[string, Record<string, unknown>?]> = []
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Simulate non-Bun runtime (Node/Electron): bun:sqlite import returns null
|
spyOn(loggerModule, "log").mockImplementation((message: string, metadata?: Record<string, unknown>) => {
|
||||||
__setBunSqliteImporterForTesting(async () => null)
|
|
||||||
|
|
||||||
spyOn(sharedModule, "log").mockImplementation((message: string, metadata?: Record<string, unknown>) => {
|
|
||||||
logCalls.push([message, metadata])
|
logCalls.push([message, metadata])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
__resetBunSqliteImporterForTesting()
|
__resetBunSqliteImporterForTesting()
|
||||||
mock.restore()
|
|
||||||
logCalls = []
|
logCalls = []
|
||||||
})
|
})
|
||||||
|
|
||||||
test("#given non-Bun runtime #when scheduleDeferredModelOverride is called #then it returns without throwing", async () => {
|
test("#given bun:sqlite import fails #when scheduleDeferredModelOverride is called #then it returns without throwing", async () => {
|
||||||
//#given
|
//#given
|
||||||
|
__setBunSqliteImporterForTesting(async () => {
|
||||||
|
throw new Error("bun:sqlite unavailable")
|
||||||
|
})
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
expect(() => {
|
expect(() => {
|
||||||
scheduleDeferredModelOverride("msg_unavailable", {
|
scheduleDeferredModelOverride("msg_unavailable", {
|
||||||
@@ -52,9 +52,9 @@ describe("scheduleDeferredModelOverride bun:sqlite unavailable", () => {
|
|||||||
await flushMicrotasks(5)
|
await flushMicrotasks(5)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
const logMessages = logCalls.map(([msg]) => msg)
|
expect(logCalls).toContainEqual([
|
||||||
expect(logMessages).toContain(
|
"[ultrawork-db-override] bun:sqlite unavailable (non-Bun runtime), skipping",
|
||||||
"[ultrawork-db-override] bun:sqlite unavailable (non-Bun runtime), skipping deferred override",
|
undefined,
|
||||||
)
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,20 +6,16 @@ import { log } from "../shared"
|
|||||||
type BunDatabase = import("bun:sqlite").Database
|
type BunDatabase = import("bun:sqlite").Database
|
||||||
type SqliteModule = { Database: new (path: string) => BunDatabase }
|
type SqliteModule = { Database: new (path: string) => BunDatabase }
|
||||||
|
|
||||||
/** @internal test-only seam: override to simulate non-Bun runtime */
|
let bunSqliteImporter: () => Promise<SqliteModule> = () => import("bun:sqlite")
|
||||||
let _bunSqliteImporter: () => Promise<SqliteModule | null> = () =>
|
|
||||||
import("bun:sqlite").catch(() => null) as Promise<SqliteModule | null>
|
|
||||||
|
|
||||||
/** @internal test-only */
|
|
||||||
export function __setBunSqliteImporterForTesting(
|
export function __setBunSqliteImporterForTesting(
|
||||||
impl: () => Promise<SqliteModule | null>,
|
importer: () => Promise<SqliteModule>,
|
||||||
): void {
|
): void {
|
||||||
_bunSqliteImporter = impl
|
bunSqliteImporter = importer
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal test-only */
|
|
||||||
export function __resetBunSqliteImporterForTesting(): void {
|
export function __resetBunSqliteImporterForTesting(): void {
|
||||||
_bunSqliteImporter = () => import("bun:sqlite").catch(() => null) as Promise<SqliteModule | null>
|
bunSqliteImporter = () => import("bun:sqlite")
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDbPath(): string {
|
function getDbPath(): string {
|
||||||
@@ -124,7 +120,6 @@ function retryViaMicrotask(
|
|||||||
* Session.updateMessage() to save the message first, then overwrites the model.
|
* Session.updateMessage() to save the message first, then overwrites the model.
|
||||||
*
|
*
|
||||||
* Falls back to setTimeout(fn, 0) after 10 microtask attempts.
|
* Falls back to setTimeout(fn, 0) after 10 microtask attempts.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
export function scheduleDeferredModelOverride(
|
export function scheduleDeferredModelOverride(
|
||||||
messageId: string,
|
messageId: string,
|
||||||
@@ -132,16 +127,14 @@ export function scheduleDeferredModelOverride(
|
|||||||
variant?: string,
|
variant?: string,
|
||||||
): void {
|
): void {
|
||||||
queueMicrotask(async () => {
|
queueMicrotask(async () => {
|
||||||
// Lazy-load bun:sqlite so this module can be imported under Node/Electron
|
let DatabaseCtor: (new (path: string) => import("bun:sqlite").Database) | undefined
|
||||||
// without crashing the ESM loader (bun: protocol is Bun-only).
|
try {
|
||||||
const sqliteModule = await _bunSqliteImporter()
|
DatabaseCtor = (await bunSqliteImporter()).Database
|
||||||
if (sqliteModule === null) {
|
} catch {
|
||||||
log("[ultrawork-db-override] bun:sqlite unavailable (non-Bun runtime), skipping deferred override")
|
log("[ultrawork-db-override] bun:sqlite unavailable (non-Bun runtime), skipping")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { Database } = sqliteModule
|
|
||||||
|
|
||||||
const dbPath = getDbPath()
|
const dbPath = getDbPath()
|
||||||
if (!existsSync(dbPath)) {
|
if (!existsSync(dbPath)) {
|
||||||
log("[ultrawork-db-override] DB not found, skipping deferred override")
|
log("[ultrawork-db-override] DB not found, skipping deferred override")
|
||||||
@@ -150,7 +143,7 @@ export function scheduleDeferredModelOverride(
|
|||||||
|
|
||||||
let db: BunDatabase
|
let db: BunDatabase
|
||||||
try {
|
try {
|
||||||
db = new Database(dbPath)
|
db = new DatabaseCtor(dbPath)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log("[ultrawork-db-override] Failed to open DB, skipping deferred override", {
|
log("[ultrawork-db-override] Failed to open DB, skipping deferred override", {
|
||||||
messageId,
|
messageId,
|
||||||
|
|||||||
Reference in New Issue
Block a user