Database readwrite transaction updates (#1932)

* Add _readWriteTransaction helper

* Improve deleteDictionary order

* Make onProgress event optional

* Simplify progress rate parameter
This commit is contained in:
toasted-nutbread 2021-09-05 20:00:08 -04:00 committed by GitHub
parent f68ad1f843
commit 97a80276f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 31 deletions

View File

@ -76,9 +76,7 @@ class Database {
return; return;
} }
const transaction = this.transaction([objectStoreName], 'readwrite'); const transaction = this._readWriteTransaction([objectStoreName], resolve, reject);
transaction.onerror = (e) => reject(e.target.error);
transaction.oncomplete = () => resolve();
const objectStore = transaction.objectStore(objectStoreName); const objectStore = transaction.objectStore(objectStoreName);
for (let i = start, ii = start + count; i < ii; ++i) { for (let i = start, ii = start + count; i < ii; ++i) {
objectStore.add(items[i]); objectStore.add(items[i]);
@ -161,9 +159,7 @@ class Database {
delete(objectStoreName, key) { delete(objectStoreName, key) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transaction = this.transaction([objectStoreName], 'readwrite'); const transaction = this._readWriteTransaction([objectStoreName], resolve, reject);
transaction.onerror = (e) => reject(e.target.error);
transaction.oncomplete = () => resolve();
const objectStore = transaction.objectStore(objectStoreName); const objectStore = transaction.objectStore(objectStoreName);
objectStore.delete(key); objectStore.delete(key);
transaction.commit(); transaction.commit();
@ -172,10 +168,7 @@ class Database {
bulkDelete(objectStoreName, indexName, query, filterKeys=null, onProgress=null) { bulkDelete(objectStoreName, indexName, query, filterKeys=null, onProgress=null) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transaction = this.transaction([objectStoreName], 'readwrite'); const transaction = this._readWriteTransaction([objectStoreName], resolve, reject);
transaction.onerror = (e) => reject(e.target.error);
transaction.oncomplete = () => resolve();
const objectStore = transaction.objectStore(objectStoreName); const objectStore = transaction.objectStore(objectStoreName);
const objectStoreOrIndex = indexName !== null ? objectStore.index(indexName) : objectStore; const objectStoreOrIndex = indexName !== null ? objectStore.index(indexName) : objectStore;
@ -317,4 +310,12 @@ class Database {
} }
} }
} }
_readWriteTransaction(storeNames, resolve, reject) {
const transaction = this.transaction(storeNames, 'readwrite');
transaction.onerror = (e) => reject(e.target.error);
transaction.onabort = () => reject(new Error('Transaction aborted'));
transaction.oncomplete = () => resolve();
return transaction;
}
} }

View File

@ -139,22 +139,37 @@ class DictionaryDatabase {
return result; return result;
} }
async deleteDictionary(dictionaryName, progressSettings, onProgress) { async deleteDictionary(dictionaryName, progressRate, onProgress) {
const targets = [ if (typeof progressRate !== 'number') {
['dictionaries', 'title'], progressRate = 1;
['kanji', 'dictionary'], }
['kanjiMeta', 'dictionary'], if (typeof onProgress !== 'function') {
['terms', 'dictionary'], onProgress = () => {};
['termMeta', 'dictionary'], }
['tagMeta', 'dictionary'],
['media', 'dictionary'] const targetGroups = [
[
['kanji', 'dictionary'],
['kanjiMeta', 'dictionary'],
['terms', 'dictionary'],
['termMeta', 'dictionary'],
['tagMeta', 'dictionary'],
['media', 'dictionary']
],
[
['dictionaries', 'title']
]
]; ];
const {rate} = progressSettings; let storeCount = 0;
for (const targets of targetGroups) {
storeCount += targets.length;
}
const progressData = { const progressData = {
count: 0, count: 0,
processed: 0, processed: 0,
storeCount: targets.length, storeCount,
storesProcesed: 0 storesProcesed: 0
}; };
@ -167,18 +182,20 @@ class DictionaryDatabase {
const onProgress2 = () => { const onProgress2 = () => {
const processed = progressData.processed + 1; const processed = progressData.processed + 1;
progressData.processed = processed; progressData.processed = processed;
if ((processed % rate) === 0 || processed === progressData.count) { if ((processed % progressRate) === 0 || processed === progressData.count) {
onProgress(progressData); onProgress(progressData);
} }
}; };
const promises = []; for (const targets of targetGroups) {
for (const [objectStoreName, indexName] of targets) { const promises = [];
const query = IDBKeyRange.only(dictionaryName); for (const [objectStoreName, indexName] of targets) {
const promise = this._db.bulkDelete(objectStoreName, indexName, query, filterKeys, onProgress2); const query = IDBKeyRange.only(dictionaryName);
promises.push(promise); const promise = this._db.bulkDelete(objectStoreName, indexName, query, filterKeys, onProgress2);
promises.push(promise);
}
await Promise.all(promises);
} }
await Promise.all(promises);
} }
findTermsBulk(termList, dictionaries, wildcard) { findTermsBulk(termList, dictionaries, wildcard) {

View File

@ -84,7 +84,7 @@ class DictionaryWorkerHandler {
async _deleteDictionary({dictionaryTitle}, onProgress) { async _deleteDictionary({dictionaryTitle}, onProgress) {
const dictionaryDatabase = await this._getPreparedDictionaryDatabase(); const dictionaryDatabase = await this._getPreparedDictionaryDatabase();
try { try {
return await dictionaryDatabase.deleteDictionary(dictionaryTitle, {rate: 1000}, onProgress); return await dictionaryDatabase.deleteDictionary(dictionaryTitle, 1000, onProgress);
} finally { } finally {
dictionaryDatabase.close(); dictionaryDatabase.close();
} }

View File

@ -122,7 +122,7 @@ async function testDatabase1() {
let progressEvent = false; let progressEvent = false;
await dictionaryDatabase.deleteDictionary( await dictionaryDatabase.deleteDictionary(
title, title,
{rate: 1000}, 1000,
() => { () => {
progressEvent = true; progressEvent = true;
} }
@ -788,7 +788,7 @@ async function testDatabase2() {
const dictionaryDatabase = new DictionaryDatabase(); const dictionaryDatabase = new DictionaryDatabase();
// Error: not prepared // Error: not prepared
await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, {rate: 1000}, () => {})); await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, 1000));
await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null)); await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null));
await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles)); await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles));
await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}])); await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}]));