use crate::app::context::AppContext;
use crate::{db::RestoreSessionManager, util::enqueue_restore_session_msg};
use mostro_core::prelude::*;
use nostr_sdk::prelude::*;
pub async fn restore_session_action(
ctx: &AppContext,
event: &UnwrappedMessage,
) -> Result<(), MostroError> {
let pool = ctx.pool();
let master_key = event.identity.to_string();
let trade_key = event.sender.to_string();
if !master_key.chars().all(|c| c.is_ascii_hexdigit()) || master_key.len() != 64 {
return Err(MostroCantDo(CantDoReason::InvalidPubkey));
}
if !trade_key.chars().all(|c| c.is_ascii_hexdigit()) || trade_key.len() != 64 {
return Err(MostroCantDo(CantDoReason::InvalidPubkey));
}
tracing::info!(
"Starting background restore session for master key: {}",
master_key
);
let manager = RestoreSessionManager::new();
let pool_clone = pool.clone();
manager
.start_restore_session(pool_clone, master_key.clone())
.await?;
tokio::spawn(async move {
handle_restore_session_results(manager, trade_key).await;
});
Ok(())
}
async fn handle_restore_session_results(mut manager: RestoreSessionManager, trade_key: String) {
let timeout = tokio::time::Duration::from_secs(60 * 60);
match tokio::time::timeout(timeout, manager.wait_for_result()).await {
Ok(Some(result)) => {
if let Err(e) = send_restore_session_response(
&trade_key,
result.restore_orders,
result.restore_disputes,
)
.await
{
tracing::error!("Failed to send restore session response: {}", e);
}
}
Ok(None) => {
tracing::error!("Restore session result channel closed unexpectedly");
}
Err(_) => {
tracing::error!("Restore session timed out after 1 hour");
if let Err(e) = send_restore_session_timeout(&trade_key).await {
tracing::error!("Failed to send timeout message: {}", e);
}
}
}
}
async fn send_restore_session_response(
trade_key: &str,
orders: Vec<RestoredOrdersInfo>,
disputes: Vec<RestoredDisputesInfo>,
) -> Result<(), MostroError> {
let trade_pubkey =
PublicKey::from_hex(trade_key).map_err(|_| MostroCantDo(CantDoReason::InvalidPubkey))?;
enqueue_restore_session_msg(
Some(Payload::RestoreData(RestoreSessionInfo {
restore_orders: orders,
restore_disputes: disputes,
})),
trade_pubkey,
)
.await;
tracing::info!("Restore session response sent to user {}", trade_key,);
Ok(())
}
async fn send_restore_session_timeout(trade_key: &str) -> Result<(), MostroError> {
let trade_pubkey =
PublicKey::from_hex(trade_key).map_err(|_| MostroCantDo(CantDoReason::InvalidPubkey))?;
enqueue_restore_session_msg(None, trade_pubkey).await;
tracing::warn!("Restore session timed out for user: {}", trade_key);
Ok(())
}