Indeed, schema migration is challenging. There is a lot to explore, both in reducing the need for migration and in ensuring a smooth transition when it's required. We plan to tackle this issue in the future.
Agreed on migrations!
Any tips or dos/don'ts you could share for how to "get it right" at the beginning? I'm hoping to build an application using CRDTs sometime in the future.
You should try to brainstorm a lot of future feature improvements and ideas you might want in 2 years and consider if your v1 design would block or need a challenging migration to support the hypothetical v100 designing. A classic example is if you need a one-to-one relationship in v1, think about how you’d support that as a one-to-many or many-to-many. It might be better to start with a schema that supports many-to-many to avoid shenanigans down the line.
I linked the Cambria essay below which has a lot of food for thought.
Ink & Switch Upwelling [0] goes into that direction. A must-watch is the StrangeLoop 2023 talk by Martin Kleppmann "New Algorithms for Collaborative Editing" [1] that excellently explains things.
I think the roadmap says that WASM is next as a target, and that makes sense for prioritization. Would you also consider Flutter/Dart as a target, even if at the level of "we checked once that flutter_rust_bridge can call Loro"?
Can this even be reconciliated?
Or is it append only?i.e. No delete operation.
UIs have delete operations in general.
A: delete Line 4@marker
B: append to the end of line 4@marker "abcd"
could then result in either line 4 with only "abcd", or "abcd" at the beginning of line 5 (as long as both sides resolve to the same state).
You're right in that this is tricky to get right, as that is inherent to the complexity of asynchonous mutation from multiple sources.What is the source of truth eventually?
I think there must probably be a hierarchy that decides it. It's probably a kind of race condition/byzantine general problem.
I wonder if this is something that can be used for versioning database columns / fields.
I like the completeness of the Loro solution: the state, the rich text, the tree. Local-first database approach sounds like a great idea. Wondering how large is the code size overhead for using this though.
Couple of questions:
- How big is the WASM blob that you need to ship for in-browser SQLite? Have you had any noticable issues from shipping a large payload to the browser?
- What are you using to persist the SQLite database on clients? Have you been using the Origin Private File System?
We're using IndexedDB. Here's a writeup on alternatives https://github.com/rhashimoto/wa-sqlite/issues/85 and a benchmark https://rhashimoto.github.io/wa-sqlite/demo/benchmarks.html
The corruption was also caught by sqlite itself - it threw a "malformed disk image" error and stopped responding to any further queries.
Also bugs around syncing some kinds of data - one bug that's already been fixed was that floats without decimal points would not get synced. https://github.com/electric-sql/electric/issues/506
In general electric's team is very responsive and fixes bugs when we bring them up.
These “update objects” can be combined to get the current document state.
They have the property that if two programs receive the same set of uodate objects, regardless of the order they get them in, then they have the same current document state.
They define any state resulting from applying the operations as “legit.” In order for that to feel “legit” to the users you want to very carefully choose your operations and their semantics.
That writeup on different SQLite VFS's for in-browser use is helpful, thanks for linking that.
[1] - https://github.com/vlcn-io/js/issues/31#issuecomment-1785296...
And if you’re really peer to peer, you’ll need older peers that don’t understand a new format in their user space software to avoid applying updates that break compatibility for them.
Geoffrey Litt documents the challenges in Cambria, see https://www.inkandswitch.com/cambria/
I think the primary issue you raise comes down to whether or not the peers can be verified to be updated before applying the migration op. If this is the case, you can go the standard sql route of deploying a diff adding forward compatibility, applying migration op, deploying diff removing backward compatibility. This is the route I’ve gone since in my case the peers are web browsers so I’ve got a pretty reliable deployment system; though the lens solution is much better since it lifts this requirement