Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

openBrowserWASQLiteOPFSDatabase() never settles while a frozen tab holds the database

Đã đóng
#1,883 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
45/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
sqlite, typescript, vite
Lĩnh vực
database, web-dev

Hướng nghiên cứu

Start with openBrowserWASQLiteOPFSDatabase() and opfs-database.ts, then trace the OPFSCoopSyncVFS hand-over and Web Lock wait. Review create(), open_v2, and handleWorkerRequest for cancellation and error propagation, using the frozen-tab reproduction as the first test case. Done means callers can bound or abort the open, late completion releases the database, and relevant errors remain distinguishable.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

  • I've validated the bug against the latest version of DB packages

Describe the bug

If another tab has the database open and that tab is frozen, openBrowserWASQLiteOPFSDatabase() in a new tab never settles. The bundled OPFSCoopSyncVFS asks the current holder to hand over its access handles over a BroadcastChannel, then waits for the holder's Web Lock. A frozen tab can't answer. The open has no timeout or AbortSignal, so the caller can't give up and fall back to non-persisted sync. Anything waiting on the open, such as persisted collections reading their startup metadata, waits until the other tab thaws.

To Reproduce

A Vite app with @tanstack/[email protected] and [email protected]:

hang.html
<!doctype html>
<meta charset="utf-8" />
<title>Frozen holder repro</title>
<pre id="log">Opening…</pre>
<script type="module" src="./hang.js"></script>
hang.js
import { openBrowserWASQLiteOPFSDatabase } from "@tanstack/browser-db-sqlite-persistence";

// Tab A: load /hang.html and let it open the store. Freeze tab A, then load
// /hang.html in tab B. Tab B's open stays pending until tab A is thawed.
const log = document.querySelector("#log");
const started = performance.now();
const elapsed = () => `${((performance.now() - started) / 1000).toFixed(1)} s`;
const timer = setInterval(() => (log.textContent = `open pending for ${elapsed()}`), 250);
try {
  const db = await openBrowserWASQLiteOPFSDatabase({ databaseName: "repro.sqlite" });
  await db.execute("CREATE TABLE IF NOT EXISTS t (x)");
  await db.execute("INSERT INTO t VALUES (1)");
  log.textContent = `opened after ${elapsed()}`;
} catch (e) {
  log.textContent = `failed after ${elapsed()}: ${e.name}: ${e.message}`;
}
clearInterval(timer);
  1. Open /hang.html in tab A. It shows opened after 0.1 s.
  2. Freeze tab A by sending the DevTools protocol command Page.setWebLifecycleState with {"state": "frozen"} to it.
  3. Open /hang.html in tab B. It shows open pending for 15.0 s and keeps counting.
  4. Send {"state": "active"} to tab A. Tab B shows opened after 15.1 s.

main at 4c5a8de, which includes #1844, behaves the same when I build its opfs-database.ts against the 0.2.23 worker. Freezing fires freeze, not pagehide, so the new cleanup never runs.

Expected behavior

A way to bound the wait, such as an AbortSignal or timeout option on openBrowserWASQLiteOPFSDatabase(), so the caller can fall back to non-persisted sync. An abandoned open that completes later should release the database rather than keep holding it.

Desktop:

  • OS: Linux x86_64
  • Browser: Chrome, headless, driven over CDP
  • Version: 152.0.0.0

Additional context

  • I forced the freeze over CDP and haven't pinned down which real-world freezes hold the lock this way. Mobile browsers suspend background tabs, and any holder that never answers the hand-over request blocks the open the same way.
  • Our workaround races the open against a 2 s deadline, falls back to non-persisted semantics, and closes an open that lands after the deadline.
  • A related gap: errors thrown while OPFSCoopSyncVFS.create() runs still reach callers as OPFSWorkerRequestError with code: "INTERNAL" and only the message. #1844 adds the VFS cause to open_v2 failures, but create() runs outside that try, and handleWorkerRequest forwards error.message alone. Forwarding error.name too would let callers tell NoModificationAllowedError contention from other failures. The navigation failure that #1844 fixes arrived that way: Failed to execute 'removeEntry' on 'FileSystemDirectoryHandle' from the VFS's stale-directory sweep, reported upstream at rhashimoto/wa-sqlite#362.
Ngôn ngữ chính
TypeScript
Star
3.9k
Fork
267
Merge trung bình
1 ngày 7 giờ
Pull request đã merge (30 ngày)
123

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của TanStack/db

Tất cả issue của TanStack/db

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.