fix: support worker memory resource fallback

This commit is contained in:
2026-08-02 20:54:48 -04:00
parent 4be5f521ff
commit 9cc5e7847e
3 changed files with 21 additions and 1 deletions

View File

@@ -32,6 +32,7 @@ const workerScope = globalThis as unknown as WorkerScope
let sqlite3: Sqlite3Static | undefined
let database: Database | undefined
let assetsDirectory: FileSystemDirectoryHandle | undefined
const transientResources = new Map<string, { resource: ProjectResource; bytes: Uint8Array }>()
let capabilities: PersistenceCapabilities = { mode: 'unavailable', sqliteWasm: false, opfs: false, schemaVersion: PROJECT_SCHEMA_VERSION, reason: 'SQLite WASM has not been initialized.' }
const cloneTree = (tree: ModelTreeItem[]) => tree.map((item) => ({ ...item, children: item.children ? [...item.children] : undefined }))
@@ -149,6 +150,12 @@ const recoveryReport = (documentId: string): ProjectRecoveryReport => {
const putResource = async (bytes: ArrayBuffer, mediaType: string): Promise<ProjectResource> => {
if (!database) throw new Error('Persistence database is not initialized.')
const hash = await hashBytes(bytes)
if (!capabilities.opfs) {
const existing = transientResources.get(hash)
const resource = { hash, byteLength: bytes.byteLength, mediaType, refCount: (existing?.resource.refCount || 0) + 1 }
transientResources.set(hash, { resource, bytes: new Uint8Array(bytes.slice(0)) })
return { ...resource }
}
const directory = await getAssetsDirectory()
const handle = await directory.getFileHandle(hash, { create: true })
const writable = await handle.createWritable()
@@ -162,6 +169,10 @@ const putResource = async (bytes: ArrayBuffer, mediaType: string): Promise<Proje
}
const getResource = async (hash: string): Promise<ArrayBuffer | null> => {
if (!capabilities.opfs) {
const resource = transientResources.get(hash)
return resource ? resource.bytes.slice().buffer : null
}
const directory = await getAssetsDirectory()
try {
const handle = await directory.getFileHandle(hash)
@@ -174,6 +185,13 @@ const getResource = async (hash: string): Promise<ArrayBuffer | null> => {
const releaseResource = async (hash: string) => {
if (!database) throw new Error('Persistence database is not initialized.')
if (!capabilities.opfs) {
const existing = transientResources.get(hash)
if (!existing) return
if (existing.resource.refCount > 1) existing.resource.refCount -= 1
else transientResources.delete(hash)
return
}
const resources = database.exec({ sql: 'SELECT ref_count FROM resources WHERE hash = ?', bind: [hash], rowMode: 'object', returnValue: 'resultRows' }) as Array<Record<string, string | number>>
const row = resources[0]
if (!row) return
@@ -188,7 +206,7 @@ const releaseResource = async (hash: string) => {
const handle = async (request: PersistenceRequest): Promise<PersistenceResponse> => {
try {
if (request.type === 'initialize') return { id: request.id, ok: true, type: 'initialized', capabilities: await initialize() }
if (request.type === 'dispose') { database?.close(); database = undefined; return { id: request.id, ok: true, type: 'disposed' } }
if (request.type === 'dispose') { database?.close(); database = undefined; transientResources.clear(); return { id: request.id, ok: true, type: 'disposed' } }
await initialize()
if (request.type === 'save-document') { const result = saveDocument(request.document); return { id: request.id, ok: true, type: 'saved', ...result } }
if (request.type === 'load-document') return { id: request.id, ok: true, type: 'loaded', document: loadDocument(request.documentId) }