diff --git a/lib/types/store-ops-types.js b/lib/types/store-ops-types.js index f86fc563e..d1897b0f9 100644 --- a/lib/types/store-ops-types.js +++ b/lib/types/store-ops-types.js @@ -1,67 +1,71 @@ // @flow import type { DraftStoreOperation, ClientDBDraftStoreOperation, ClientDBDraftInfo, } from './draft-types.js'; import type { ClientDBMessageInfo, ClientDBThreadMessageInfo, } from './message-types.js'; import type { ClientReportCreationRequest } from './report-types.js'; import type { ClientDBThreadInfo, ThreadStore } from './thread-types.js'; import type { UserInfos } from './user-types.js'; -import type { ClientDBKeyserverInfo } from '../ops/keyserver-store-ops.js'; +import type { + ClientDBKeyserverInfo, + ClientDBKeyserverStoreOperation, +} from '../ops/keyserver-store-ops.js'; import type { ClientDBMessageStoreOperation, MessageStoreOperation, } from '../ops/message-store-ops.js'; import type { ReportStoreOperation, ClientDBReport, ClientDBReportStoreOperation, } from '../ops/report-store-ops.js'; import type { ClientDBThreadStoreOperation, ThreadStoreOperation, } from '../ops/thread-store-ops.js'; import type { UserStoreOperation, ClientDBUserInfo, } from '../ops/user-store-ops.js'; export type StoreOperations = { +draftStoreOperations: $ReadOnlyArray, +threadStoreOperations: $ReadOnlyArray, +messageStoreOperations: $ReadOnlyArray, +reportStoreOperations: $ReadOnlyArray, +userStoreOperations: $ReadOnlyArray, }; export type ClientDBStoreOperations = { +draftStoreOperations?: $ReadOnlyArray, +threadStoreOperations?: $ReadOnlyArray, +messageStoreOperations?: $ReadOnlyArray, +reportStoreOperations?: $ReadOnlyArray, + +keyserverStoreOperations?: $ReadOnlyArray, }; export type ClientDBStore = { +messages: $ReadOnlyArray, +drafts: $ReadOnlyArray, +threads: $ReadOnlyArray, +messageStoreThreads: $ReadOnlyArray, +reports: $ReadOnlyArray, +users: $ReadOnlyArray, +keyservers: $ReadOnlyArray, }; export type ClientStore = { +currentUserID: ?string, +drafts: $ReadOnlyArray, +messages: ?$ReadOnlyArray, +threadStore: ?ThreadStore, +messageStoreThreads: ?$ReadOnlyArray, +reports: ?$ReadOnlyArray, +users: ?UserInfos, }; diff --git a/web/database/worker/process-operations.js b/web/database/worker/process-operations.js index 0992d17c5..bfd381628 100644 --- a/web/database/worker/process-operations.js +++ b/web/database/worker/process-operations.js @@ -1,180 +1,223 @@ // @flow +import type { ClientDBKeyserverStoreOperation } from 'lib/ops/keyserver-store-ops.js'; import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js'; import type { ClientDBDraftStoreOperation, DraftStoreOperation, } from 'lib/types/draft-types.js'; import type { ClientDBStore, ClientDBStoreOperations, } from 'lib/types/store-ops-types.js'; import { getMessageForException } from 'lib/utils/errors.js'; import { clientDBThreadInfoToWebThread, webThreadToClientDBThreadInfo, } from '../types/entities.js'; import type { EmscriptenModule } from '../types/module.js'; import type { SQLiteQueryExecutor } from '../types/sqlite-query-executor.js'; function getProcessingStoreOpsExceptionMessage( e: mixed, module: EmscriptenModule, ): string { if (typeof e === 'number') { return module.getExceptionMessage(e); } return getMessageForException(e) ?? 'unknown error'; } function processDraftStoreOperations( sqliteQueryExecutor: SQLiteQueryExecutor, operations: $ReadOnlyArray, module: EmscriptenModule, ) { for (const operation: DraftStoreOperation of operations) { try { if (operation.type === 'remove_all') { sqliteQueryExecutor.removeAllDrafts(); } else if (operation.type === 'remove') { const { ids } = operation.payload; sqliteQueryExecutor.removeDrafts(ids); } else if (operation.type === 'update') { const { key, text } = operation.payload; sqliteQueryExecutor.updateDraft(key, text); } else if (operation.type === 'move') { const { oldKey, newKey } = operation.payload; sqliteQueryExecutor.moveDraft(oldKey, newKey); } else { throw new Error('Unsupported draft operation'); } } catch (e) { throw new Error( `Error while processing ${ operation.type } draft operation: ${getProcessingStoreOpsExceptionMessage(e, module)}`, ); } } } function processReportStoreOperations( sqliteQueryExecutor: SQLiteQueryExecutor, operations: $ReadOnlyArray, module: EmscriptenModule, ) { for (const operation: ClientDBReportStoreOperation of operations) { try { if (operation.type === 'remove_all_reports') { sqliteQueryExecutor.removeAllReports(); } else if (operation.type === 'remove_reports') { const { ids } = operation.payload; sqliteQueryExecutor.removeReports(ids); } else if (operation.type === 'replace_report') { const { id, report } = operation.payload; sqliteQueryExecutor.replaceReport({ id, report }); } else { throw new Error('Unsupported report operation'); } } catch (e) { throw new Error( `Error while processing ${ operation.type } report operation: ${getProcessingStoreOpsExceptionMessage( e, module, )}`, ); } } } function processThreadStoreOperations( sqliteQueryExecutor: SQLiteQueryExecutor, operations: $ReadOnlyArray, module: EmscriptenModule, ) { for (const operation: ClientDBThreadStoreOperation of operations) { try { if (operation.type === 'remove_all') { sqliteQueryExecutor.removeAllThreads(); } else if (operation.type === 'remove') { const { ids } = operation.payload; sqliteQueryExecutor.removeThreads(ids); } else if (operation.type === 'replace') { sqliteQueryExecutor.replaceThreadWeb( clientDBThreadInfoToWebThread(operation.payload), ); } else { throw new Error('Unsupported thread operation'); } } catch (e) { throw new Error( `Error while processing ${ operation.type } thread operation: ${getProcessingStoreOpsExceptionMessage( e, module, )}`, ); } } } +function processKeyserverStoreOperations( + sqliteQueryExecutor: SQLiteQueryExecutor, + operations: $ReadOnlyArray, + module: EmscriptenModule, +) { + for (const operation: ClientDBKeyserverStoreOperation of operations) { + try { + if (operation.type === 'remove_all_keyservers') { + sqliteQueryExecutor.removeAllKeyservers(); + } else if (operation.type === 'remove_keyservers') { + const { ids } = operation.payload; + sqliteQueryExecutor.removeKeyservers(ids); + } else if (operation.type === 'replace_keyserver') { + const { id, keyserverInfo } = operation.payload; + sqliteQueryExecutor.replaceKeyserver({ id, keyserverInfo }); + } else { + throw new Error('Unsupported keyserver operation'); + } + } catch (e) { + throw new Error( + `Error while processing ${ + operation.type + } keyserver operation: ${getProcessingStoreOpsExceptionMessage( + e, + module, + )}`, + ); + } + } +} + function processDBStoreOperations( sqliteQueryExecutor: SQLiteQueryExecutor, storeOperations: ClientDBStoreOperations, module: EmscriptenModule, ) { - const { draftStoreOperations, reportStoreOperations, threadStoreOperations } = - storeOperations; + const { + draftStoreOperations, + reportStoreOperations, + threadStoreOperations, + keyserverStoreOperations, + } = storeOperations; try { sqliteQueryExecutor.beginTransaction(); if (draftStoreOperations && draftStoreOperations.length > 0) { processDraftStoreOperations( sqliteQueryExecutor, draftStoreOperations, module, ); } if (reportStoreOperations && reportStoreOperations.length > 0) { processReportStoreOperations( sqliteQueryExecutor, reportStoreOperations, module, ); } if (threadStoreOperations && threadStoreOperations.length > 0) { processThreadStoreOperations( sqliteQueryExecutor, threadStoreOperations, module, ); } + if (keyserverStoreOperations && keyserverStoreOperations.length > 0) { + processKeyserverStoreOperations( + sqliteQueryExecutor, + keyserverStoreOperations, + module, + ); + } sqliteQueryExecutor.commitTransaction(); } catch (e) { sqliteQueryExecutor.rollbackTransaction(); console.log('Error while processing store ops: ', e); throw e; } } function getClientStoreFromQueryExecutor( sqliteQueryExecutor: SQLiteQueryExecutor, ): ClientDBStore { return { drafts: sqliteQueryExecutor.getAllDrafts(), messages: [], threads: sqliteQueryExecutor .getAllThreadsWeb() .map(t => webThreadToClientDBThreadInfo(t)), messageStoreThreads: [], reports: sqliteQueryExecutor.getAllReports(), users: [], - keyservers: [], + keyservers: sqliteQueryExecutor.getAllKeyservers(), }; } export { processDBStoreOperations, getClientStoreFromQueryExecutor };