Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3375546
D10621.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
D10621.id.diff
View Options
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
@@ -125,6 +125,8 @@
jsi::Runtime &rt,
jsi::String accessToken) override;
virtual jsi::Value clearCommServicesAccessToken(jsi::Runtime &rt) override;
+ virtual void startBackupHandler(jsi::Runtime &rt) override;
+ virtual void stopBackupHandler(jsi::Runtime &rt) override;
virtual jsi::Value createNewBackup(
jsi::Runtime &rt,
jsi::String backupSecret,
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
@@ -1315,6 +1315,22 @@
});
}
+void CommCoreModule::startBackupHandler(jsi::Runtime &rt) {
+ try {
+ ::startBackupHandler();
+ } catch (const std::exception &e) {
+ throw jsi::JSError(rt, e.what());
+ }
+}
+
+void CommCoreModule::stopBackupHandler(jsi::Runtime &rt) {
+ try {
+ ::stopBackupHandler();
+ } catch (const std::exception &e) {
+ throw jsi::JSError(rt, e.what());
+ }
+}
+
jsi::Value CommCoreModule::createNewBackup(
jsi::Runtime &rt,
jsi::String backupSecret,
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
@@ -143,6 +143,14 @@
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_clearCommServicesAccessToken(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->clearCommServicesAccessToken(rt);
}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_startBackupHandler(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+ static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->startBackupHandler(rt);
+ return jsi::Value::undefined();
+}
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_stopBackupHandler(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+ static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->stopBackupHandler(rt);
+ return jsi::Value::undefined();
+}
static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->createNewBackup(rt, args[0].asString(rt), args[1].asString(rt));
}
@@ -194,6 +202,8 @@
methodMap_["getCommServicesAuthMetadata"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getCommServicesAuthMetadata};
methodMap_["setCommServicesAccessToken"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_setCommServicesAccessToken};
methodMap_["clearCommServicesAccessToken"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_clearCommServicesAccessToken};
+ methodMap_["startBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_startBackupHandler};
+ methodMap_["stopBackupHandler"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_stopBackupHandler};
methodMap_["createNewBackup"] = MethodMetadata {2, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_createNewBackup};
methodMap_["restoreBackup"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreBackup};
}
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
@@ -62,6 +62,8 @@
virtual jsi::Value getCommServicesAuthMetadata(jsi::Runtime &rt) = 0;
virtual jsi::Value setCommServicesAccessToken(jsi::Runtime &rt, jsi::String accessToken) = 0;
virtual jsi::Value clearCommServicesAccessToken(jsi::Runtime &rt) = 0;
+ virtual void startBackupHandler(jsi::Runtime &rt) = 0;
+ virtual void stopBackupHandler(jsi::Runtime &rt) = 0;
virtual jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String userData) = 0;
virtual jsi::Value restoreBackup(jsi::Runtime &rt, jsi::String backupSecret) = 0;
@@ -421,6 +423,22 @@
return bridging::callFromJs<jsi::Value>(
rt, &T::clearCommServicesAccessToken, jsInvoker_, instance_);
}
+ void startBackupHandler(jsi::Runtime &rt) override {
+ static_assert(
+ bridging::getParameterCount(&T::startBackupHandler) == 1,
+ "Expected startBackupHandler(...) to have 1 parameters");
+
+ return bridging::callFromJs<void>(
+ rt, &T::startBackupHandler, jsInvoker_, instance_);
+ }
+ void stopBackupHandler(jsi::Runtime &rt) override {
+ static_assert(
+ bridging::getParameterCount(&T::stopBackupHandler) == 1,
+ "Expected stopBackupHandler(...) to have 1 parameters");
+
+ return bridging::callFromJs<void>(
+ rt, &T::stopBackupHandler, jsInvoker_, instance_);
+ }
jsi::Value createNewBackup(jsi::Runtime &rt, jsi::String backupSecret, jsi::String userData) override {
static_assert(
bridging::getParameterCount(&T::createNewBackup) == 3,
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
@@ -1,9 +1,13 @@
+mod upload_handler;
+
+use std::error::Error;
+
use crate::argon2_tools::{compute_backup_key, compute_backup_key_str};
use crate::constants::{aes, secure_store};
use crate::ffi::secure_store_get;
-use crate::handle_string_result_as_callback;
use crate::BACKUP_SOCKET_ADDR;
use crate::RUNTIME;
+use crate::{handle_string_result_as_callback, handle_void_result_as_callback};
use backup_client::{
BackupClient, BackupData, BackupDescriptor, DownloadLogsRequest,
LatestBackupIDResponse, LogUploadConfirmation, LogWSResponse, RequestedData,
@@ -11,13 +15,12 @@
};
use serde::{Deserialize, Serialize};
use serde_json::json;
-use std::error::Error;
pub mod ffi {
- use crate::handle_void_result_as_callback;
-
use super::*;
+ pub use upload_handler::ffi::*;
+
pub fn create_backup_sync(
backup_id: String,
backup_secret: String,
diff --git a/native/native_rust_library/src/backup/upload_handler.rs b/native/native_rust_library/src/backup/upload_handler.rs
new file mode 100644
--- /dev/null
+++ b/native/native_rust_library/src/backup/upload_handler.rs
@@ -0,0 +1,105 @@
+use super::get_user_identity_from_secure_store;
+use crate::constants::BACKUP_SERVICE_CONNECTION_RETRY_DELAY;
+use crate::BACKUP_SOCKET_ADDR;
+use crate::RUNTIME;
+use backup_client::{
+ BackupClient, Error as BackupError, LogUploadConfirmation, Stream, StreamExt,
+ WSError,
+};
+use lazy_static::lazy_static;
+use std::convert::Infallible;
+use std::error::Error;
+use std::future::{self, Future};
+use std::pin::Pin;
+use std::sync::{Arc, Mutex};
+use tokio::task::JoinHandle;
+
+lazy_static! {
+ pub static ref UPLOAD_HANDLER: Arc<Mutex<Option<JoinHandle<Infallible>>>> =
+ Arc::new(Mutex::new(None));
+}
+
+pub mod ffi {
+ use super::*;
+
+ pub fn start_backup_handler() -> Result<(), Box<dyn Error>> {
+ let mut handle = UPLOAD_HANDLER.lock()?;
+ match handle.take() {
+ // Don't start backup handler if it's already running
+ Some(handle) if !handle.is_finished() => (),
+ _ => {
+ *handle = Some(RUNTIME.spawn(super::start()?));
+ }
+ }
+
+ Ok(())
+ }
+
+ pub fn stop_backup_handler() -> Result<(), Box<dyn Error>> {
+ let Some(handler) = UPLOAD_HANDLER.lock()?.take() else {
+ return Ok(());
+ };
+ if handler.is_finished() {
+ return Ok(());
+ }
+
+ handler.abort();
+ Ok(())
+ }
+}
+
+pub fn start() -> Result<impl Future<Output = Infallible>, Box<dyn Error>> {
+ let backup_client = BackupClient::new(BACKUP_SOCKET_ADDR)?;
+ let user_identity = get_user_identity_from_secure_store()?;
+
+ Ok(async move {
+ loop {
+ let (tx, rx) = match backup_client.upload_logs(&user_identity).await {
+ Ok(ws) => ws,
+ Err(err) => {
+ println!(
+ "Backup handler error when estabilishing connection: '{err:?}'"
+ );
+ tokio::time::sleep(BACKUP_SERVICE_CONNECTION_RETRY_DELAY).await;
+ continue;
+ }
+ };
+
+ let mut _tx = Box::pin(tx);
+ let mut rx = Box::pin(rx);
+
+ let err = tokio::select! {
+ Err(err) = watch_and_upload_files() => err,
+ Err(err) = delete_confirmed_logs(&mut rx) => err,
+ };
+
+ println!("Backup handler error: '{err:?}'");
+
+ tokio::time::sleep(BACKUP_SERVICE_CONNECTION_RETRY_DELAY).await;
+ println!("Retrying backup log upload");
+ }
+ })
+}
+
+async fn watch_and_upload_files() -> Result<Infallible, BackupHandlerError> {
+ loop {
+ let () = future::pending().await;
+ }
+}
+
+async fn delete_confirmed_logs(
+ rx: &mut Pin<Box<impl Stream<Item = Result<LogUploadConfirmation, WSError>>>>,
+) -> Result<Infallible, BackupHandlerError> {
+ while let Some(_) = rx.next().await.transpose()? {}
+
+ Err(BackupHandlerError::WSClosed)
+}
+
+#[derive(
+ Debug, derive_more::Display, derive_more::From, derive_more::Error,
+)]
+enum BackupHandlerError {
+ BackupError(BackupError),
+ BackupWSError(WSError),
+ WSClosed,
+}
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
@@ -1,3 +1,5 @@
+use std::time::Duration;
+
pub mod aes {
pub const KEY_SIZE: usize = 32; // bytes
pub const IV_LENGTH: usize = 12; // bytes - unique Initialization Vector (nonce)
@@ -10,3 +12,6 @@
pub const USER_ID: &str = "userID";
pub const DEVICE_ID: &str = "deviceID";
}
+
+pub const BACKUP_SERVICE_CONNECTION_RETRY_DELAY: Duration =
+ Duration::from_secs(5);
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
@@ -240,6 +240,11 @@
// Backup
extern "Rust" {
+ #[cxx_name = "startBackupHandler"]
+ fn start_backup_handler() -> Result<()>;
+ #[cxx_name = "stopBackupHandler"]
+ fn stop_backup_handler() -> Result<()>;
+
#[cxx_name = "createBackup"]
fn create_backup_sync(
backup_id: String,
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -124,6 +124,8 @@
+getCommServicesAuthMetadata: () => Promise<CommServicesAuthMetadata>;
+setCommServicesAccessToken: (accessToken: string) => Promise<void>;
+clearCommServicesAccessToken: () => Promise<void>;
+ +startBackupHandler: () => void;
+ +stopBackupHandler: () => void;
+createNewBackup: (backupSecret: string, userData: string) => Promise<void>;
+restoreBackup: (backupSecret: string) => Promise<string>;
}
diff --git a/shared/backup_client/src/lib.rs b/shared/backup_client/src/lib.rs
--- a/shared/backup_client/src/lib.rs
+++ b/shared/backup_client/src/lib.rs
@@ -3,9 +3,8 @@
DownloadLogsRequest, LatestBackupIDResponse, LogWSRequest, LogWSResponse,
UploadLogRequest,
};
-pub use futures_util::{SinkExt, StreamExt, TryStreamExt};
+pub use futures_util::{Sink, SinkExt, Stream, StreamExt, TryStreamExt};
-use futures_util::{Sink, Stream};
use hex::ToHex;
use reqwest::{
header::InvalidHeaderValue,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 27, 8:44 PM (10 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2591644
Default Alt Text
D10621.id.diff (11 KB)
Attached To
Mode
D10621: [native] Implement persistent rust backup client
Attached
Detach File
Event Timeline
Log In to Comment