Handle indexedDB versioning

Viewed 33

I have a page that contains data based on which ID is receiving, for some business logic I need to store those values into an indexDB.

This is my code from loadData page

await createIndexDB(querystringID);

And this is what I use to create the indexDB:

const createIndexDB= async (ID) => {
    return new Promise(function (resolve, reject) {
        let isTrueInit = false;

        var dbReq = indexedDB.open('myindexDB', 1);

        dbReq.onerror = (e) => {
            myDB = dbReq.result
            myDB.close()
            reject({
                status: 'error',
                message: dbReq.error,
            })
        }

        dbReq.onsuccess = (event) => {
            const storeName = 'myindexDB' + ID;
            myDB = dbReq.result
            if (!myDB.objectStoreNames.contains(storeName)) {
                myDB.close()
                isTrueInit = true
                reject({
                    status: 'upgradeneeded',
                    message: "Store doesn't exist",
                    upgradeNeeded: true,
                    version: dbReq.result.version,
                    isTrueInit,
                })
            } else {
                myDB.onversionchange = (e) => {
                    // Close immediately to allow the upgrade requested by another
                    // instance to proceed.
                    myDB.close()
                }
                resolve({
                    db: myDB,
                    isTrueInit,
                })
            }
        }

        dbReq.onupgradeneeded = () => {
            const storeName = 'myindexDB' + ID;
            myDB = dbReq.result;
            if (!myDB.objectStoreNames.contains(storeName)) isTrueInit = true
            myDB.createObjectStore(storeName, { keyPath: 'itemid', autoIncrement: true })
        }

    });
}

Then, on the loadData page I execute some function to retrieve, set and delete items from the indexDB, to do that I use something like this:

await getAllIndexDBItem(querystringID);

const getAllIndexDBItem = async (ID) => {
    return new Promise(function (resolve, reject) {
        var myDB = null;
        var dbReq = indexedDB.open('myindexDB', 1);

        dbReq.onsuccess = function (e) {
            myDB= dbReq.result;
            const transaction = myDB.transaction(['myindexDB' + ID], 'readonly');
            const store = transaction.objectStore('myindexDB' + ID);

            let request = store.getAll();

            request.onsuccess = event => {
                const result = request ? request.result : null;
                resolve(result);
            };

            transaction.onerror = event => {
                console.log('error getting element from myindexDB' + event.target.error);
                reject('error getting element from myindexDB ' + event.target.error);
            };

            transaction.oncomplete = event => {

            };
        }
    });
}

Everything it's working with the first ID that I sent to loadData page, creates the indexDB and the object, but when I sent another ID to loadData page I get the upgradeneeded error message. If I change this:

var dbReq = indexedDB.open('myindexDB', 1);

To:

var dbReq = indexedDB.open('myindexDB', 2);

Now it works okay with the two different IDs. So my question is, what can I do to handle the indexDB versioning properly instead of changing manually the version? Taking into consideration that sometimes the indexDB will not exists yet.

1 Answers

The short but unhelpful answer is "you're doing it wrong". You should only change the schema (add/delete object stores) when your code and hence your logic requirements for the database are changing.

Rather than thinking about separate object stores per ID, a more typical approach is to include the ID in the store's keys. For example, use [ID, other_key] as the key structure in your stores - a compound key with the ID you are partitioning by, and whatever other key(s) you were planning to use.

Another option would be to use an entirely different database per ID, with a unique name per database. Each such database would be an identical schema. e.g. make the open call open('myDB-' + ID), and use the same store name in each database.

Related