Move util database modification functions (#499)

* Update onProgress callback to handle multiple arguments

* Add apiImportDictionaryArchive

* Add apiDeleteDictionary

* Make onProgress the last argument for consistency

* Remove deprecated util functions

* Fix issue with missing progress args

* Remove function calls which modify the database from Translator

* Update tests

* Fix errors not being serialized correctly in _createActionListenerPort
This commit is contained in:
toasted-nutbread 2020-05-06 19:28:26 -04:00 committed by GitHub
parent 501281e887
commit 021ccb5ac3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 52 deletions

View File

@ -117,7 +117,10 @@ class Backend {
['logIndicatorClear', {handler: this._onApiLogIndicatorClear.bind(this), async: false}],
['createActionPort', {handler: this._onApiCreateActionPort.bind(this), async: false}]
]);
this._messageHandlersWithProgress = new Map();
this._messageHandlersWithProgress = new Map([
['importDictionaryArchive', {handler: this._onApiImportDictionaryArchive.bind(this), async: true}],
['deleteDictionary', {handler: this._onApiDeleteDictionary.bind(this), async: true}]
]);
this._commandHandlers = new Map([
['search', this._onCommandSearch.bind(this)],
@ -771,7 +774,8 @@ class Backend {
async _onApiPurgeDatabase(params, sender) {
this._validatePrivilegedMessageSender(sender);
return await this.translator.purgeDatabase();
this.translator.clearDatabaseCaches();
await this.database.purge();
}
async _onApiGetMedia({targets}) {
@ -814,12 +818,23 @@ class Backend {
return portName;
}
async _onApiImportDictionaryArchive({archiveContent, details}, sender, onProgress) {
this._validatePrivilegedMessageSender(sender);
return await this.dictionaryImporter.import(this.database, archiveContent, details, onProgress);
}
async _onApiDeleteDictionary({dictionaryName}, sender, onProgress) {
this._validatePrivilegedMessageSender(sender);
this.translator.clearDatabaseCaches();
await this.database.deleteDictionary(dictionaryName, {rate: 1000}, onProgress);
}
// Command handlers
_createActionListenerPort(port, sender, handlers) {
let hasStarted = false;
const onProgress = (data) => {
const onProgress = (...data) => {
try {
if (port === null) { return; }
port.postMessage({type: 'progress', data});
@ -847,7 +862,7 @@ class Backend {
port.postMessage({type: 'complete', data: result});
} catch (e) {
if (port !== null) {
port.postMessage({type: 'error', data: e});
port.postMessage({type: 'error', data: errorToJson(e)});
}
cleanup();
}

View File

@ -129,7 +129,7 @@ class Database {
await this.prepare();
}
async deleteDictionary(dictionaryName, onProgress, progressSettings) {
async deleteDictionary(dictionaryName, progressSettings, onProgress) {
this._validate();
const targets = [

View File

@ -27,7 +27,7 @@ class DictionaryImporter {
this._schemas = new Map();
}
async import(database, archiveSource, onProgress, details) {
async import(database, archiveSource, details, onProgress) {
if (!database) {
throw new Error('Invalid database');
}

View File

@ -17,8 +17,10 @@
/* global
* PageExitPrevention
* apiDeleteDictionary
* apiGetDictionaryCounts
* apiGetDictionaryInfo
* apiImportDictionaryArchive
* apiOptionsGet
* apiOptionsGetFull
* apiPurgeDatabase
@ -29,8 +31,6 @@
* storageEstimate
* storageUpdateStats
* utilBackgroundIsolate
* utilDatabaseDeleteDictionary
* utilDatabaseImport
*/
let dictionaryUI = null;
@ -312,7 +312,7 @@ class SettingsDictionaryEntryUI {
progressBar.style.width = `${percent}%`;
};
await utilDatabaseDeleteDictionary(this.dictionaryInfo.title, onProgress, {rate: 1000});
await apiDeleteDictionary(this.dictionaryInfo.title, onProgress);
} catch (e) {
dictionaryErrorsShow([e]);
} finally {
@ -679,7 +679,8 @@ async function onDictionaryImport(e) {
dictImportInfo.textContent = `(${i + 1} of ${ii})`;
}
const {result, errors} = await utilDatabaseImport(files[i], updateProgress, importDetails);
const archiveContent = await dictReadFile(files[i]);
const {result, errors} = await apiImportDictionaryArchive(archiveContent, importDetails, updateProgress);
for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) {
const dictionaryOptions = SettingsDictionaryListUI.createDictionaryOptions();
dictionaryOptions.enabled = true;
@ -713,6 +714,15 @@ async function onDictionaryImport(e) {
}
}
function dictReadFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsBinaryString(file);
});
}
async function onDatabaseEnablePrefixWildcardSearchesChanged(e) {
const optionsFull = await getOptionsFullMutable();

View File

@ -45,14 +45,8 @@ class Translator {
this.deinflector = new Deinflector(reasons);
}
async purgeDatabase() {
clearDatabaseCaches() {
this.tagCache.clear();
await this.database.purge();
}
async deleteDictionary(dictionaryName) {
this.tagCache.clear();
await this.database.deleteDictionary(dictionaryName);
}
async getSequencedDefinitions(definitions, mainDictionary) {

View File

@ -66,31 +66,6 @@ function utilBackend() {
return backend;
}
async function utilDatabaseDeleteDictionary(dictionaryName, onProgress) {
return utilIsolate(await utilBackend().translator.database.deleteDictionary(
utilBackgroundIsolate(dictionaryName),
utilBackgroundFunctionIsolate(onProgress)
));
}
async function utilDatabaseImport(data, onProgress, details) {
data = await utilReadFile(data);
return utilIsolate(await utilBackend().importDictionary(
utilBackgroundIsolate(data),
utilBackgroundFunctionIsolate(onProgress),
utilBackgroundIsolate(details)
));
}
function utilReadFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsBinaryString(file);
});
}
function utilReadFileArrayBuffer(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();

View File

@ -152,6 +152,14 @@ function apiLogIndicatorClear() {
return _apiInvoke('logIndicatorClear');
}
function apiImportDictionaryArchive(archiveContent, details, onProgress) {
return _apiInvokeWithProgress('importDictionaryArchive', {archiveContent, details}, onProgress);
}
function apiDeleteDictionary(dictionaryName, onProgress) {
return _apiInvokeWithProgress('deleteDictionary', {dictionaryName}, onProgress);
}
function _apiCreateActionPort(timeout=5000) {
return new Promise((resolve, reject) => {
let timer = null;
@ -213,7 +221,7 @@ function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) {
break;
case 'progress':
try {
onProgress(message.data);
onProgress(...message.data);
} catch (e) {
// NOP
}

View File

@ -233,10 +233,10 @@ async function testDatabase1() {
let progressEvent = false;
await database.deleteDictionary(
title,
{rate: 1000},
() => {
progressEvent = true;
},
{rate: 1000}
}
);
assert.ok(progressEvent);
@ -267,10 +267,10 @@ async function testDatabase1() {
const {result, errors} = await dictionaryImporter.import(
database,
testDictionarySource,
{prefixWildcardsSupported: true},
() => {
progressEvent = true;
},
{prefixWildcardsSupported: true}
}
);
vm.assert.deepStrictEqual(errors, []);
vm.assert.deepStrictEqual(result, expectedSummary);
@ -908,7 +908,7 @@ async function testDatabase2() {
// Error: not prepared
await assert.rejects(async () => await database.purge());
await assert.rejects(async () => await database.deleteDictionary(title, () => {}, {}));
await assert.rejects(async () => await database.deleteDictionary(title, {}, () => {}));
await assert.rejects(async () => await database.findTermsBulk(['?'], titles, null));
await assert.rejects(async () => await database.findTermsExactBulk(['?'], ['?'], titles));
await assert.rejects(async () => await database.findTermsBySequenceBulk([1], title));
@ -919,17 +919,17 @@ async function testDatabase2() {
await assert.rejects(async () => await database.findTagForTitle('tag', title));
await assert.rejects(async () => await database.getDictionaryInfo());
await assert.rejects(async () => await database.getDictionaryCounts(titles, true));
await assert.rejects(async () => await dictionaryImporter.import(database, testDictionarySource, () => {}, {}));
await assert.rejects(async () => await dictionaryImporter.import(database, testDictionarySource, {}, () => {}));
await database.prepare();
// Error: already prepared
await assert.rejects(async () => await database.prepare());
await dictionaryImporter.import(database, testDictionarySource, () => {}, {});
await dictionaryImporter.import(database, testDictionarySource, {}, () => {});
// Error: dictionary already imported
await assert.rejects(async () => await dictionaryImporter.import(database, testDictionarySource, () => {}, {}));
await assert.rejects(async () => await dictionaryImporter.import(database, testDictionarySource, {}, () => {}));
await database.close();
}
@ -956,7 +956,7 @@ async function testDatabase3() {
let error = null;
try {
await dictionaryImporter.import(database, testDictionarySource, () => {}, {});
await dictionaryImporter.import(database, testDictionarySource, {}, () => {});
} catch (e) {
error = e;
}