diff --git a/services/backup/src/service/handlers/send_log.rs b/services/backup/src/service/handlers/send_log.rs --- a/services/backup/src/service/handlers/send_log.rs +++ b/services/backup/src/service/handlers/send_log.rs @@ -1,4 +1,5 @@ use tonic::Status; +use tracing::{error, trace, warn}; use uuid::Uuid; use crate::{ @@ -53,19 +54,40 @@ &mut self, user_id: String, ) -> Result<(), Status> { - unimplemented!() + if self.user_id.is_some() { + warn!("user ID already provided"); + return Err(Status::invalid_argument("User ID already provided")); + } + self.user_id = Some(user_id); + self.handle_internal().await } pub async fn handle_backup_id( &mut self, backup_id: String, ) -> Result<(), Status> { - unimplemented!() + if self.backup_id.is_some() { + warn!("backup ID already provided"); + return Err(Status::invalid_argument("Backup ID already provided")); + } + tracing::Span::current().record("backup_id", &backup_id); + self.backup_id = Some(backup_id); + self.handle_internal().await } pub async fn handle_log_hash( &mut self, log_hash: Vec, ) -> Result<(), Status> { - unimplemented!() + if self.log_hash.is_some() { + warn!("Log hash already provided"); + return Err(Status::invalid_argument("Log hash already provided")); + } + let hash_str = String::from_utf8(log_hash).map_err(|err| { + error!("Failed to convert data_hash into string: {:?}", err); + Status::aborted("Unexpected error") + })?; + tracing::Span::current().record("log_hash", &hash_str); + self.log_hash = Some(hash_str); + self.handle_internal().await } pub async fn handle_log_data( &mut self, @@ -77,4 +99,36 @@ pub async fn finish(self) -> Result { unimplemented!() } + + // internal param handler helper + async fn handle_internal(&mut self) -> Result<(), Status> { + if self.should_receive_data { + error!("SendLogHandler is already expecting data chunks"); + return Err(Status::failed_precondition("Log data chunk expected")); + } + + // all non-data inputs must be set before receiving log contents + let (Some(backup_id), Some(_), Some(_)) = ( + self.backup_id.as_ref(), + self.user_id.as_ref(), + self.log_hash.as_ref() + ) else { return Ok(()); }; + + let log_id = generate_log_id(backup_id); + tracing::Span::current().record("log_id", &log_id); + self.log_id = Some(log_id); + + trace!("Everything prepared, waiting for data..."); + self.should_receive_data = true; + Ok(()) + } +} + +fn generate_log_id(backup_id: &str) -> String { + format!( + "{backup_id}{sep}{uuid}", + backup_id = backup_id, + sep = ID_SEPARATOR, + uuid = Uuid::new_v4() + ) }