Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue initialising rxdb with seed data #5885

Open
iamsmkr opened this issue Apr 10, 2024 · 3 comments
Open

Issue initialising rxdb with seed data #5885

iamsmkr opened this issue Apr 10, 2024 · 3 comments

Comments

@iamsmkr
Copy link

iamsmkr commented Apr 10, 2024

I am trying to initialise the rxdb database with a seed data if not already found in the database.

image

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

  1. Start fresh with no collection in pouchdb server
  2. 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.
image
  1. 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!

@pubkey
Copy link
Owner

pubkey commented Apr 10, 2024

I think you are using it correctly and you found a bug. Please make a PR with a test case to reproduce the problem.

@iamsmkr
Copy link
Author

iamsmkr commented Apr 21, 2024

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) { }
        })
    );

Copy link

stale bot commented Apr 29, 2024

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.

@stale stale bot added the stale label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants