I had a working demo, but then I made a lot of changes in RxMoDB. Let me try to fix it a bit and walk you thru.
Start with a document setup like this https://github.com/infu/RxMoDb/blob/main/test/hero.mo
There is some documentation and tests to help you figure out how to set it up.
It has a Primary key (id) and Index (updatedAt + id)
Push
Haven’t tested the conflict resolution yet, but this should work. You will need to put doc.revision +=1 whenever you update @ frontend (Or you can put different conflict detection)
Pull
Frontend
This is the schema I’ve used.
const mySchema = {
title: "hero schema",
version: 0,
description: "describes a simple hero",
primaryKey: "id",
type: "object",
properties: {
id: {
type: "string",
maxLength: 100, // <- the primary key must have set maxLength
},
updatedAt: {
type: "number",
},
score: {
type: "number",
minimum: 0,
maximum: 100000,
multipleOf: 1,
},
name: {
type: "string",
maxLength: 100,
},
level: {
type: "number",
minimum: 1,
maximum: 80,
},
skills: {
type: "array",
maxItems: 5,
uniqueItems: true,
items: {
type: "string",
},
},
},
required: ["id", "updatedAt", "score", "name", "level", "skills"],
indexes: ["score"],
};
Init
import { createRxDatabase } from "rxdb";
import { getRxStorageDexie } from "rxdb/plugins/storage-dexie";
import { RxDBDevModePlugin } from "rxdb/plugins/dev-mode";
import { addRxPlugin } from "rxdb";
import { start_replication } from "./replication";
import { RxDBUpdatePlugin } from "rxdb/plugins/update";
import { RxDBQueryBuilderPlugin } from "rxdb/plugins/query-builder";
addRxPlugin(RxDBQueryBuilderPlugin);
addRxPlugin(RxDBUpdatePlugin);
addRxPlugin(RxDBDevModePlugin);
const db = await createRxDatabase({
name: "heroesdb",
storage: getRxStorageDexie(),
multiInstance: true,
eventReduce: true,
cleanupPolicy: {},
});
const myCollections = await db.addCollections({
humans: {
schema: mySchema,
},
});
await start_replication(myCollections.humans);
replication.js | https://rxdb.info/replication.html
import { replicateRxCollection } from "rxdb/plugins/replication";
import { lastOfArray } from "rxdb";
import { Subject } from "rxjs";
import icblast, { toState } from "@infu/icblast";
let ic = icblast({ local: "true", local_host: "http://localhost:8080" });
export const start_replication = async (myRxCollection) => {
const pullStream$ = new Subject();
const replicationState = await replicateRxCollection({
collection: myRxCollection,
replicationIdentifier: "anything",
retryTime: 5 * 1000,
waitForLeadership: true,
autoStart: true,
deletedField: "deleted",
push: {
async handler(docs) {
let store = [];
for (let { assumedMasterState, newDocumentState } of docs) {
store.push(newDocumentState);
}
let can = await ic("rrkah-fqaaa-aaaaa-aaaaq-cai");
return await can.push(store);
},
batchSize: 100,
modifier: (d) => d,
},
pull: {
async handler(lastCheckpoint, batchSize) {
const minTimestamp = lastCheckpoint ? lastCheckpoint.updatedAt : 0;
const lastId = lastCheckpoint ? lastCheckpoint.id : null;
let can = await ic("rrkah-fqaaa-aaaaa-aaaaq-cai");
let rez = await can
.pull(minTimestamp, lastId || undefined, batchSize)
.catch((e) => console.log(e));
const documentsFromRemote = toState(rez);
return {
documents: documentsFromRemote,
checkpoint:
documentsFromRemote.length === 0
? lastCheckpoint
: {
id: lastOfArray(documentsFromRemote).id,
updatedAt: lastOfArray(documentsFromRemote).updatedAt,
},
};
},
batchSize: 1000,
modifier: (d) => d,
},
});
};
Then you can use all RxDB functions and the DB will get synced with the IC backend.