zai_rs/tool/file_parser_result/
data.rs1use std::sync::Arc;
7
8use tracing::{debug, trace, warn};
9
10use super::{request::*, response::*};
11use crate::{
12 ZaiResult,
13 client::{
14 endpoints::{ApiBase, EndpointConfig, join_url, paths},
15 error::codes,
16 http::{HttpClientConfig, parse_typed_response, send_empty_request},
17 },
18};
19
20pub struct FileParserResultRequest {
41 pub key: String,
43 endpoint_config: EndpointConfig,
44 api_base: ApiBase,
45 http_config: Arc<HttpClientConfig>,
46 pub task_id: String,
48}
49
50impl FileParserResultRequest {
51 pub fn new(key: String, task_id: impl Into<String>) -> Self {
62 Self {
63 key,
64 endpoint_config: EndpointConfig::default(),
65 api_base: ApiBase::PaasV4,
66 http_config: Arc::new(HttpClientConfig::default()),
67 task_id: task_id.into(),
68 }
69 }
70
71 pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
72 self.api_base = ApiBase::Custom(base_url.into());
73 self
74 }
75
76 pub fn with_endpoint_config(mut self, endpoint_config: EndpointConfig) -> Self {
77 self.endpoint_config = endpoint_config;
78 self
79 }
80
81 pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
82 self.http_config = Arc::new(config);
83 self
84 }
85
86 fn result_url(&self, format_type: &FormatType) -> String {
87 let path = join_url(
88 paths::FILE_PARSER_RESULT,
89 &join_url(&self.task_id, &format_type.to_string()),
90 );
91 self.endpoint_config.url(&self.api_base, &path)
92 }
93
94 pub async fn get_result(&self, format_type: FormatType) -> ZaiResult<FileParserResultResponse> {
104 let url = self.result_url(&format_type);
105 trace!(url = %url, "Fetching file parser result");
106 let response = send_empty_request(
107 reqwest::Method::GET,
108 url,
109 self.key.clone(),
110 self.http_config.clone(),
111 )
112 .await?;
113 parse_typed_response::<FileParserResultResponse>(response).await
114 }
115
116 pub async fn wait_for_result(
128 &self,
129 format_type: FormatType,
130 timeout_seconds: u64,
131 poll_interval_seconds: u64,
132 ) -> ZaiResult<FileParserResultResponse> {
133 debug!(
134 timeout_seconds,
135 poll_interval_seconds, "Polling file parser result"
136 );
137 let start_time = std::time::Instant::now();
138
139 loop {
140 trace!("Checking file parser result status");
141 let result = self.get_result(format_type.clone()).await?;
142
143 match result.status {
144 ParserStatus::Succeeded => {
145 debug!("File parsing completed successfully");
146 return Ok(result);
147 },
148 ParserStatus::Failed => {
149 warn!(
150 task_id = %self.task_id,
151 message = %result.message,
152 "File parsing task reported failure"
153 );
154 return Err(crate::client::error::ZaiError::ApiError {
155 code: codes::SDK_EXTERNAL_TOOL,
156 message: format!("Parsing failed: {}", result.message),
157 });
158 },
159 ParserStatus::Processing => {
160 let elapsed = start_time.elapsed().as_secs();
161 trace!(elapsed, "File parser result still processing");
162 if elapsed > timeout_seconds {
163 warn!(
164 task_id = %self.task_id,
165 elapsed,
166 timeout_seconds,
167 "Polling timed out waiting for parsing result"
168 );
169 return Err(crate::client::error::ZaiError::ApiError {
170 code: codes::SDK_TIMEOUT,
171 message: "Timeout waiting for parsing result".to_string(),
172 });
173 }
174 tokio::time::sleep(tokio::time::Duration::from_secs(poll_interval_seconds))
175 .await;
176 },
177 }
178 }
179 }
180
181 pub async fn get_all_results(
187 &self,
188 ) -> ZaiResult<(FileParserResultResponse, FileParserResultResponse)> {
189 let text_result = self.get_result(FormatType::Text).await?;
190 let download_result = self.get_result(FormatType::DownloadLink).await?;
191 Ok((text_result, download_result))
192 }
193}