This is an example of how to use RxDB on the client and replicate with a Supabase server in realtime.
- Clone the whole RxDB-repo via
git clone https://github.com/pubkey/rxdb.git
- Build the RxDB base project
cd rxdb && npm install && npm run build
- Go into this folder
cd examples/supabase
- Fetch the supabase docker containers via
sh init-supabase.sh
. - Run supabase via
sh start-supabase.sh
(leave this terminal open) - Run
sh import-dump.sh
to import the default table that is used for this example.
- Fetch the supabase docker containers via
- Install the frontend libraries via
npm run preinstall && npm install
- Run the frontend via
npm run dev
- Open the supabase dashboard at http://localhost:3000/
- Open the frontend at http://localhost:8888/
For the replication, the RxDB replication protocol is used which allows a two-way, realtime replication with the supabase server.
To be compatible with the protocol, the pull- and push-handler have been implemented accordingly. Also a pull.stream$
is implemented with the supabase changestream.
The replication will pause when the user is disconnected from the server and it will automatically continue when the supabase server can be reached again. On reconnects a RESYNC
flat is emitted from the pull.stream$
so that the replication will switch into Checkpoint iteration mode to consider any change events that have been missed out during the online time.
See more at src/replication.ts.
Conflicts are resolved on the client side which makes it easier to have a plain, dumb supabase backend without any complex SQL statements.
To be able to detect and resolve conflicts, an additional field replicationRevision
is added to each document/row.
To ensure this field is updated on each write, we add the preInsert
, preRemove
, preSave
hooks when creating the database. These hooks automatically increase the revision height
and hash
. This works simliar to RxDB's internal revision handling.
In the conflictHandler we can compare the replicationRevision
of two documents to detect if there is a conflict. The current conflictHandler
drops the local state on conflict and uses the master/server state of the document. You can change the handler to project any additional logic like merging fields or cherry picking the new document state depending on some conditions.
- The
pull.stream$
currently only processes one document after another instead of processing change-bulks which would be much faster. But atm there is no way to tell supabase to fetch the changes in bulks. - The
push.handler
has abatchSize
of1
which makes the replication easier to implement. For better performance we could use a supabase rpc call instead.