use crate::core::types::EntryType;
use iroh_blobs::{Hash, ticket::BlobTicket};
use std::path::PathBuf;
use tokio::sync::watch;
pub use crate::core::progress::SenderTransferStatus;
pub struct SendResult {
pub ticket: BlobTicket,
pub hash: Hash,
pub size: u64,
pub entry_type: EntryType,
pub router: iroh::protocol::Router, pub temp_tag: iroh_blobs::api::TempTag, pub blobs_data_dir: PathBuf, pub _progress_handle: n0_future::task::AbortOnDropHandle<anyhow::Result<()>>, pub _store: iroh_blobs::store::fs::FsStore, pub(crate) transfer_status_rx: watch::Receiver<SenderTransferStatus>,
}
fn normalize_sender_cleanup_result(cleanup_result: std::io::Result<()>) -> anyhow::Result<()> {
match cleanup_result {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(error.into()),
}
}
fn finalize_sender_shutdown(
shutdown_result: anyhow::Result<()>,
cleanup_result: anyhow::Result<()>,
) -> anyhow::Result<()> {
if let Err(error) = cleanup_result {
tracing::warn!(error = %error, "failed to clean sender temporary data dir");
}
shutdown_result
}
impl SendResult {
pub fn transfer_status(&self) -> SenderTransferStatus {
*self.transfer_status_rx.borrow()
}
pub fn subscribe_transfer_status(&self) -> watch::Receiver<SenderTransferStatus> {
self.transfer_status_rx.clone()
}
pub async fn shutdown(self) -> anyhow::Result<()> {
drop(self.temp_tag);
let shutdown_result =
match tokio::time::timeout(std::time::Duration::from_secs(2), self.router.shutdown())
.await
{
Ok(result) => result.map_err(anyhow::Error::from),
Err(error) => Err(error.into()),
};
let cleanup_result =
normalize_sender_cleanup_result(tokio::fs::remove_dir_all(&self.blobs_data_dir).await);
finalize_sender_shutdown(shutdown_result, cleanup_result)
}
}
#[derive(Debug)]
pub struct ReceiveResult {
pub message: String,
pub file_path: PathBuf,
}
#[cfg(test)]
mod tests {
use super::{finalize_sender_shutdown, normalize_sender_cleanup_result};
#[test]
fn normalize_sender_cleanup_result_ignores_not_found() {
let err = std::io::Error::new(std::io::ErrorKind::NotFound, "missing dir");
normalize_sender_cleanup_result(Err(err)).expect("not found should be ignored");
}
#[test]
fn finalize_sender_shutdown_preserves_shutdown_error() {
let shutdown_error = anyhow::anyhow!("shutdown failed");
let cleanup_error = anyhow::anyhow!("cleanup failed");
let err = finalize_sender_shutdown(Err(shutdown_error), Err(cleanup_error))
.expect_err("shutdown error should be preserved");
assert!(err.to_string().contains("shutdown failed"));
}
#[test]
fn finalize_sender_shutdown_returns_ok_when_shutdown_succeeds() {
finalize_sender_shutdown(Ok(()), Err(anyhow::anyhow!("cleanup failed")))
.expect("cleanup errors should not fail successful shutdown");
}
}