Issue initialising rxdb with seed data
I am trying to initialise the rxdb database with a seed data if not already found in the database.
Create Database This is pretty much straight out of documentation besides initialising the database with seed data.
import { createRxDatabase, addRxPlugin } from 'rxdb';
import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie';
import { RxDBLeaderElectionPlugin } from 'rxdb/plugins/leader-election';
import { replicateCouchDB } from 'rxdb/plugins/replication-couchdb';
import { activityLogsSchema, contributionGraphSchema } from './Schema';
addRxPlugin(RxDBLeaderElectionPlugin);
const syncURL = 'http://' + window.location.hostname + ':10102/';
console.log('host: ' + syncURL);
let dbPromise = null;
const _create = async () => {
if (process.env.NODE_ENV === "development") {
await import('rxdb/plugins/dev-mode').then(
module => addRxPlugin(module.RxDBDevModePlugin)
);
}
console.log('DatabaseService: creating database..');
const db = await createRxDatabase({
name: 'visibilitydb',
storage: getRxStorageDexie()
});
console.log('DatabaseService: created database');
window['db'] = db; // write to window for debugging
// Show leadership in title
db.waitForLeadership().then(() => {
console.log('isLeader now');
document.title = '♛ ' + document.title;
});
// Create collections
console.log('DatabaseService: create collections');
await db.addCollections({
activity_logs: {
schema: activityLogsSchema,
methods: {
hpPercent() {
return this.hp / this.maxHP * 100;
}
}
},
contribution_graph: {
schema: contributionGraphSchema,
methods: {
hpPercent() {
return this.hp / this.maxHP * 100;
}
}
}
});
// Init contribution graphs
// The database is initialised when the app is loaded for the first time.
const graphCollection = db.contribution_graph;
const graphDocuments = await graphCollection.find().exec();
if (graphDocuments.length == 0) {
await graphCollection.bulkInsert([
{ index: 1, activity: 'Study', streaks: [] },
{ index: 2, activity: 'Gym', streaks: [] },
]);
};
// Sync
console.log('DatabaseService: sync');
await Promise.all(
Object.values(db.collections).map(async (col) => {
try {
// create the CouchDB database
await fetch(
syncURL + col.name + '/',
{
method: 'PUT'
}
);
} catch (err) { }
})
);
console.log('DatabaseService: sync - start live');
Object.values(db.collections).map(col => col.name).map(colName => {
const url = syncURL + colName + '/';
console.log('url: ' + url);
const replicationState = replicateCouchDB({
collection: db[colName],
url,
live: true,
pull: {},
push: {},
autoStart: true
});
replicationState.error$.subscribe(err => {
console.error('Got replication error:');
console.dir(err);
});
});
return db;
};
export const get = () => {
if (!dbPromise)
dbPromise = _create();
return dbPromise;
};
Problem Statement When I try to start the app fresh i.e., when there is no collection in the database it all works just fine. The documents are created in the local storage and then replicated to the pouch db server. But it becomes issue if there are collections/documents already in the pouchdb server.
Steps To Reproduce
-
Start fresh with no collection in pouchdb server
-
Clear local storage in the app browser. This step allows to check the behaviour when the app is launched in a browser for the first time.
-
Refresh app page gives error:
RxError (RC_PUSH): RxError (RC_PUSH):
RxReplication push handler threw an error - see .errors for more details
Given parameters: {
pushRows:[
{
"assumedMasterState": null,
"newDocumentState": {
"index": 0,
"activity": "2024",
"streaks": [],
"_deleted": false
}
},
{
"assumedMasterState": null,
"newDocumentState": {
"index": 1,
"activity": "Study",
"streaks": [],
"_deleted": false
}
},
{
"assumedMasterState": null,
"newDocumentState": {
"index": 2,
"activity": "Gym",
"streaks": [],
"_deleted": false
}
},
{
"assumedMasterState": null,
"newDocumentState": {
"index": 3,
"activity": "Reading",
"streaks": [],
"_deleted": false
}
},
{
"assumedMasterState": null,
"newDocumentState": {
"index": 4,
"activity": "Meditation",
"streaks": [],
"_deleted": false
}
},
{
"assumedMasterState": null,
"newDocumentState": {
"index": 5,
"activity": "Fasting",
"streaks": [],
"_deleted": false
}
}
]
errors:{"name":"TypeError","message":"Cannot read properties of undefined (reading '_attachments')","stack":"TypeError: Cannot read properties of undefined (reading '_attachments') \n at stripAttachmentsDataFromDocument (http://localhost:3000/static/js/bundle.js:127410:12) \n at defaultConflictHandler (http://localhost:3000/static/js/bundle.js:121797:113) \n at http://localhost:3000/static/js/bundle.js:118401:45 \n at Array.map (<anonymous>) \n at Object.handler (http://localhost:3000/static/js/bundle.js:118394:45) \n at async Object.masterWrite (http://localhost:3000/static/js/bundle.js:118764:24) \n at async http://localhost:3000/static/js/bundle.js:122939:33 \n at async Promise.all (index 0) \n at async http://localhost:3000/static/js/bundle.js:122932:7"}
direction:"push"}
at newRxError (http://localhost:3000/static/js/bundle.js:125434:10)
at Object.masterWrite (http://localhost:3000/static/js/bundle.js:118782:105)
at async http://localhost:3000/static/js/bundle.js:122939:33
at async Promise.all (index 0)
at async http://localhost:3000/static/js/bundle.js:122932:7
The issue seems to be that rxdb local storage is getting initialised before it is synced with the pouchdb server!
How do we initialise the db instance?? Please suggest!
I think you are using it correctly and you found a bug. Please make a PR with a test case to reproduce the problem.
Found a work around for now!
The idea is to initialize the collection only if database creation on the couchdb instance passes. If it fails, that would mean the database was already created and already initialize.
console.log('DatabaseService: sync');
await Promise.all(
Object.values(db.collections).map(async (col) => {
try {
// create the CouchDB database
await fetch(
syncURL + col.name + '/',
{
method: 'PUT'
}
).then(response => {
if (!response.ok) {
throw new Error(`Failed to create database: ${response.status}`);
}
});
// Init contribution graphs
if (col.name === 'contribution_graph') {
const graphCollection = db.contribution_graph;
const graphDocuments = await graphCollection.find().exec();
if (graphDocuments.length == 0) {
await graphCollection.bulkInsert([
{ index: 1, activity: 'Study', streaks: [] },
{ index: 2, activity: 'Gym', streaks: [] },
]);
};
}
} catch (err) { }
})
);
This issue has been automatically marked as stale because it has not had recent activity. It will be closed soon. If you still have a problem, make a PR with a test case or to prove that you have tried to fix the problem. Notice that only bugs in the rxdb premium plugins are ensured to be fixed by the maintainer. Everything else is expected to be fixed by the community, likely you must fix it by yourself.
Issues are autoclosed after some time. If you still have a problem, make a PR with a test case or to prove that you have tried to fix the problem.