LegendApp / legend-state

Legend-State is a super fast and powerful state library that enables fine-grained reactivity and easy automatic persistence
https://legendapp.com/open-source/state/
MIT License
2.59k stars 76 forks source link

Error when attempting to delete with indexedDB persistence #327

Open warrenbhw opened 1 week ago

warrenbhw commented 1 week ago

I have a nextJS app router application, and I'm using syncedSupabase and indexedDB persistence. When I attempt to delete an observable, I see this error in the console:

Uncaught (in promise) DOMException: Failed to execute 'put' on 'IDBObjectStore': Symbol(delete) could not be cloned.
    at ObservablePersistIndexedDB._setItem (webpack-internal:///(app-pages-browser)/./node_modules/@legendapp/state/persist-plugins/indexeddb.mjs:340:20)
    at eval (webpack-internal:///(app-pages-browser)/./node_modules/@legendapp/state/persist-plugins/indexeddb.mjs:197:28)
    at Set.forEach (<anonymous>)
    at eval (webpack-internal:///(app-pages-browser)/./node_modules/@legendapp/state/persist-plugins/indexeddb.mjs:196:17)
    at Array.forEach (<anonymous>)
    at eval (webpack-internal:///(app-pages-browser)/./node_modules/@legendapp/state/persist-plugins/indexeddb.mjs:188:33)
    at Map.forEach (<anonymous>)
    at ObservablePersistIndexedDB.doSave (webpack-internal:///(app-pages-browser)/./node_modules/@legendapp/state/persist-plugins/indexeddb.mjs:187:23)
_setItem @ indexeddb.mjs:335
eval @ indexeddb.mjs:192
eval @ indexeddb.mjs:191
eval @ indexeddb.mjs:183
doSave @ indexeddb.mjs:182
Show 5 more frames
Show less

CleanShot 2024-07-04 at 20 57 43@2x

warrenbhw commented 1 week ago

hmmm... thinking about this for a few mins, I'm thinking this may be about soft vs. hard delete. It sounds like this may be happening because under-the-hood, legend-state is trying to set a "deleted" column, but I don't current have a "deleted" column on my table

Will try adding that and see what changes

warrenbhw commented 1 week ago

OK - that did seem to be the issue. Needed a deleted column on the table. Closing.

jmeistrich commented 1 week ago

This is a problem, I'll look into it.

warrenbhw commented 6 days ago

@jmeistrich two somewhat related questions...

  1. When using indexedDB persistence, what's the best way to force a reset of the indexedDB? If I had some code that makes bad writes and puts my app in a weird state, I'd love to have a way to force a clean reset for users.
  2. What does changing the version of the indexedDB config actually do under-the-hood? Will it trigger what I'm describing in (1.)?
warrenbhw commented 6 days ago

@jmeistrich possibly related:

wen I turn off local persistence, but turn on realtime subscription from supabase, deleting a row in supabase (from a different client) causes my local state to update so that I actually create a new row with no attributes, but don't delete the row that should be deleted.

my suspicion is that somewhere we're doing a set/assign/update (whatever the appropriate term is in this context) rather than a delete.

jmeistrich commented 3 days ago

I believe alpha.26 should fix this problem. Does it work better for you after the update?

For resetting, the syncState has a clearPersist function: https://legendapp.com/open-source/state/v3/sync/persist-sync/#syncstate. I'm also working on a way to clear all persistences globally, but it's not quite done yet.

The version parameter basically goes straight into indexedDB.open(databaseName, version). You'd change that version when you want to add or remove tableNames to make it change the database to have those tables.

warrenbhw commented 3 days ago

gotcha! I'll test persistence in the next few hrs.

One option I'd be interested in is simply blowing away any local data and recreating the local persistent store if the version number changes.

Operationally, this seems like the simplest and least-bug-prone way for me to start making my application local-first.