Skip to main content

rusty_cat/
transfer_task.rs

1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3
4use reqwest::header::HeaderMap;
5use reqwest::Method;
6use tokio::fs::File;
7use tokio::sync::Mutex;
8
9use crate::direction::Direction;
10use crate::http_breakpoint::{BreakpointDownload, BreakpointDownloadHttpConfig, BreakpointUpload};
11use crate::inner::inner_task::InnerTask;
12
13/// 对 [`crate::transfer_executor_trait::TransferTrait`] 暴露的任务快照:仅含查询接口,由内部从 [`InnerTask`] 填充。
14#[derive(Clone)]
15pub struct TransferTask {
16    file_sign: String,
17    file_name: String,
18    file_path: PathBuf,
19    direction: Direction,
20    total_size: u64,
21    chunk_size: u64,
22    url: String,
23    method: Method,
24    headers: HeaderMap,
25    breakpoint_download_http: BreakpointDownloadHttpConfig,
26    breakpoint_upload: Arc<dyn BreakpointUpload + Send + Sync>,
27    breakpoint_download: Arc<dyn BreakpointDownload + Send + Sync>,
28    http_client: Option<reqwest::Client>,
29    /// 任务级上传文件句柄槽位,避免每个 chunk 反复 open。
30    upload_file_slot: Arc<Mutex<Option<File>>>,
31    /// 任务级下载文件句柄槽位,避免每个 chunk 反复 open/create。
32    download_file_slot: Arc<Mutex<Option<File>>>,
33}
34
35impl std::fmt::Debug for TransferTask {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.debug_struct("TransferTask")
38            .field("file_sign", &self.file_sign)
39            .field("file_name", &self.file_name)
40            .field("file_path", &self.file_path)
41            .field("direction", &self.direction)
42            .field("total_size", &self.total_size)
43            .field("chunk_size", &self.chunk_size)
44            .field("url", &self.url)
45            .field("method", &self.method)
46            .field("headers", &self.headers)
47            .field("breakpoint_upload", &"<dyn BreakpointUpload>")
48            .field("breakpoint_download", &"<dyn BreakpointDownload>")
49            .field("breakpoint_download_http", &self.breakpoint_download_http)
50            .finish()
51    }
52}
53
54impl TransferTask {
55    pub(crate) fn from_inner(inner: &InnerTask) -> Self {
56        Self {
57            file_sign: inner.file_sign().to_string(),
58            file_name: inner.file_name().to_string(),
59            file_path: inner.file_path().to_path_buf(),
60            direction: inner.direction(),
61            total_size: inner.total_size(),
62            chunk_size: inner.chunk_size(),
63            url: inner.url().to_string(),
64            method: inner.method(),
65            headers: inner.headers().clone(),
66            breakpoint_download_http: inner.breakpoint_download_http().clone(),
67            breakpoint_upload: inner.breakpoint_upload().clone(),
68            breakpoint_download: inner.breakpoint_download().clone(),
69            http_client: inner.http_client_ref().cloned(),
70            upload_file_slot: Arc::new(Mutex::new(None)),
71            download_file_slot: Arc::new(Mutex::new(None)),
72        }
73    }
74
75    pub fn direction(&self) -> Direction {
76        self.direction
77    }
78
79    pub fn total_size(&self) -> u64 {
80        self.total_size
81    }
82
83    pub fn chunk_size(&self) -> u64 {
84        self.chunk_size
85    }
86
87    pub fn file_sign(&self) -> &str {
88        &self.file_sign
89    }
90
91    pub fn file_name(&self) -> &str {
92        &self.file_name
93    }
94
95    pub fn file_path(&self) -> &Path {
96        &self.file_path
97    }
98
99    pub fn url(&self) -> &str {
100        &self.url
101    }
102
103    pub fn method(&self) -> Method {
104        self.method.clone()
105    }
106
107    pub fn headers(&self) -> &HeaderMap {
108        &self.headers
109    }
110
111    /// 返回任务级断点下载 HTTP 配置,供自定义 [`crate::download_trait::BreakpointDownload`]
112    /// 实现读取(例如 `range_accept` 语义)。
113    pub fn breakpoint_download_http(&self) -> Option<&BreakpointDownloadHttpConfig> {
114        Some(&self.breakpoint_download_http)
115    }
116
117    pub(crate) fn breakpoint_upload(&self) -> Option<&Arc<dyn BreakpointUpload + Send + Sync>> {
118        Some(&self.breakpoint_upload)
119    }
120
121    pub(crate) fn breakpoint_download(&self) -> Option<&Arc<dyn BreakpointDownload + Send + Sync>> {
122        Some(&self.breakpoint_download)
123    }
124
125    pub(crate) fn http_client_ref(&self) -> Option<&reqwest::Client> {
126        self.http_client.as_ref()
127    }
128
129    pub(crate) fn upload_file_slot(&self) -> &Arc<Mutex<Option<File>>> {
130        &self.upload_file_slot
131    }
132
133    pub(crate) fn download_file_slot(&self) -> &Arc<Mutex<Option<File>>> {
134        &self.download_file_slot
135    }
136}