Loading changes from other sessions/tabs with sqlite-wasm localStorage
(1) By Søren Sjørup (zorendk) on 2023-11-01 18:26:50 [link] [source]
I'm using a sqlite-wasm database in localStorage
created with oo1.JsStorageDb('local');
and it's working great! I haven't found an elegant solution for incoming changes from other sessions/tabs. The following seems to be working. I'm using journal_mode=DELETE
and from the minimal testing I've done it seems the last storage event that happens is the journal being deleted. But hardcoding 'kvvfs-local-jrnl'
seems brittle.
// listen for changes from other sessions
addEventListener('storage', (event) => {
// when other session clears the journal, it means it has committed potentially changing all data
if (
event.storageArea === localStorage &&
event.key === 'kvvfs-local-jrnl' &&
event.newValue === null
) {
// load data from other session
}
});
Is there a better way?
Kind regards Søren
(2) By Stephan Beal (stephan) on 2023-11-01 18:46:06 in reply to 1 [source]
I haven't found an elegant solution for incoming changes from other sessions/tabs. The following seems to be working. I'm using journal_mode=DELETE and from the minimal testing I've done it seems the last storage event that happens is the journal being deleted. But hardcoding 'kvvfs-local-jrnl' seems brittle. ... Is there a better way?
That is an excellent question with, unfortunately, no readily-available answer. Frankly, we've never done any intensive cross-tab testing on a kvvfs-hosted database and current priorities won't give me the bandwidth to explore that in detail for the near-term future.
But hardcoding 'kvvfs-local-jrnl' seems brittle
It does fundamentally seem brittle but the name of that VFS and its pseudo-files are exceedingly unlikely to ever change because doing so would invalidate every existing local/session-storage db.
// listen for changes from other sessions
addEventListener('storage', (event)...
i literally didn't know that was possible but your solution, insofar as i can currently see, looks entirely plausible to me (despite the unsightliness of relying on an internal key name).
Perhaps we could teach the VFS to fire a custom event when a journal is deleted?
My current suggestion is to keep doing what you're doing and we can guaranty to never change those key names. If you eventually run into problems with this approach, or even if it continues to work great for you, i'd be very interested in hearing about it. Perhaps by then there will be another option in place, e.g. using Web Locks, with the caveat that Web Locks are async and the VFS API is synchronous, so such locks would need to happen in higher-level (probably client-level) code.
(3) By Søren Sjørup (zorendk) on 2023-11-08 10:42:59 in reply to 2 [link] [source]
Dear Stephan
Thank you very much for your kind response.
I agree that firing a custom event on JsStorageDb would be nice.
I was mainly using localStorage for a blog post where I implement TodoMVC using sqlite-wasm, so it's not a great concern for me.
You can try it out(it has a live SQL console) and read about it here: http://zoren.dk/todomvsqlite.html
/Søren
(4) By Stephan Beal (stephan) on 2023-11-08 13:05:33 in reply to 3 [link] [source]
I agree that firing a custom event on JsStorageDb would be nice.
In hindsight, my only concern with that is that it's far removed from the rest of the API, so seems a bit like a back door. How about if, instead, we add something like:
sqlite3_js_kvvfs_onSOMETHING( callback )
where SOMETHING is a to-be-determined appropriate name (feel free to suggest something) and callback is a function which receives:
{
target: localStorage|sessionStorage
... maybe other info? Any suggestions?
}
We could implement that in terms of an event listener, but i'd prefer to make it part of the visible API rather than hiding it entirely behind an event listener.
(5) By Roy Hashimoto (rhashimoto) on 2023-11-08 16:54:58 in reply to 1 [link] [source]
I don't think this is the right approach. Your todo app knows exactly when it modifies the database, so it can easily notify other instances at the application level (I would use BroadcastChannel, but you could use an application-specific localStorage key if you want the same browser compatibility). Getting reactivity from the database might be a cool feature but I don't think it's needed here.
(6) By Stephan Beal (stephan) on 2023-11-08 18:07:52 in reply to 5 [link] [source]
(I would use BroadcastChannel, but you could use an application-specific localStorage key if you want the same browser compatibility)
@Søren FWIW, i'd trust Roy's intuition on that over my own! He's far more in touch with modern JS than i am. i'll hold off on adding an event handler to the library for now.
(7) By Søren Sjørup (zorendk) on 2023-11-09 11:52:35 in reply to 6 [link] [source]
Thank you both very much. I've updated the blog and code to use a BroadcastChannel. And it is indeed much more elegant!