Zenn
Open6

DuckDB-Wasm (OPFS) メモ

voluntasvoluntas

DuckDB-Wasm に OPFS 対応がマージされたので、自分用にメモしていきます。

Add OPFS (Origin Private File System) Support by e1arikawa · Pull Request #1856 · duckdb/duckdb-wasm

DuckDB-Wasm の OPFS 対応は DuckDB-Wasm のデータベース保存先を OPFS にするという仕組みです。この仕組みを利用することでブラウザを閉じてもデータが残るようになります。

今まで自前で Parquet ファイルなどを OPFS に保存する仕組みが一切不要になります。

npm パッケージ

2025 年 2 月 9 日現在で 1.29.1-dev68.0 で動作を確認しています。
https://www.npmjs.com/package/@duckdb/duckdb-wasm/v/1.29.1-dev68.0

voluntasvoluntas

利用方法はシンプルで db.instantiate した後に db.open で path に opfs:// から始めます。
書き込みと読み込みをするので、 accessMode を READ_WRITE にします。

import * as duckdb from '@duckdb/duckdb-wasm'
import duckdb_worker from '@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js?worker'
import duckdb_wasm from '@duckdb/duckdb-wasm/dist/duckdb-eh.wasm?url'

const worker = new duckdb_worker()
const logger = new duckdb.ConsoleLogger()
const db = new duckdb.AsyncDuckDB(logger, worker)
await db.instantiate(duckdb_wasm)
await db.open({
    path: 'opfs://duckdb-wasm-opfs.db',
    accessMode: duckdb.DuckDBAccessMode.READ_WRITE,
})

実際に書き込む場合は CHECKPOINT; を呼び出すことで、 OPFS の WAL から DB へ書き込まれます。
CHECKPOINT Statement – DuckDB

const con = await db.connect()
// ここで WRITE 処理を行う
await conn.send('CHECKPOINT;')
await conn.close()
voluntasvoluntas

OPFS に保存されるファイルの確認と削除

確認方法は OPFS Explorer がお勧めです。

削除は今のところ OPFS API をそのまま使う方法が良さそうです。

await db.terminate()
const opfsRoot = await navigator.storage.getDirectory()
await opfsRoot.removeEntry('duckdb-wasm-opfs.db').catch(() => {})
await opfsRoot.removeEntry('duckdb-wasm-opfs.db.wal').catch(() => {})

DuckDB-Wasm の OPFS のテストがそのまま利用してるので現時点ではこれで良さそうです。
https://github.com/duckdb/duckdb-wasm/blob/main/packages/duckdb-wasm/test/opfs.test.ts#L281-L306

voluntasvoluntas

課題

複数タブを開いたときの挙動が不安定。OPFS を両方から読もうとしてしまう。Web Locks API を利用してなんとかうまくやる必要がある。

作成者以外のコメントは許可されていません