cloudiful_docling_convert/processor/service/
remote.rs1use super::DocumentConverter;
2use crate::api::{DoclingConvertRequest, DoclingResult};
3use crate::document::{InputDocument, OutputFormat, RemoteConvertOptions};
4use crate::error::{PdfConvertError, Result};
5use crate::models::TaskStatusResponse;
6
7impl DocumentConverter {
8 pub async fn convert_source_to_file_async(
9 &self,
10 url: &str,
11 filename: impl Into<String>,
12 input_kind: crate::document::InputKind,
13 output_formats: Vec<OutputFormat>,
14 options: &RemoteConvertOptions,
15 output_dir: std::path::PathBuf,
16 selected_output: OutputFormat,
17 overwrite: bool,
18 ) -> Result<crate::document::ConvertedFile> {
19 self.convert_source_to_file_async_with_docling_progress(
20 url,
21 filename,
22 input_kind,
23 output_formats,
24 options,
25 output_dir,
26 selected_output,
27 overwrite,
28 |_| async {},
29 )
30 .await
31 }
32
33 pub async fn convert_source_to_file_async_with_docling_progress<F, Fut>(
34 &self,
35 url: &str,
36 filename: impl Into<String>,
37 input_kind: crate::document::InputKind,
38 output_formats: Vec<OutputFormat>,
39 options: &RemoteConvertOptions,
40 output_dir: std::path::PathBuf,
41 selected_output: OutputFormat,
42 overwrite: bool,
43 mut on_status: F,
44 ) -> Result<crate::document::ConvertedFile>
45 where
46 F: FnMut(TaskStatusResponse) -> Fut + Send,
47 Fut: std::future::Future<Output = ()> + Send,
48 {
49 let filename = filename.into();
50 let input = InputDocument::new(
51 filename,
52 input_kind.canonical_media_type("source", None),
53 Vec::<u8>::new(),
54 )
55 .with_input_kind(input_kind);
56 let request = DoclingConvertRequest {
57 output_formats,
58 page_range: None,
59 chunker: options.chunker,
60 chunking: options.chunking.clone(),
61 pipeline: options.pipeline,
62 };
63 let task_id = self
64 .docling_client
65 .submit_source_async(url, input_kind, &request)
66 .await?;
67 let task_result = self
68 .docling_client
69 .wait_for_result_with_progress(&task_id, &mut on_status)
70 .await?;
71 let document = Self::document_from_task_result(&input, task_result)?;
72 let output_path =
73 Self::calculate_output_path(&output_dir, &document.filename, selected_output);
74 if !overwrite && output_path.exists() {
75 return Err(PdfConvertError::operation_error(
76 "writing output",
77 format!(
78 "output already exists and overwrite is disabled: {}",
79 output_path.display()
80 ),
81 ));
82 }
83 Self::write_output_file(&output_path, &document, selected_output).await?;
84 Ok(crate::document::ConvertedFile {
85 document,
86 output_paths: vec![output_path],
87 })
88 }
89
90 pub(super) async fn convert_remote_with_docling_progress<F, Fut>(
91 &self,
92 input: &InputDocument,
93 options: &RemoteConvertOptions,
94 output_formats: &[OutputFormat],
95 on_status: &mut F,
96 ) -> Result<crate::document::ConvertedDocument>
97 where
98 F: FnMut(TaskStatusResponse) -> Fut + Send,
99 Fut: std::future::Future<Output = ()> + Send,
100 {
101 let request = DoclingConvertRequest {
102 output_formats: output_formats.to_vec(),
103 page_range: None,
104 chunker: options.chunker,
105 chunking: options.chunking.clone(),
106 pipeline: options.pipeline,
107 };
108 let task_id = self
109 .docling_client
110 .submit_file_async(input, &request)
111 .await?;
112 let task_result = self
113 .docling_client
114 .wait_for_result_with_progress(&task_id, on_status)
115 .await?;
116 Self::document_from_task_result(input, task_result)
117 }
118
119 pub(super) async fn convert_remote<F, Fut>(
120 &self,
121 input: &InputDocument,
122 options: &RemoteConvertOptions,
123 output_formats: &[OutputFormat],
124 asynchronous: bool,
125 on_progress: &mut F,
126 ) -> Result<crate::document::ConvertedDocument>
127 where
128 F: FnMut(usize, usize) -> Fut + Send,
129 Fut: std::future::Future<Output = ()> + Send,
130 {
131 let request = DoclingConvertRequest {
132 output_formats: output_formats.to_vec(),
133 page_range: None,
134 chunker: options.chunker,
135 chunking: options.chunking.clone(),
136 pipeline: options.pipeline,
137 };
138
139 let result = if asynchronous {
140 let task_id = self
141 .docling_client
142 .submit_file_async(input, &request)
143 .await?;
144 let task_result = self.docling_client.wait_for_result(&task_id).await?;
145 let document = Self::document_from_task_result(input, task_result)?;
146 on_progress(1, 1).await;
147 return Ok(document);
148 } else {
149 let result = self.docling_client.convert_file(input, &request).await?;
150 on_progress(1, 1).await;
151 result
152 };
153
154 Self::document_from_result(input, result)
155 }
156
157 pub(super) fn document_from_result(
158 input: &InputDocument,
159 result: DoclingResult,
160 ) -> Result<crate::document::ConvertedDocument> {
161 let input_kind = input.kind()?;
162 match result {
163 DoclingResult::Failure(failure) => Err(PdfConvertError::api_task_failed(
164 "failure",
165 failure.failure.message,
166 )),
167 result => Ok(Self::build_document(input, input_kind, result)),
168 }
169 }
170
171 pub fn document_from_task_result(
172 input: &InputDocument,
173 task_result: crate::api::DoclingTaskResult,
174 ) -> Result<crate::document::ConvertedDocument> {
175 let mut document = Self::document_from_result(input, task_result.result)?;
176 document.errors.extend(task_result.errors);
177 document.errors.sort();
178 document.errors.dedup();
179 Ok(document)
180 }
181}