diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -1806,7 +1806,7 @@ std::string logID = this->getMetadata("logID"); if (!logID.size()) { - logID = "0"; + logID = "1"; } bool newLogCreated = SQLiteQueryExecutor::connectionManager.captureLogs( diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h --- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.h @@ -11,6 +11,8 @@ std::string mainCompactionPath, std::string mainCompactionEncryptionKey, size_t futureID); - static void restoreFromBackupLog(const std::vector &backupLog); + static void restoreFromBackupLog( + const std::vector &backupLog, + size_t futureID); }; } // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp --- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp @@ -43,15 +43,16 @@ } void BackupOperationsExecutor::restoreFromBackupLog( - const std::vector &backupLog) { - taskType job = [backupLog]() { + const std::vector &backupLog, + size_t futureID) { + taskType job = [backupLog, futureID]() { try { DatabaseManager::getQueryExecutor().restoreFromBackupLog(backupLog); + ::resolveUnitFuture(futureID); } catch (const std::exception &e) { - // TODO: Inform Rust networking about failure - // of restoration from backup log. - Logger::log( - "Restore from backup log failed. Details: " + std::string(e.what())); + std::string errorDetails = std::string(e.what()); + Logger::log("Restore from backup log failed. Details: " + errorDetails); + ::rejectFuture(futureID, errorDetails); } }; GlobalDBSingleton::instance.scheduleOrRunCancellable(job); diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/BaseDataStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/BaseDataStore.h --- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/BaseDataStore.h +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/BaseDataStore.h @@ -4,6 +4,7 @@ #include "GlobalDBSingleton.h" #include "NativeModuleUtils.h" #include "WorkerThread.h" +#include "lib.rs.h" #include #include @@ -66,6 +67,10 @@ } } + if (!error.size()) { + ::triggerBackupFileUpload(); + } + this->jsInvoker->invokeAsync([=]() { if (error.size()) { promise->reject(error); @@ -89,6 +94,8 @@ } NativeModuleUtils::runSyncOrThrowJSError(rt, [&storeOps]() { + std::string error; + try { DatabaseManager::getQueryExecutor().beginTransaction(); for (const auto &operation : storeOps) { @@ -97,8 +104,14 @@ DatabaseManager::getQueryExecutor().captureBackupLogs(); DatabaseManager::getQueryExecutor().commitTransaction(); } catch (const std::exception &e) { + error = e.what(); DatabaseManager::getQueryExecutor().rollbackTransaction(); - throw e; + } + + if (error.size()) { + throw std::runtime_error(error); + } else if (!error.size()) { + ::triggerBackupFileUpload(); } }); } diff --git a/native/native_rust_library/RustBackupExecutor.h b/native/native_rust_library/RustBackupExecutor.h --- a/native/native_rust_library/RustBackupExecutor.h +++ b/native/native_rust_library/RustBackupExecutor.h @@ -14,6 +14,6 @@ rust::Str mainCompactionPath, rust::Str mainCompactionEncryptionKey, size_t futureID); -void restoreFromBackupLog(rust::Vec backupLog); +void restoreFromBackupLog(rust::Vec backupLog, size_t futureID); } // namespace comm diff --git a/native/native_rust_library/RustBackupExecutor.cpp b/native/native_rust_library/RustBackupExecutor.cpp --- a/native/native_rust_library/RustBackupExecutor.cpp +++ b/native/native_rust_library/RustBackupExecutor.cpp @@ -41,8 +41,9 @@ futureID); } -void restoreFromBackupLog(rust::Vec backupLog) { +void restoreFromBackupLog(rust::Vec backupLog, size_t futureID) { BackupOperationsExecutor::restoreFromBackupLog( - std::move(std::vector(backupLog.begin(), backupLog.end()))); + std::move(std::vector(backupLog.begin(), backupLog.end())), + futureID); } } // namespace comm diff --git a/native/native_rust_library/src/backup.rs b/native/native_rust_library/src/backup.rs --- a/native/native_rust_library/src/backup.rs +++ b/native/native_rust_library/src/backup.rs @@ -6,15 +6,15 @@ use crate::constants::{aes, secure_store}; use crate::ffi::{ create_main_compaction, get_backup_directory_path, - get_backup_user_keys_file_path, restore_from_main_compaction, - secure_store_get, void_callback, + get_backup_user_keys_file_path, restore_from_backup_log, + restore_from_main_compaction, secure_store_get, void_callback, }; use crate::future_manager; use crate::BACKUP_SOCKET_ADDR; use crate::RUNTIME; use backup_client::{ BackupClient, BackupDescriptor, LatestBackupIDResponse, RequestedData, - UserIdentity, + TryStreamExt, UserIdentity, }; use serde::{Deserialize, Serialize}; use std::error::Error; @@ -89,6 +89,14 @@ return; } + if let Err(error) = + download_and_apply_logs(&result.backup_id, result.backup_log_data_key) + .await + { + void_callback(error.to_string(), promise_id); + return; + } + void_callback(String::new(), promise_id); }); } @@ -106,8 +114,12 @@ let backup_data_key = secure_store_get(secure_store::SECURE_STORE_ENCRYPTION_KEY_ID)?; + let backup_log_data_key = + secure_store_get(secure_store::SECURE_STORE_BACKUP_LOGS_ENCRYPTION_KEY_ID)?; + let user_keys = UserKeys { backup_data_key, + backup_log_data_key, pickle_key, pickled_account, }; @@ -164,9 +176,36 @@ backup_id, backup_restoration_path, backup_data_key: user_keys.backup_data_key, + backup_log_data_key: user_keys.backup_log_data_key, }) } +async fn download_and_apply_logs( + backup_id: &str, + backup_log_data_key: String, +) -> Result<(), Box> { + let mut backup_log_data_key = backup_log_data_key.into_bytes(); + + let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?; + let user_identity = get_user_identity_from_secure_store()?; + + let stream = backup_client.download_logs(&user_identity, backup_id).await; + let mut stream = Box::pin(stream); + + while let Some(mut log) = stream.try_next().await? { + let data = decrypt( + backup_log_data_key.as_mut_slice(), + log.content.as_mut_slice(), + )?; + + let (future_id, future) = future_manager::new_future::<()>().await; + restore_from_backup_log(data, future_id); + future.await?; + } + + Ok(()) +} + fn get_user_identity_from_secure_store() -> Result { Ok(UserIdentity { @@ -180,11 +219,13 @@ backup_id: String, backup_restoration_path: PathBuf, backup_data_key: String, + backup_log_data_key: String, } #[derive(Debug, Serialize, Deserialize)] struct UserKeys { backup_data_key: String, + backup_log_data_key: String, pickle_key: String, pickled_account: String, } diff --git a/native/native_rust_library/src/constants.rs b/native/native_rust_library/src/constants.rs --- a/native/native_rust_library/src/constants.rs +++ b/native/native_rust_library/src/constants.rs @@ -14,6 +14,8 @@ pub const DEVICE_ID: &str = "deviceID"; /// Should match constant defined in `SQLiteQueryExecutor.h` pub const SECURE_STORE_ENCRYPTION_KEY_ID: &str = "comm.encryptionKey"; + pub const SECURE_STORE_BACKUP_LOGS_ENCRYPTION_KEY_ID: &str = + "comm.backupLogsEncryptionKey"; } pub const BACKUP_SERVICE_CONNECTION_RETRY_DELAY: Duration = diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -369,9 +369,8 @@ future_id: usize, ); - #[allow(unused)] #[cxx_name = "restoreFromBackupLog"] - fn restore_from_backup_log(backup_log: Vec) -> Result<()>; + fn restore_from_backup_log(backup_log: Vec, future_id: usize); } // Future handling from C++