DallasHoff / sqlocal

SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.
https://sqlocal.dallashoffman.com
MIT License
315 stars 14 forks source link

Method to check persistence type from application code #30

Closed rhazn closed 3 months ago

rhazn commented 3 months ago

I am using sqlocal in a small project of mine - thank you for your work!

The issue I am facing is that I want to permanently persist data for a PWA, but I am unable to determine if the persistence actually worked because sqlocal seems to swallow the errors and fall back to a non-persistent database.

This is especially an issue with iOS 16.4 which seems to silently fail with a timeout in SQLite:

[Warning] Ignoring inability to install OPFS sqlite3_vfs: – "Timeout while waiting for OPFS async proxy worker." (sqlite3-bundler-friendly.mjs, line 13461)
[Warning] The origin private file system is not available, so database.sqlite3 will not be persisted. Make sure your web server is configured to use the correct HTTP response headers (See https://sqlocal.dallashoffman.com/guide/setup#cross-origin-isolation). (processor.js, line 67)

(see SQLite change here: https://sqlite.org/src/info/4fc1904b8e18c7d41fa65490ced125f1df4f0c22c13de957b24615ed09b3ecb7, forum discussion here: https://sqlite.org/forum/forumpost/a708c98dcb3ef).

I would love to catch any issues with persistence and notify the user that their data will be lost when they close the application, but so far I've failed to do so. The OPFS is available in iOS 16.4 (at least navigator.storage.getDirectory() resolves), new SQLocal resolves, I can even successfully query it because the database silently falls back to a non-persistent option.

Is there a way to detect that persistence has failed? If not, would you be open to a PR that introduces a way to do so?

DallasHoff commented 3 months ago

Very good point. SQLocal currently assumes that the persistence would fail to initialize for only 2 reasons: OPFS is not supported by the browser being used or your HTTP headers are not configured correctly. However, it looks like while Safari 16 supports OPFS, its implementation has bugs which make SQLite WASM incompatible with it. These bugs were fixed in Safari 17. Because of this, there exists a case where the browser could both report OPFS support and have the right headers but still not be capable of persisting the database.

As you described, there's no real way of knowing if the persistence is enabled from application code, but because of that case, there is a need for it. I will add a getter to the library that reports whether the database is being stored in the OPFS or in memory in the next update.

DallasHoff commented 3 months ago

I just released version 0.10.0 which adds a getDatabaseInfo method.