Closed pantchox closed 2 years ago
You're running into this issue https://github.com/jakearchibald/idb#transaction-lifetime.
Copying from one database to another cannot be done in a single transaction as transactions must involve a single database.
Here's how I'd do what you're aiming for:
async function openSettingsDB() {
let needsKeyvalTransfer = false;
const db = await openDB('settings', 1, {
async upgrade(db, oldVersion, newVersion, transaction) {
if (oldVersion < 1) {
db.createObjectStore('channels');
needsKeyvalTransfer = true;
}
},
});
if (needsKeyvalTransfer) {
const keysToTransfer = ['foo', 'bar', 123];
const oldDb = await openDB('keyval-store');
const oldStore = db.transaction('keyval').store;
// Get values from the old DB
const toTransfer = new Map(
await Promise.all(
keysToTransfer.map(async (key) => {
return [key, await oldStore.get(key)];
})
)
);
// Add the values to the new DB in a single transaction
const tx = db.transaction('channels', 'readwrite');
for (const [key, val] of toTransfer) tx.store.put(value, key);
await tx.done;
}
return db;
}
Thanks for the quick reply! But in this part
if (needsKeyvalTransfer) {
const keysToTransfer = ['foo', 'bar', 123];
...
I don't know the keys from advanced and I need to query it.
so if I apply keysToTransfer
this:
const oldDb = await openDB('keyval-store');
const oldStore = db.transaction('keyval').store;
const keysToTransfer = await oldStore.getAllKeys();
keysToTransfer
returns empty array.
to test it is not empty of course I looked the the "application" tab on the dev tools and also I was able to query like on my original code to see it does have values (even though the error happens after as in my original code).
any idea why this happen?
I can't reproduce the issue. https://static-misc-3.glitch.me/idb-keyval-test/copy-keys.html
I suspect it's because you're written db.transaction('keyval')
where db
refers to the new database, rather than oldDb
.
If you run into more issues, please create a reduced reproduction of the issue for me to debug, so I don't need to create it myself.
That was a typo (copied originally from your first solution :) ) I did refer to `oldDb' in my code. eventually what I did this:
const oldDb = await openDB('keyval-store');
const keysToTransfer = await oldDb.getAllKeys('keyval');
// start a transaction part
const oldStore = oldDb.transaction('keyval').store;
const toTransfer = new Map(
await Promise.all(
keysToTransfer.map(async (key) => {
return [key, await oldStore.get(key)];
})
)
);
it has some kind of "duplication" in getting the oldDb old store, but it works and the DB is few lines so it works fine.
thanks for your support - much appreciated!
Hello, After using
idb-keyval
package I wanted to have multiple stores so I started using this library.Now in the upgrade function when opening the DB I would like to open the store created by the
idb-keyval
which iskeyval
and copy all the keys and values to my new database and store created byidb
package.here is my code
Running this causes an error
When calling
transacation.objectStore('channels').add
What am I missing? thanks!