Open NekodRider opened 1 month ago
The retry
option in syncedSupabase
should enable that to happen automatically. And the retrySync
option enables persisting the changes and retrying after reload: https://legendapp.com/open-source/state/v3/sync/persist-sync/#synced
It does not currently check network connection though, so it just keeps retrying and failing until it eventually works. I'm planning to change that soon so it stops retrying while offline and starts again when coming back online. But at least it works :)
I keep retry
to {infinite: true}
and retrySync
to true
all the time, but I think they are intended for retrying to save local changes to remote, not fetching?
In my case, only remote data changes during the app offline. When the app gets back online, the realtime reconnects instantly. However it won't actively check if it missed some updates, it just assumes there is no remote update during the offline period. Supabase realtime also doesn't guarantee that it knows it missed some broadcasts.
I understand that implementing network check for the legend-state takes time, so I'm trying to do a manual refresh myself. Right now I've found syncState(obs).reset()
works for the purpose. I think it only resets the state to initial and clears persistence, then others do the sync. So is there a way to trigger a complete refresh without resetting the state? Just fetch all the remote data and replace the local data.
BTW, I'm curious why reset()
works well but when I replace it with clearPersist()
, it still gives undefined
.
What version are you using? I'm testing it and in the latest alpha.41 I'm seeing that when coming back online, realtime reconnects instantly and updates with all the changes. And also, calling syncState(obs).sync()
updates as expected.
retrySync
is for retrying saving, but retry
is for everything so it should retry selects as well.
Maybe an update to the supabase js library might improve things too? If not can you share some of your code, or ideally a sandbox I could test?
I just updated from 39 to 42 and syncState(obs).sync()
works great now. Thanks!
I think realtime does miss update during offline, I'll create a sandbox repo and come back later.
I was building a simple repo until I saw your blog on expo. So I just borrowed it for test and the problem did exist.
To reproduce it, first add some todo items, then go offline and delete some items in database. When the app gets back online, the deleted items are still there. If it's soft delete, the app could bring it back to database when we toggle it, since it will also update the deleted field. But for hard delete it will stay there forever unless we do the reset
.
Btw, I tried to implement delete todo for that repo, but soft delete seems to have some problems when all items are deleted? Although I am also using Object.values()
with some filter(undefined
key) to access the obs, I hope there would be a helper function to get the key array instead.
I'm getting the same issue with deleting. Lots of empty todos popping up, it's extremely buggy at the moment.
Can you share your repo so I can test it?
Are you using changesSince: 'lastSync'? That requires soft deletes. If not then I would think that Supabase's realtime would reconnect and see the deletes. Or is it not?
@jmeistrich Sure thing. Yes, I'm using soft deletes with changesSince: 'lastSync'
. I've created a minimal reproduction based on the Supabase example from your recent blog post.
I've stuck as close as possible to the example. You can see my changes in this commit. Perhaps I'm doing something very stupid but I can't figure it out.
Steps to reproduce:
You'll see a new empty todo pop up like in @NekodRider's screenshot.
If you add a few todos, mark them as done, then click "clear completed todos" at the bottom, it starts to get pretty wacky (also try refreshing, etc).
I've also tried:
export function deleteTodo(id: string) {
// todos$[id].delete();
todos$[id].deleted.set(true);
}
But that doesn't cause a re-render and you only see the change after a hard refresh. The other weird behavior remains the same.
Also, if I set my phone to Airplane Mode, add a todo on my Mac, then go back online with my phone, it will often not pick up on the new todo.
Thanks, I repro'd it and I'm working on it.
This should be fixed in beta.7. There were a couple bugs:
Is it working better for you now?
@jmeistrich Looks like this resolves the issue with the empty todos, thanks! Soft deleting works smoothly now.
I'm still seeing the issue where mobile (iOS native in Expo Go) doesn't pick up on new todos after being offline (same repo). Is there something I can do here?
Hmm ok I'll check that tomorrow. I'd been testing on expo web.
I think that may be a Supabase bug. If I add this logging to SupaLegend.ts I sometimes see a status of CHANNEL_ERROR
with error undefined
.
supabase
.channel(`LS_TEST`)
.on(
'postgres_changes',
{
event: '*',
table: 'todos',
schema: 'public',
},
(payload) => {
console.log('1payload', payload);
},
)
.subscribe((status, error) => {
console.log('1status', status);
console.log('1error', error);
});
I'm not sure what causes it but I seem to have a pattern that reproduces it:
Can you try adding that in yours and see what happens for you?
@jmeistrich Yeah, I'm seeing a lot of this error when I reconnect:
1status CHANNEL_ERROR
1error undefined
1status CHANNEL_ERROR
1error undefined
1status CHANNEL_ERROR
1error undefined
1status CHANNEL_ERROR
1error undefined
etc…
I'm working on an offline feature for my app using the Supabase plugin with persist and realtime.
When the app goes offline for a period and then reconnects, it can receive realtime broadcasts after back online, but any updates that occurred during the offline period are lost. So there will be inconsistent records until they are updated again and broadcast by realtime.
I think Legend doesn't check network connection so I have to manually refresh data after back online. But I've been unable to find a reliable method to manually sync data from Supabase(similar to an initial load). I've tried using
syncState(Contacts$).sync()
withisLoaded
, but as mentioned in other issues, it doesn't work and I think it's possible related tosyncState
.