diff --git a/lib/handlers/db-ops-handler.react.js b/lib/handlers/db-ops-handler.react.js --- a/lib/handlers/db-ops-handler.react.js +++ b/lib/handlers/db-ops-handler.react.js @@ -5,6 +5,7 @@ import { opsProcessingFinishedActionType } from '../actions/db-ops-actions.js'; import { usePeerToPeerCommunication } from '../tunnelbroker/peer-to-peer-context.js'; import { useConfirmPeerToPeerMessage } from '../tunnelbroker/use-confirm-peer-to-peer-message.js'; +import { databaseIdentifier } from '../types/database-identifier-types.js'; import type { DBOpsEntry } from '../types/db-ops-types.js'; import { getConfig } from '../utils/config.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; @@ -28,7 +29,7 @@ const { ops, dispatchMetadata, notificationsCreationData } = queueFront; void (async () => { if (ops) { - await processDBStoreOperations(ops); + await processDBStoreOperations(ops, databaseIdentifier.MAIN); if (ops.outboundP2PMessages && ops.outboundP2PMessages.length > 0) { const messageIDs = ops.outboundP2PMessages.map( message => message.messageID, diff --git a/lib/types/sqlite-types.js b/lib/types/sqlite-types.js --- a/lib/types/sqlite-types.js +++ b/lib/types/sqlite-types.js @@ -1,5 +1,6 @@ // @flow +import type { DatabaseIdentifier } from './database-identifier-types.js'; import type { IdentityAuthResult } from './identity-service-types.js'; import type { ClientDBMessageInfo } from './message-types.js'; import type { ClientStore, StoreOperations } from './store-ops-types.js'; @@ -87,7 +88,7 @@ +processDBStoreOperations: ( operations: StoreOperations, - userID?: ?string, + dbID: DatabaseIdentifier, ) => Promise, // backup diff --git a/lib/utils/migration-utils.js b/lib/utils/migration-utils.js --- a/lib/utils/migration-utils.js +++ b/lib/utils/migration-utils.js @@ -12,6 +12,7 @@ getPendingThreadID, draftKeySuffix, } from '../shared/thread-utils.js'; +import { databaseIdentifier } from '../types/database-identifier-types.js'; import type { ClientDBDraftInfo, ClientDBDraftStoreOperation, @@ -317,7 +318,10 @@ versionUpdateOp, ], }; - await getConfig().sqliteAPI.processDBStoreOperations(dbOps); + await getConfig().sqliteAPI.processDBStoreOperations( + dbOps, + databaseIdentifier.MAIN, + ); } } catch (exception) { if (handleException) { diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -76,8 +76,10 @@ virtual void processThreadStoreOperationsSync( jsi::Runtime &rt, jsi::Array operations) override; - virtual jsi::Value - processDBStoreOperations(jsi::Runtime &rt, jsi::Object operations) override; + virtual jsi::Value processDBStoreOperations( + jsi::Runtime &rt, + jsi::Object operations, + std::optional dbID) override; template void appendDBStoreOps( jsi::Runtime &rt, diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -317,9 +317,15 @@ jsi::Value CommCoreModule::processDBStoreOperations( jsi::Runtime &rt, - jsi::Object operations) { + jsi::Object operations, + std::optional dbID) { std::string createOperationsError; + DatabaseIdentifier identifier = DatabaseIdentifier::MAIN; + if (dbID.has_value()) { + identifier = stringToDatabaseIdentifier(dbID->utf8(rt)); + } + auto storeOpsPtr = std::make_shared>>(); try { @@ -453,7 +459,7 @@ try { DatabaseManager::getQueryExecutor().beginTransaction(); for (const auto &operation : *storeOpsPtr) { - operation->execute(DatabaseIdentifier::MAIN); + operation->execute(identifier); } if (messages.size() > 0) { DatabaseManager::getQueryExecutor().addOutboundP2PMessages( diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -37,7 +37,7 @@ return jsi::Value::undefined(); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processDBStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->processDBStoreOperations(rt, args[0].asObject(rt)); + return static_cast(&turboModule)->processDBStoreOperations(rt, args[0].asObject(rt), args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt))); } static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeCryptoAccount(rt); @@ -245,7 +245,7 @@ methodMap_["getAllThreadsSync"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getAllThreadsSync}; methodMap_["processReportStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperationsSync}; methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; - methodMap_["processDBStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processDBStoreOperations}; + methodMap_["processDBStoreOperations"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processDBStoreOperations}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; methodMap_["getOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getOneTimeKeys}; diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h --- a/native/cpp/CommonCpp/_generated/commJSI.h +++ b/native/cpp/CommonCpp/_generated/commJSI.h @@ -27,7 +27,7 @@ virtual jsi::Array getAllThreadsSync(jsi::Runtime &rt) = 0; virtual void processReportStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; - virtual jsi::Value processDBStoreOperations(jsi::Runtime &rt, jsi::Object operations) = 0; + virtual jsi::Value processDBStoreOperations(jsi::Runtime &rt, jsi::Object operations, std::optional dbID) = 0; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -169,13 +169,13 @@ return bridging::callFromJs( rt, &T::processThreadStoreOperationsSync, jsInvoker_, instance_, std::move(operations)); } - jsi::Value processDBStoreOperations(jsi::Runtime &rt, jsi::Object operations) override { + jsi::Value processDBStoreOperations(jsi::Runtime &rt, jsi::Object operations, std::optional dbID) override { static_assert( - bridging::getParameterCount(&T::processDBStoreOperations) == 2, - "Expected processDBStoreOperations(...) to have 2 parameters"); + bridging::getParameterCount(&T::processDBStoreOperations) == 3, + "Expected processDBStoreOperations(...) to have 3 parameters"); return bridging::callFromJs( - rt, &T::processDBStoreOperations, jsInvoker_, instance_, std::move(operations)); + rt, &T::processDBStoreOperations, jsInvoker_, instance_, std::move(operations), std::move(dbID)); } jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override { static_assert( diff --git a/native/database/sqlite-api.js b/native/database/sqlite-api.js --- a/native/database/sqlite-api.js +++ b/native/database/sqlite-api.js @@ -2,6 +2,7 @@ import { getKeyserversToRemoveFromNotifsStore } from 'lib/ops/keyserver-store-ops.js'; import { convertStoreOperationsToClientDBStoreOperations } from 'lib/shared/redux/client-db-utils.js'; +import type { DatabaseIdentifier } from 'lib/types/database-identifier-types'; import type { SQLiteAPI } from 'lib/types/sqlite-types.js'; import type { StoreOperations } from 'lib/types/store-ops-types'; import type { QRAuthBackupData } from 'lib/types/tunnelbroker/qr-code-auth-message-types.js'; @@ -33,6 +34,7 @@ async processDBStoreOperations( storeOperations: StoreOperations, + dbID: DatabaseIdentifier, ): Promise { const keyserversToRemoveFromNotifsStore = getKeyserversToRemoveFromNotifsStore( @@ -52,7 +54,7 @@ const dbOps = convertStoreOperationsToClientDBStoreOperations(storeOperations); if (values(dbOps).some(ops => ops && ops.length > 0)) { - promises.push(commCoreModule.processDBStoreOperations(dbOps)); + promises.push(commCoreModule.processDBStoreOperations(dbOps, dbID)); } await Promise.all(promises); } catch (e) { diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -49,7 +49,10 @@ +processThreadStoreOperationsSync: ( operations: $ReadOnlyArray, ) => void; - +processDBStoreOperations: (operations: Object) => Promise; + +processDBStoreOperations: ( + operations: Object, + dbID?: ?string, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getOneTimeKeys: (oneTimeKeysAmount: number) => Promise; @@ -250,6 +253,8 @@ +getSIWEBackupSecrets: () => Promise; +processDBStoreOperations: ( operations: ClientDBStoreOperations, + //This type should be DatabaseIdentifier + dbID?: ?string, ) => Promise; +getQRAuthBackupData: () => Promise; } diff --git a/web/database/sqlite-api.js b/web/database/sqlite-api.js --- a/web/database/sqlite-api.js +++ b/web/database/sqlite-api.js @@ -2,6 +2,7 @@ import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js'; import { convertStoreOperationsToClientDBStoreOperations } from 'lib/shared/redux/client-db-utils.js'; +import type { DatabaseIdentifier } from 'lib/types/database-identifier-types.js'; import type { IdentityAuthResult } from 'lib/types/identity-service-types.js'; import type { ClientDBMessageInfo } from 'lib/types/message-types.js'; import type { @@ -183,6 +184,7 @@ async processDBStoreOperations( storeOperations: StoreOperations, + dbID: DatabaseIdentifier, ): Promise { const dbOps = convertStoreOperationsToClientDBStoreOperations(storeOperations); @@ -200,6 +202,7 @@ await sharedWorker.schedule({ type: workerRequestMessageTypes.PROCESS_STORE_OPERATIONS, storeOperations: dbOps, + dbID, }); } catch (e) { console.log(e); diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js --- a/web/redux/initial-state-gate.js +++ b/web/redux/initial-state-gate.js @@ -11,6 +11,7 @@ import type { UserStoreOperation } from 'lib/ops/user-store-ops.js'; import { getMessageSearchStoreOps } from 'lib/reducers/db-ops-reducer.js'; import { allUpdatesCurrentAsOfSelector } from 'lib/selectors/keyserver-selectors.js'; +import { databaseIdentifier } from 'lib/types/database-identifier-types.js'; import type { RawThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { ClientStore } from 'lib/types/store-ops-types.js'; import { threadIDIsThick } from 'lib/types/thread-types.js'; @@ -207,21 +208,24 @@ messageStoreOperations, ); const { sqliteAPI } = getConfig(); - await sqliteAPI.processDBStoreOperations({ - threadStoreOperations, - draftStoreOperations: [], - messageStoreOperations, - reportStoreOperations: [], - userStoreOperations, - keyserverStoreOperations: [], - communityStoreOperations: [], - integrityStoreOperations: [], - syncedMetadataStoreOperations: [], - auxUserStoreOperations: [], - threadActivityStoreOperations: [], - entryStoreOperations, - messageSearchStoreOperations, - }); + await sqliteAPI.processDBStoreOperations( + { + threadStoreOperations, + draftStoreOperations: [], + messageStoreOperations, + reportStoreOperations: [], + userStoreOperations, + keyserverStoreOperations: [], + communityStoreOperations: [], + integrityStoreOperations: [], + syncedMetadataStoreOperations: [], + auxUserStoreOperations: [], + threadActivityStoreOperations: [], + entryStoreOperations, + messageSearchStoreOperations, + }, + databaseIdentifier.MAIN, + ); } dispatch({ diff --git a/web/shared-worker/worker/shared-worker.js b/web/shared-worker/worker/shared-worker.js --- a/web/shared-worker/worker/shared-worker.js +++ b/web/shared-worker/worker/shared-worker.js @@ -352,6 +352,21 @@ } else if ( message.type === workerRequestMessageTypes.PROCESS_STORE_OPERATIONS ) { + if (message.dbID && message.dbID === databaseIdentifier.RESTORED) { + const backupQueryExecutor = getSQLiteQueryExecutor( + databaseIdentifier.RESTORED, + ); + if (!backupQueryExecutor) { + throw new Error( + `Backup not initialized, unable to process request type: ${message.type}`, + ); + } + processDBStoreOperations( + backupQueryExecutor, + message.storeOperations, + dbModule, + ); + } processDBStoreOperations( sqliteQueryExecutor, message.storeOperations, diff --git a/web/types/worker-types.js b/web/types/worker-types.js --- a/web/types/worker-types.js +++ b/web/types/worker-types.js @@ -7,6 +7,7 @@ OLMIdentityKeys, OlmAPI, } from 'lib/types/crypto-types.js'; +import type { DatabaseIdentifier } from 'lib/types/database-identifier-types.js'; import type { PlatformDetails } from 'lib/types/device-types.js'; import type { IdentityServiceClient, @@ -102,6 +103,7 @@ export type ProcessStoreOperationsRequestMessage = { +type: 3, +storeOperations: ClientDBStoreOperations, + +dbID?: DatabaseIdentifier, }; export type GetClientStoreRequestMessage = {