diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java index d6c8eb9..e496380 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeApi.java @@ -1,12 +1,17 @@ package ai.docling.serve.api; +import java.time.Duration; + import org.jspecify.annotations.Nullable; +import ai.docling.serve.api.convert.request.ConvertDocumentRequest; + /** * Docling Serve API interface. */ public interface DoclingServeApi extends DoclingServeHealthApi, DoclingServeConvertApi, DoclingServeChunkApi, DoclingServeClearApi, DoclingServeTaskApi { + /** * Creates and returns a builder instance capable of constructing a duplicate or modified * version of the current API instance. The builder provides a customizable way to adjust @@ -103,6 +108,30 @@ default B prettyPrint() { return prettyPrint(true); } + /** + * Sets the polling interval for async operations. + * + *
This configures how frequently the client will check the status of async + * conversion tasks when using {@link DoclingServeApi#convertSourceAsync(ConvertDocumentRequest)} (ConvertDocumentRequest)}. + * + * @param asyncPollInterval the polling interval (must not be null or negative) + * @return this builder instance for method chaining + * @throws IllegalArgumentException if asyncPollInterval is null or negative + */ + B asyncPollInterval(Duration asyncPollInterval); + + /** + * Sets the timeout for async operations. + * + *
This configures the maximum time to wait for an async conversion task to complete + * when using {@link DoclingServeApi#convertSourceAsync(ConvertDocumentRequest)} (ConvertDocumentRequest)}. + * + * @param asyncTimeout the timeout duration (must not be null or negative) + * @return this builder instance for method chaining + * @throws IllegalArgumentException if asyncTimeout is null or negative + */ + B asyncTimeout(Duration asyncTimeout); + /** * Builds and returns an instance of the specified type, representing the completed configuration * of the builder. The returned instance is typically an implementation of the Docling API. diff --git a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeConvertApi.java b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeConvertApi.java index 6c28631..fbe626c 100644 --- a/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeConvertApi.java +++ b/docling-serve/docling-serve-api/src/main/java/ai/docling/serve/api/DoclingServeConvertApi.java @@ -1,5 +1,7 @@ package ai.docling.serve.api; +import java.util.concurrent.CompletableFuture; + import ai.docling.serve.api.convert.request.ConvertDocumentRequest; import ai.docling.serve.api.convert.response.ConvertDocumentResponse; @@ -9,11 +11,33 @@ * a structured or processed document format based on the specified conversion options. */ public interface DoclingServeConvertApi { - /** + /** * Converts the provided document source(s) into a processed document based on the specified options. * * @param request the {@link ConvertDocumentRequest} containing the source(s), conversion options, and optional target. * @return a {@link ConvertDocumentResponse} containing the processed document data, processing details, and any errors. */ ConvertDocumentResponse convertSource(ConvertDocumentRequest request); + + /** + * Initiates an asynchronous conversion of the provided document source(s) and returns a + * {@link CompletableFuture} that completes when the conversion is done. + * + *
This method starts the conversion, polls the status in the background, and completes + * the future with the result when the conversion finishes. + * + *
Example usage: + *
{@code
+ * client.convertSourceAsync(request)
+ * .thenApply(response -> response.getDocument().getMarkdownContent())
+ * .thenAccept(markdown -> System.out.println(markdown))
+ * .exceptionally(ex -> { ex.printStackTrace(); return null; });
+ * }
+ *
+ * @param request the {@link ConvertDocumentRequest} containing the source(s) and conversion options.
+ * @return a {@link CompletableFuture} that completes with the {@link ConvertDocumentResponse}
+ * when the conversion is finished, or completes exceptionally if the conversion fails
+ * or times out.
+ */
+ CompletableFutureThis configures the maximum time to wait for an async conversion task to complete
+ * when using {@link DoclingServeApi#convertSourceAsync(ConvertDocumentRequest)} (ConvertDocumentRequest)}.
+ *
+ * @param asyncTimeout the timeout duration (must not be null or negative)
+ * @return this builder instance for method chaining
+ * @throws IllegalArgumentException if asyncTimeout is null or negative
+ */
+ @Override
+ public B asyncTimeout(Duration asyncTimeout) {
+ if (asyncTimeout == null || asyncTimeout.isNegative() || asyncTimeout.isZero()) {
+ throw new IllegalArgumentException("asyncTimeout must be a positive duration");
+ }
+ this.asyncTimeout = asyncTimeout;
+ return (B) this;
+ }
}
}
diff --git a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java
index 87e1839..14e866d 100644
--- a/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java
+++ b/docling-serve/docling-serve-client/src/main/java/ai/docling/serve/client/operations/ConvertOperations.java
@@ -1,27 +1,51 @@
package ai.docling.serve.client.operations;
+import java.time.Duration;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import ai.docling.serve.api.DoclingServeConvertApi;
+import ai.docling.serve.api.DoclingServeTaskApi;
import ai.docling.serve.api.convert.request.ConvertDocumentRequest;
import ai.docling.serve.api.convert.response.ConvertDocumentResponse;
+import ai.docling.serve.api.task.request.TaskResultRequest;
+import ai.docling.serve.api.task.request.TaskStatusPollRequest;
+import ai.docling.serve.api.task.response.TaskStatusPollResponse;
import ai.docling.serve.api.util.ValidationUtils;
/**
* Base class for document conversion API operations. Provides access to document
- * conversion functionality.
+ * conversion functionality including both synchronous and asynchronous operations.
*/
public final class ConvertOperations implements DoclingServeConvertApi {
- private final HttpOperations httpOperations;
+ private static final Logger LOG = LoggerFactory.getLogger(ConvertOperations.class);
- public ConvertOperations(HttpOperations httpOperations) {
- this.httpOperations = httpOperations;
- }
+ private final HttpOperations httpOperations;
+ private final DoclingServeTaskApi taskApi;
+ private final Duration asyncPollInterval;
+ private final Duration asyncTimeout;
/**
- * Converts the provided document source(s) into a processed document based on the specified options.
+ * Creates a new ConvertOperations instance.
*
- * @param request the {@link ConvertDocumentRequest} containing the source(s), conversion options, and optional target.
- * @return a {@link ConvertDocumentResponse} containing the processed document data, processing details, and any errors.
+ * @param httpOperations the HTTP operations handler for executing requests
+ * @param taskApi the task operations handler for polling and retrieving results
+ * @param asyncPollInterval the interval between status polls for async operations
+ * @param asyncTimeout the maximum time to wait for async operations to complete
*/
+ public ConvertOperations(HttpOperations httpOperations, DoclingServeTaskApi taskApi,
+ Duration asyncPollInterval, Duration asyncTimeout) {
+ this.httpOperations = httpOperations;
+ this.taskApi = taskApi;
+ this.asyncPollInterval = asyncPollInterval;
+ this.asyncTimeout = asyncTimeout;
+ }
+
+ @Override
public ConvertDocumentResponse convertSource(ConvertDocumentRequest request) {
ValidationUtils.ensureNotNull(request, "request");
return this.httpOperations.executePost(createRequestContext("/v1/convert/source", request));
@@ -34,4 +58,78 @@ private RequestContext createRequestContext(Stri
.uri(uri)
.build();
}
+
+ private RequestContext createAsyncRequestContext(String uri, I request) {
+ return RequestContext.builder()
+ .request(request)
+ .responseType(TaskStatusPollResponse.class)
+ .uri(uri)
+ .build();
+ }
+
+ @Override
+ public CompletableFuture