This is an automated email from the ASF dual-hosted git repository. oscerd pushed a commit to branch fix/CAMEL-23459 in repository https://gitbox.apache.org/repos/asf/camel.git
commit e322ab6c22fed9e431c56b5bc4726b6208bd9a51 Author: Andrea Cosentino <[email protected]> AuthorDate: Mon May 11 15:20:34 2026 +0200 CAMEL-23459: Add TTL cleanup for pending async tasks to prevent memory leak DoclingComponent now tracks pending async-conversion task IDs with timestamps in AsyncTaskEntry wrapper objects. A scheduled cleanup task runs periodically (every 10% of TTL, minimum 1 minute) to evict entries older than the configured asyncTaskTtl (default 24 hours). - Added AsyncTaskEntry class to wrap CompletableFuture with creation timestamp - Added asyncTaskTtl configuration option (default 86400000ms / 24 hours) - Implemented scheduled cleanup using Camel's ScheduledExecutorService - Added DEBUG logging for evictions with task ID and age - Updated documentation in docling-component.adoc - Added unit tests for TTL eviction behavior Signed-off-by: Andrea Cosentino <[email protected]> --- .bob/notes/pending-notes.txt | 13 ++ .mcp.json | 20 +++ Apache_Camel_Roadmap_2026_2027.pptx | Bin 0 -> 39338 bytes .../docling/DoclingComponentConfigurer.java | 6 + .../docling/DoclingConfigurationConfigurer.java | 6 + .../docling/DoclingEndpointConfigurer.java | 6 + .../docling/DoclingEndpointUriFactory.java | 3 +- .../apache/camel/component/docling/docling.json | 160 +++++++++++---------- .../src/main/docs/docling-component.adoc | 4 + .../camel/component/docling/AsyncTaskEntry.java | 54 +++++++ .../camel/component/docling/DoclingComponent.java | 84 ++++++++++- .../component/docling/DoclingConfiguration.java | 13 ++ .../camel/component/docling/DoclingProducer.java | 15 +- .../component/docling/DoclingAsyncTaskTtlTest.java | 131 +++++++++++++++++ 14 files changed, 423 insertions(+), 92 deletions(-) diff --git a/.bob/notes/pending-notes.txt b/.bob/notes/pending-notes.txt new file mode 100644 index 000000000000..86143db56d3c --- /dev/null +++ b/.bob/notes/pending-notes.txt @@ -0,0 +1,13 @@ +{"id":"cb1e2340-5547-4fca-bfa3-0526361eb072","ts":"2026-05-11T12:26:20.434Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/AsyncTaskEntry.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"4fe29d55-3252-4cc8-820c-de883341efe1","ts":"2026-05-11T12:26:30.105Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"6c780401-34a4-4f39-8103-219115a7c643","ts":"2026-05-11T12:26:35.422Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"4a8ce898-0b4f-493b-8470-8237082830cb","ts":"2026-05-11T12:26:42.969Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"71950004-f88e-4b52-bbc4-1229a2f59555","ts":"2026-05-11T12:26:50.025Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"9f91ebd4-29c9-4d65-bb75-855f3b430c04","ts":"2026-05-11T12:26:57.509Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"d44ebfdf-22c1-4b7e-a1a1-aa84a33a0047","ts":"2026-05-11T12:27:09.030Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"58cfe263-be83-49b2-b19b-99fb333c1349","ts":"2026-05-11T12:27:14.746Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"82d06b45-dfc7-41a2-8218-14464b9f1402","ts":"2026-05-11T12:27:23.361Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"d2f554b2-ccbe-448b-ba46-46a15c817266","ts":"2026-05-11T12:27:30.389Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"9baf2bf9-27ed-4716-bc22-20ec5d32cdc8","ts":"2026-05-11T12:27:54.122Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingAsyncTaskTtlTest.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"f031c280-334d-4caf-9bd3-2d5472f34f3c","ts":"2026-05-11T12:28:17.171Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} +{"id":"a548caef-7885-4263-b255-d912720de400","ts":"2026-05-11T12:30:25.421Z","path":"/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingAsyncTaskTtlTest.java","version":"1.0.0","taskID":"03972b0b-1027-4c47-b01d-e42fe0a1413e"} diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 000000000000..a7e0b0709a28 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,20 @@ +{ + "mcpServers": { + "camel-compressed": { + "type": "stdio", + "command": "java", + "args": [ + "-jar", + "/home/oscerd/workspace/misc/mcp-tool-compressor/mcp-tool-compressor-cli/target/mcp-tool-compressor-cli-0.1.0-SNAPSHOT.jar", + "proxy", + "--command", + "java", + "--args", + "-jar /home/oscerd/.m2/repository/org/apache/camel/camel-jbang-mcp/4.19.0-SNAPSHOT/camel-jbang-mcp-4.19.0-SNAPSHOT-runner.jar", + "--budget", + "2000" + ], + "env": {} + } + } +} \ No newline at end of file diff --git a/Apache_Camel_Roadmap_2026_2027.pptx b/Apache_Camel_Roadmap_2026_2027.pptx new file mode 100644 index 000000000000..1f6228338e7f Binary files /dev/null and b/Apache_Camel_Roadmap_2026_2027.pptx differ diff --git a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java index 06f2b12a0327..d55a7a8724ac 100644 --- a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java +++ b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java @@ -36,6 +36,8 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "apiKeyHeader": getOrCreateConfiguration(target).setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true; case "asyncpollinterval": case "asyncPollInterval": getOrCreateConfiguration(target).setAsyncPollInterval(property(camelContext, long.class, value)); return true; + case "asynctaskttl": + case "asyncTaskTtl": getOrCreateConfiguration(target).setAsyncTaskTtl(property(camelContext, long.class, value)); return true; case "asynctimeout": case "asyncTimeout": getOrCreateConfiguration(target).setAsyncTimeout(property(camelContext, long.class, value)); return true; case "authenticationscheme": @@ -144,6 +146,8 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "apiKeyHeader": return java.lang.String.class; case "asyncpollinterval": case "asyncPollInterval": return long.class; + case "asynctaskttl": + case "asyncTaskTtl": return long.class; case "asynctimeout": case "asyncTimeout": return long.class; case "authenticationscheme": @@ -253,6 +257,8 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "apiKeyHeader": return getOrCreateConfiguration(target).getApiKeyHeader(); case "asyncpollinterval": case "asyncPollInterval": return getOrCreateConfiguration(target).getAsyncPollInterval(); + case "asynctaskttl": + case "asyncTaskTtl": return getOrCreateConfiguration(target).getAsyncTaskTtl(); case "asynctimeout": case "asyncTimeout": return getOrCreateConfiguration(target).getAsyncTimeout(); case "authenticationscheme": diff --git a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java index 0cc0f033b1d8..44c19bdc57bb 100644 --- a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java +++ b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java @@ -29,6 +29,8 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "apiKeyHeader": target.setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true; case "asyncpollinterval": case "asyncPollInterval": target.setAsyncPollInterval(property(camelContext, long.class, value)); return true; + case "asynctaskttl": + case "asyncTaskTtl": target.setAsyncTaskTtl(property(camelContext, long.class, value)); return true; case "asynctimeout": case "asyncTimeout": target.setAsyncTimeout(property(camelContext, long.class, value)); return true; case "authenticationscheme": @@ -132,6 +134,8 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "apiKeyHeader": return java.lang.String.class; case "asyncpollinterval": case "asyncPollInterval": return long.class; + case "asynctaskttl": + case "asyncTaskTtl": return long.class; case "asynctimeout": case "asyncTimeout": return long.class; case "authenticationscheme": @@ -236,6 +240,8 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "apiKeyHeader": return target.getApiKeyHeader(); case "asyncpollinterval": case "asyncPollInterval": return target.getAsyncPollInterval(); + case "asynctaskttl": + case "asyncTaskTtl": return target.getAsyncTaskTtl(); case "asynctimeout": case "asyncTimeout": return target.getAsyncTimeout(); case "authenticationscheme": diff --git a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java index 47ca22efb0f5..b671a1aa3145 100644 --- a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java +++ b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java @@ -29,6 +29,8 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "apiKeyHeader": target.getConfiguration().setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true; case "asyncpollinterval": case "asyncPollInterval": target.getConfiguration().setAsyncPollInterval(property(camelContext, long.class, value)); return true; + case "asynctaskttl": + case "asyncTaskTtl": target.getConfiguration().setAsyncTaskTtl(property(camelContext, long.class, value)); return true; case "asynctimeout": case "asyncTimeout": target.getConfiguration().setAsyncTimeout(property(camelContext, long.class, value)); return true; case "authenticationscheme": @@ -134,6 +136,8 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "apiKeyHeader": return java.lang.String.class; case "asyncpollinterval": case "asyncPollInterval": return long.class; + case "asynctaskttl": + case "asyncTaskTtl": return long.class; case "asynctimeout": case "asyncTimeout": return long.class; case "authenticationscheme": @@ -240,6 +244,8 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "apiKeyHeader": return target.getConfiguration().getApiKeyHeader(); case "asyncpollinterval": case "asyncPollInterval": return target.getConfiguration().getAsyncPollInterval(); + case "asynctaskttl": + case "asyncTaskTtl": return target.getConfiguration().getAsyncTaskTtl(); case "asynctimeout": case "asyncTimeout": return target.getConfiguration().getAsyncTimeout(); case "authenticationscheme": diff --git a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java index dad866ccfdb7..eb05c59aa55c 100644 --- a/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java +++ b/components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java @@ -23,10 +23,11 @@ public class DoclingEndpointUriFactory extends org.apache.camel.support.componen private static final Set<String> SECRET_PROPERTY_NAMES; private static final Map<String, String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(51); + Set<String> props = new HashSet<>(52); props.add("abortOnError"); props.add("apiKeyHeader"); props.add("asyncPollInterval"); + props.add("asyncTaskTtl"); props.add("asyncTimeout"); props.add("authenticationScheme"); props.add("authenticationToken"); diff --git a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json index c5cad438501d..7d7c78c7d667 100644 --- a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json +++ b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json @@ -36,46 +36,47 @@ "useDoclingServe": { "index": 9, "kind": "property", "displayName": "Use Docling Serve", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use docling-serve API instead of CLI command" }, "abortOnError": { "index": 10, "kind": "property", "displayName": "Abort On Error", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Abort processing on error" }, "asyncPollInterval": { "index": 11, "kind": "property", "displayName": "Async Poll Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Polling interval for async conversion status in millise [...] - "asyncTimeout": { "index": 12, "kind": "property", "displayName": "Async Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for async conversion completion in millisec [...] - "autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching [...] - "doclingCommand": { "index": 14, "kind": "property", "displayName": "Docling Command", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Path to Docling Python executable or command" }, - "doCodeEnrichment": { "index": 15, "kind": "property", "displayName": "Do Code Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable code enrichment in document processing" }, - "documentTimeout": { "index": 16, "kind": "property", "displayName": "Document Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Document processing timeout in seconds" }, - "doFormulaEnrichment": { "index": 17, "kind": "property", "displayName": "Do Formula Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable formula enrichment in document [...] - "doOcr": { "index": 18, "kind": "property", "displayName": "Do Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable OCR processing in docling-serve API mode. When not set, the [...] - "doPictureClassification": { "index": 19, "kind": "property", "displayName": "Do Picture Classification", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture classification [...] - "doPictureDescription": { "index": 20, "kind": "property", "displayName": "Do Picture Description", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture description generati [...] - "doTableStructure": { "index": 21, "kind": "property", "displayName": "Do Table Structure", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table structure recognition" }, - "forceOcr": { "index": 22, "kind": "property", "displayName": "Force Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Force OCR processing even for digital documents" }, - "imageExportMode": { "index": 23, "kind": "property", "displayName": "Image Export Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Image export mode for referenced images" }, - "imagesScale": { "index": 24, "kind": "property", "displayName": "Images Scale", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Scale factor for exported images" }, - "includeImages": { "index": 25, "kind": "property", "displayName": "Include Images", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include images in the conversion output" }, - "mdPageBreakPlaceholder": { "index": 26, "kind": "property", "displayName": "Md Page Break Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Placeholder string for page breaks in markdown output" }, - "ocrEngine": { "index": 27, "kind": "property", "displayName": "Ocr Engine", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OCR engine to use" }, - "pdfBackend": { "index": 28, "kind": "property", "displayName": "Pdf Backend", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "PDF parsing backend" }, - "pipeline": { "index": 29, "kind": "property", "displayName": "Pipeline", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Processing pipeline to use" }, - "processTimeout": { "index": 30, "kind": "property", "displayName": "Process Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Timeout for Docling process execution in milliseconds" }, - "tableCellMatching": { "index": 31, "kind": "property", "displayName": "Table Cell Matching", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table cell matching post-processing" }, - "tableMode": { "index": 32, "kind": "property", "displayName": "Table Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Table structure recognition mode" }, - "useAsyncMode": { "index": 33, "kind": "property", "displayName": "Use Async Mode", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use asynchronous conversion mode (docling-serve API only)" }, - "workingDirectory": { "index": 34, "kind": "property", "displayName": "Working Directory", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Working directory for Docling execution" }, - "batchFailOnFirstError": { "index": 35, "kind": "property", "displayName": "Batch Fail On First Error", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Fail entire batch on first error (true) or conti [...] - "batchParallelism": { "index": 36, "kind": "property", "displayName": "Batch Parallelism", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 4, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of parallel threads for batch processing" }, - "batchSize": { "index": 37, "kind": "property", "displayName": "Batch Size", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of documents to submit per sub-batch. Documents are partitioned into sub-b [...] - "batchTimeout": { "index": 38, "kind": "property", "displayName": "Batch Timeout", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for batch completion in milliseconds" }, - "splitBatchResults": { "index": 39, "kind": "property", "displayName": "Split Batch Results", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Split batch results into individual exchanges (one per do [...] - "chunkingIncludeRawText": { "index": 40, "kind": "property", "displayName": "Chunking Include Raw Text", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw text in chunk output" }, - "chunkingMaxTokens": { "index": 41, "kind": "property", "displayName": "Chunking Max Tokens", "group": "chunking", "label": "chunking", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum number of tokens per chunk for hybrid chunking" }, - "chunkingMergePeers": { "index": 42, "kind": "property", "displayName": "Chunking Merge Peers", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Whether to merge peer chunks in hybrid c [...] - "chunkingTokenizer": { "index": 43, "kind": "property", "displayName": "Chunking Tokenizer", "group": "chunking", "label": "chunking", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Tokenizer model for hybrid chunking (e.g. sentence-transformers\/al [...] - "chunkingUseMarkdownTables": { "index": 44, "kind": "property", "displayName": "Chunking Use Markdown Tables", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use markdown format for [...] - "includeMetadataInHeaders": { "index": 45, "kind": "property", "displayName": "Include Metadata In Headers", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include metadata in message headers w [...] - "includeRawMetadata": { "index": 46, "kind": "property", "displayName": "Include Raw Metadata", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw metadata as returned by the parser" }, - "apiKeyHeader": { "index": 47, "kind": "property", "displayName": "Api Key Header", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "X-API-Key", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Header name for API key authentication" }, - "authenticationScheme": { "index": 48, "kind": "property", "displayName": "Authentication Scheme", "group": "security", "label": "security", "required": false, "type": "enum", "javaType": "org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", "BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "NONE", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configuration [...] - "authenticationToken": { "index": 49, "kind": "property", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API [...] - "maxFileSize": { "index": 50, "kind": "property", "displayName": "Max File Size", "group": "security", "label": "security", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 52428800, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum file size in bytes for processing" }, - "oauthProfile": { "index": 51, "kind": "property", "displayName": "Oauth Profile", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OAuth profile name for obtaining an access token via the OAuth 2.0 Client Cre [...] + "asyncTaskTtl": { "index": 12, "kind": "property", "displayName": "Async Task Ttl", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 86400000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Time-to-live for pending async conversion tasks in millisecon [...] + "asyncTimeout": { "index": 13, "kind": "property", "displayName": "Async Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for async conversion completion in millisec [...] + "autowiredEnabled": { "index": 14, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching [...] + "doclingCommand": { "index": 15, "kind": "property", "displayName": "Docling Command", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Path to Docling Python executable or command" }, + "doCodeEnrichment": { "index": 16, "kind": "property", "displayName": "Do Code Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable code enrichment in document processing" }, + "documentTimeout": { "index": 17, "kind": "property", "displayName": "Document Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Document processing timeout in seconds" }, + "doFormulaEnrichment": { "index": 18, "kind": "property", "displayName": "Do Formula Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable formula enrichment in document [...] + "doOcr": { "index": 19, "kind": "property", "displayName": "Do Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable OCR processing in docling-serve API mode. When not set, the [...] + "doPictureClassification": { "index": 20, "kind": "property", "displayName": "Do Picture Classification", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture classification [...] + "doPictureDescription": { "index": 21, "kind": "property", "displayName": "Do Picture Description", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture description generati [...] + "doTableStructure": { "index": 22, "kind": "property", "displayName": "Do Table Structure", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table structure recognition" }, + "forceOcr": { "index": 23, "kind": "property", "displayName": "Force Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Force OCR processing even for digital documents" }, + "imageExportMode": { "index": 24, "kind": "property", "displayName": "Image Export Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Image export mode for referenced images" }, + "imagesScale": { "index": 25, "kind": "property", "displayName": "Images Scale", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Scale factor for exported images" }, + "includeImages": { "index": 26, "kind": "property", "displayName": "Include Images", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include images in the conversion output" }, + "mdPageBreakPlaceholder": { "index": 27, "kind": "property", "displayName": "Md Page Break Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Placeholder string for page breaks in markdown output" }, + "ocrEngine": { "index": 28, "kind": "property", "displayName": "Ocr Engine", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OCR engine to use" }, + "pdfBackend": { "index": 29, "kind": "property", "displayName": "Pdf Backend", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "PDF parsing backend" }, + "pipeline": { "index": 30, "kind": "property", "displayName": "Pipeline", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Processing pipeline to use" }, + "processTimeout": { "index": 31, "kind": "property", "displayName": "Process Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Timeout for Docling process execution in milliseconds" }, + "tableCellMatching": { "index": 32, "kind": "property", "displayName": "Table Cell Matching", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table cell matching post-processing" }, + "tableMode": { "index": 33, "kind": "property", "displayName": "Table Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Table structure recognition mode" }, + "useAsyncMode": { "index": 34, "kind": "property", "displayName": "Use Async Mode", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use asynchronous conversion mode (docling-serve API only)" }, + "workingDirectory": { "index": 35, "kind": "property", "displayName": "Working Directory", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Working directory for Docling execution" }, + "batchFailOnFirstError": { "index": 36, "kind": "property", "displayName": "Batch Fail On First Error", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Fail entire batch on first error (true) or conti [...] + "batchParallelism": { "index": 37, "kind": "property", "displayName": "Batch Parallelism", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 4, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of parallel threads for batch processing" }, + "batchSize": { "index": 38, "kind": "property", "displayName": "Batch Size", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of documents to submit per sub-batch. Documents are partitioned into sub-b [...] + "batchTimeout": { "index": 39, "kind": "property", "displayName": "Batch Timeout", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for batch completion in milliseconds" }, + "splitBatchResults": { "index": 40, "kind": "property", "displayName": "Split Batch Results", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Split batch results into individual exchanges (one per do [...] + "chunkingIncludeRawText": { "index": 41, "kind": "property", "displayName": "Chunking Include Raw Text", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw text in chunk output" }, + "chunkingMaxTokens": { "index": 42, "kind": "property", "displayName": "Chunking Max Tokens", "group": "chunking", "label": "chunking", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum number of tokens per chunk for hybrid chunking" }, + "chunkingMergePeers": { "index": 43, "kind": "property", "displayName": "Chunking Merge Peers", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Whether to merge peer chunks in hybrid c [...] + "chunkingTokenizer": { "index": 44, "kind": "property", "displayName": "Chunking Tokenizer", "group": "chunking", "label": "chunking", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Tokenizer model for hybrid chunking (e.g. sentence-transformers\/al [...] + "chunkingUseMarkdownTables": { "index": 45, "kind": "property", "displayName": "Chunking Use Markdown Tables", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use markdown format for [...] + "includeMetadataInHeaders": { "index": 46, "kind": "property", "displayName": "Include Metadata In Headers", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include metadata in message headers w [...] + "includeRawMetadata": { "index": 47, "kind": "property", "displayName": "Include Raw Metadata", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw metadata as returned by the parser" }, + "apiKeyHeader": { "index": 48, "kind": "property", "displayName": "Api Key Header", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "X-API-Key", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Header name for API key authentication" }, + "authenticationScheme": { "index": 49, "kind": "property", "displayName": "Authentication Scheme", "group": "security", "label": "security", "required": false, "type": "enum", "javaType": "org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", "BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "NONE", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configuration [...] + "authenticationToken": { "index": 50, "kind": "property", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API [...] + "maxFileSize": { "index": 51, "kind": "property", "displayName": "Max File Size", "group": "security", "label": "security", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 52428800, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum file size in bytes for processing" }, + "oauthProfile": { "index": 52, "kind": "property", "displayName": "Oauth Profile", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OAuth profile name for obtaining an access token via the OAuth 2.0 Client Cre [...] }, "headers": { "CamelDoclingOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "DoclingOperations", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform", "constantName": "org.apache.camel.component.docling.DoclingHeaders#OPERATION" }, @@ -123,44 +124,45 @@ "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] "abortOnError": { "index": 10, "kind": "parameter", "displayName": "Abort On Error", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Abort processing on error" }, "asyncPollInterval": { "index": 11, "kind": "parameter", "displayName": "Async Poll Interval", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Polling interval for async conversion status in millis [...] - "asyncTimeout": { "index": 12, "kind": "parameter", "displayName": "Async Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for async conversion completion in millise [...] - "doclingCommand": { "index": 13, "kind": "parameter", "displayName": "Docling Command", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Path to Docling Python executable or command" }, - "doCodeEnrichment": { "index": 14, "kind": "parameter", "displayName": "Do Code Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable code enrichment in document processing" }, - "documentTimeout": { "index": 15, "kind": "parameter", "displayName": "Document Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Document processing timeout in seconds" }, - "doFormulaEnrichment": { "index": 16, "kind": "parameter", "displayName": "Do Formula Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable formula enrichment in documen [...] - "doOcr": { "index": 17, "kind": "parameter", "displayName": "Do Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable OCR processing in docling-serve API mode. When not set, th [...] - "doPictureClassification": { "index": 18, "kind": "parameter", "displayName": "Do Picture Classification", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture classificatio [...] - "doPictureDescription": { "index": 19, "kind": "parameter", "displayName": "Do Picture Description", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture description generat [...] - "doTableStructure": { "index": 20, "kind": "parameter", "displayName": "Do Table Structure", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table structure recognition" }, - "forceOcr": { "index": 21, "kind": "parameter", "displayName": "Force Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Force OCR processing even for digital documents" }, - "imageExportMode": { "index": 22, "kind": "parameter", "displayName": "Image Export Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Image export mode for referenced images" }, - "imagesScale": { "index": 23, "kind": "parameter", "displayName": "Images Scale", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Scale factor for exported images" }, - "includeImages": { "index": 24, "kind": "parameter", "displayName": "Include Images", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include images in the conversion output" }, - "mdPageBreakPlaceholder": { "index": 25, "kind": "parameter", "displayName": "Md Page Break Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Placeholder string for page breaks in markdown output" }, - "ocrEngine": { "index": 26, "kind": "parameter", "displayName": "Ocr Engine", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OCR engine to use" }, - "pdfBackend": { "index": 27, "kind": "parameter", "displayName": "Pdf Backend", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "PDF parsing backend" }, - "pipeline": { "index": 28, "kind": "parameter", "displayName": "Pipeline", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Processing pipeline to use" }, - "processTimeout": { "index": 29, "kind": "parameter", "displayName": "Process Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Timeout for Docling process execution in milliseconds" }, - "tableCellMatching": { "index": 30, "kind": "parameter", "displayName": "Table Cell Matching", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table cell matching post-processing" }, - "tableMode": { "index": 31, "kind": "parameter", "displayName": "Table Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Table structure recognition mode" }, - "useAsyncMode": { "index": 32, "kind": "parameter", "displayName": "Use Async Mode", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use asynchronous conversion mode (docling-serve API only)" }, - "workingDirectory": { "index": 33, "kind": "parameter", "displayName": "Working Directory", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Working directory for Docling execution" }, - "batchFailOnFirstError": { "index": 34, "kind": "parameter", "displayName": "Batch Fail On First Error", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Fail entire batch on first error (true) or cont [...] - "batchParallelism": { "index": 35, "kind": "parameter", "displayName": "Batch Parallelism", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 4, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of parallel threads for batch processing" }, - "batchSize": { "index": 36, "kind": "parameter", "displayName": "Batch Size", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of documents to submit per sub-batch. Documents are partitioned into sub- [...] - "batchTimeout": { "index": 37, "kind": "parameter", "displayName": "Batch Timeout", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for batch completion in milliseconds" }, - "splitBatchResults": { "index": 38, "kind": "parameter", "displayName": "Split Batch Results", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Split batch results into individual exchanges (one per d [...] - "chunkingIncludeRawText": { "index": 39, "kind": "parameter", "displayName": "Chunking Include Raw Text", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw text in chunk output" }, - "chunkingMaxTokens": { "index": 40, "kind": "parameter", "displayName": "Chunking Max Tokens", "group": "chunking", "label": "chunking", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum number of tokens per chunk for hybrid chunking" }, - "chunkingMergePeers": { "index": 41, "kind": "parameter", "displayName": "Chunking Merge Peers", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Whether to merge peer chunks in hybrid [...] - "chunkingTokenizer": { "index": 42, "kind": "parameter", "displayName": "Chunking Tokenizer", "group": "chunking", "label": "chunking", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Tokenizer model for hybrid chunking (e.g. sentence-transformers\/a [...] - "chunkingUseMarkdownTables": { "index": 43, "kind": "parameter", "displayName": "Chunking Use Markdown Tables", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use markdown format for [...] - "includeMetadataInHeaders": { "index": 44, "kind": "parameter", "displayName": "Include Metadata In Headers", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include metadata in message headers [...] - "includeRawMetadata": { "index": 45, "kind": "parameter", "displayName": "Include Raw Metadata", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw metadata as returned by the parser" }, - "apiKeyHeader": { "index": 46, "kind": "parameter", "displayName": "Api Key Header", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "X-API-Key", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Header name for API key authentication" }, - "authenticationScheme": { "index": 47, "kind": "parameter", "displayName": "Authentication Scheme", "group": "security", "label": "security", "required": false, "type": "enum", "javaType": "org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", "BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "NONE", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configuratio [...] - "authenticationToken": { "index": 48, "kind": "parameter", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve AP [...] - "maxFileSize": { "index": 49, "kind": "parameter", "displayName": "Max File Size", "group": "security", "label": "security", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 52428800, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum file size in bytes for processing" }, - "oauthProfile": { "index": 50, "kind": "parameter", "displayName": "Oauth Profile", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OAuth profile name for obtaining an access token via the OAuth 2.0 Client Cr [...] + "asyncTaskTtl": { "index": 12, "kind": "parameter", "displayName": "Async Task Ttl", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 86400000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Time-to-live for pending async conversion tasks in milliseco [...] + "asyncTimeout": { "index": 13, "kind": "parameter", "displayName": "Async Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for async conversion completion in millise [...] + "doclingCommand": { "index": 14, "kind": "parameter", "displayName": "Docling Command", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Path to Docling Python executable or command" }, + "doCodeEnrichment": { "index": 15, "kind": "parameter", "displayName": "Do Code Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable code enrichment in document processing" }, + "documentTimeout": { "index": 16, "kind": "parameter", "displayName": "Document Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Document processing timeout in seconds" }, + "doFormulaEnrichment": { "index": 17, "kind": "parameter", "displayName": "Do Formula Enrichment", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable formula enrichment in documen [...] + "doOcr": { "index": 18, "kind": "parameter", "displayName": "Do Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable OCR processing in docling-serve API mode. When not set, th [...] + "doPictureClassification": { "index": 19, "kind": "parameter", "displayName": "Do Picture Classification", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture classificatio [...] + "doPictureDescription": { "index": 20, "kind": "parameter", "displayName": "Do Picture Description", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable picture description generat [...] + "doTableStructure": { "index": 21, "kind": "parameter", "displayName": "Do Table Structure", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table structure recognition" }, + "forceOcr": { "index": 22, "kind": "parameter", "displayName": "Force Ocr", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Force OCR processing even for digital documents" }, + "imageExportMode": { "index": 23, "kind": "parameter", "displayName": "Image Export Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Image export mode for referenced images" }, + "imagesScale": { "index": 24, "kind": "parameter", "displayName": "Images Scale", "group": "advanced", "label": "advanced", "required": false, "type": "number", "javaType": "java.lang.Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Scale factor for exported images" }, + "includeImages": { "index": 25, "kind": "parameter", "displayName": "Include Images", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include images in the conversion output" }, + "mdPageBreakPlaceholder": { "index": 26, "kind": "parameter", "displayName": "Md Page Break Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Placeholder string for page breaks in markdown output" }, + "ocrEngine": { "index": 27, "kind": "parameter", "displayName": "Ocr Engine", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OCR engine to use" }, + "pdfBackend": { "index": 28, "kind": "parameter", "displayName": "Pdf Backend", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "PDF parsing backend" }, + "pipeline": { "index": 29, "kind": "parameter", "displayName": "Pipeline", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Processing pipeline to use" }, + "processTimeout": { "index": 30, "kind": "parameter", "displayName": "Process Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Timeout for Docling process execution in milliseconds" }, + "tableCellMatching": { "index": 31, "kind": "parameter", "displayName": "Table Cell Matching", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Enable table cell matching post-processing" }, + "tableMode": { "index": 32, "kind": "parameter", "displayName": "Table Mode", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Table structure recognition mode" }, + "useAsyncMode": { "index": 33, "kind": "parameter", "displayName": "Use Async Mode", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use asynchronous conversion mode (docling-serve API only)" }, + "workingDirectory": { "index": 34, "kind": "parameter", "displayName": "Working Directory", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Working directory for Docling execution" }, + "batchFailOnFirstError": { "index": 35, "kind": "parameter", "displayName": "Batch Fail On First Error", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Fail entire batch on first error (true) or cont [...] + "batchParallelism": { "index": 36, "kind": "parameter", "displayName": "Batch Parallelism", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 4, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of parallel threads for batch processing" }, + "batchSize": { "index": 37, "kind": "parameter", "displayName": "Batch Size", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Number of documents to submit per sub-batch. Documents are partitioned into sub- [...] + "batchTimeout": { "index": 38, "kind": "parameter", "displayName": "Batch Timeout", "group": "batch", "label": "batch", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum time to wait for batch completion in milliseconds" }, + "splitBatchResults": { "index": 39, "kind": "parameter", "displayName": "Split Batch Results", "group": "batch", "label": "batch", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Split batch results into individual exchanges (one per d [...] + "chunkingIncludeRawText": { "index": 40, "kind": "parameter", "displayName": "Chunking Include Raw Text", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw text in chunk output" }, + "chunkingMaxTokens": { "index": 41, "kind": "parameter", "displayName": "Chunking Max Tokens", "group": "chunking", "label": "chunking", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum number of tokens per chunk for hybrid chunking" }, + "chunkingMergePeers": { "index": 42, "kind": "parameter", "displayName": "Chunking Merge Peers", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Whether to merge peer chunks in hybrid [...] + "chunkingTokenizer": { "index": 43, "kind": "parameter", "displayName": "Chunking Tokenizer", "group": "chunking", "label": "chunking", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Tokenizer model for hybrid chunking (e.g. sentence-transformers\/a [...] + "chunkingUseMarkdownTables": { "index": 44, "kind": "parameter", "displayName": "Chunking Use Markdown Tables", "group": "chunking", "label": "chunking", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Use markdown format for [...] + "includeMetadataInHeaders": { "index": 45, "kind": "parameter", "displayName": "Include Metadata In Headers", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include metadata in message headers [...] + "includeRawMetadata": { "index": 46, "kind": "parameter", "displayName": "Include Raw Metadata", "group": "metadata", "label": "metadata", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include raw metadata as returned by the parser" }, + "apiKeyHeader": { "index": 47, "kind": "parameter", "displayName": "Api Key Header", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "X-API-Key", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Header name for API key authentication" }, + "authenticationScheme": { "index": 48, "kind": "parameter", "displayName": "Authentication Scheme", "group": "security", "label": "security", "required": false, "type": "enum", "javaType": "org.apache.camel.component.docling.AuthenticationScheme", "enum": [ "NONE", "BEARER", "API_KEY" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "NONE", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configuratio [...] + "authenticationToken": { "index": 49, "kind": "parameter", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "security": "secret", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve AP [...] + "maxFileSize": { "index": 50, "kind": "parameter", "displayName": "Max File Size", "group": "security", "label": "security", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 52428800, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum file size in bytes for processing" }, + "oauthProfile": { "index": 51, "kind": "parameter", "displayName": "Oauth Profile", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "OAuth profile name for obtaining an access token via the OAuth 2.0 Client Cr [...] } } diff --git a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc index 68595ddcdac4..c96d3448f478 100644 --- a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc +++ b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc @@ -2514,6 +2514,10 @@ When using docling-serve API mode, the component uses the https://github.com/doc | 300000 | Maximum time to wait for async conversion completion in milliseconds (5 minutes). +| `asyncTaskTtl` +| 86400000 +| Time-to-live for pending async conversion tasks in milliseconds (24 hours). Tasks older than this will be automatically evicted from memory to prevent leaks. A background cleanup task runs periodically to remove expired entries. + |=== IMPORTANT: The default `processTimeout` of 30 seconds may not be sufficient for complex PDF documents, especially when OCR or enrichment options are enabled. For production use with PDF files, consider increasing `processTimeout` to at least 120000 (2 minutes). diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/AsyncTaskEntry.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/AsyncTaskEntry.java new file mode 100644 index 000000000000..62888fa5597d --- /dev/null +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/AsyncTaskEntry.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.docling; + +import java.util.concurrent.CompletableFuture; + +import ai.docling.serve.api.convert.response.ConvertDocumentResponse; + +/** + * Wrapper for async conversion tasks that tracks creation timestamp for TTL-based cleanup. + */ +final class AsyncTaskEntry { + + private final String taskId; + private final CompletableFuture<ConvertDocumentResponse> future; + private final long createdAtMs; + + AsyncTaskEntry(String taskId, CompletableFuture<ConvertDocumentResponse> future) { + this.taskId = taskId; + this.future = future; + this.createdAtMs = System.currentTimeMillis(); + } + + public String getTaskId() { + return taskId; + } + + public CompletableFuture<ConvertDocumentResponse> getFuture() { + return future; + } + + public long getCreatedAtMs() { + return createdAtMs; + } + + public long getAgeMs() { + return System.currentTimeMillis() - createdAtMs; + } + +} diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java index 048eace5bc73..e06f31db730a 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingComponent.java @@ -16,17 +16,21 @@ */ package org.apache.camel.component.docling; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import ai.docling.serve.api.convert.response.ConvertDocumentResponse; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Component; import org.apache.camel.support.DefaultComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Component for integrating with Docling document processing library. @@ -34,13 +38,16 @@ import org.apache.camel.support.DefaultComponent; @Component("docling") public class DoclingComponent extends DefaultComponent { + private static final Logger LOG = LoggerFactory.getLogger(DoclingComponent.class); + @Metadata DoclingConfiguration configuration; // Shared across all producers so that SUBMIT_ASYNC_CONVERSION and CHECK_CONVERSION_STATUS // (which may resolve to different endpoints/producers) can see each other's tasks. - private final Map<String, CompletableFuture<ConvertDocumentResponse>> pendingAsyncTasks = new ConcurrentHashMap<>(); + private final Map<String, AsyncTaskEntry> pendingAsyncTasks = new ConcurrentHashMap<>(); private final AtomicLong taskIdCounter = new AtomicLong(); + private ScheduledExecutorService cleanupExecutor; public DoclingComponent() { this(null); @@ -51,6 +58,26 @@ public class DoclingComponent extends DefaultComponent { this.configuration = new DoclingConfiguration(); } + @Override + protected void doStart() throws Exception { + super.doStart(); + + // Start scheduled cleanup task for expired async tasks + long ttl = configuration.getAsyncTaskTtl(); + long cleanupInterval = Math.max(ttl / 10, 60000); // Run cleanup every 10% of TTL, minimum 1 minute + + cleanupExecutor = getCamelContext().getExecutorServiceManager() + .newScheduledThreadPool(this, "DoclingAsyncTaskCleanup", 1); + + cleanupExecutor.scheduleWithFixedDelay( + this::cleanupExpiredTasks, + cleanupInterval, + cleanupInterval, + TimeUnit.MILLISECONDS); + + LOG.info("Started async task cleanup with TTL={}ms, cleanup interval={}ms", ttl, cleanupInterval); + } + @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { DoclingConfiguration config = this.configuration.copy(); @@ -70,7 +97,7 @@ public class DoclingComponent extends DefaultComponent { this.configuration = configuration; } - Map<String, CompletableFuture<ConvertDocumentResponse>> getPendingAsyncTasks() { + Map<String, AsyncTaskEntry> getPendingAsyncTasks() { return pendingAsyncTasks; } @@ -78,9 +105,56 @@ public class DoclingComponent extends DefaultComponent { return taskIdCounter; } + /** + * Cleanup expired async tasks based on configured TTL. Runs periodically in background to prevent memory leaks. + */ + private void cleanupExpiredTasks() { + if (pendingAsyncTasks.isEmpty()) { + return; + } + + long ttl = configuration.getAsyncTaskTtl(); + long now = System.currentTimeMillis(); + List<String> expiredTaskIds = new ArrayList<>(); + + // Identify expired tasks + for (Map.Entry<String, AsyncTaskEntry> entry : pendingAsyncTasks.entrySet()) { + AsyncTaskEntry taskEntry = entry.getValue(); + long age = now - taskEntry.getCreatedAtMs(); + + if (age > ttl) { + expiredTaskIds.add(entry.getKey()); + } + } + + // Remove expired tasks + for (String taskId : expiredTaskIds) { + AsyncTaskEntry removed = pendingAsyncTasks.remove(taskId); + if (removed != null) { + // Cancel the future if still pending + removed.getFuture().cancel(true); + LOG.debug("Evicted expired async task: {} (age: {}ms, TTL: {}ms)", + taskId, removed.getAgeMs(), ttl); + } + } + + if (!expiredTaskIds.isEmpty()) { + LOG.info("Cleaned up {} expired async tasks (current map size: {})", + expiredTaskIds.size(), pendingAsyncTasks.size()); + } + } + @Override protected void doStop() throws Exception { - pendingAsyncTasks.forEach((id, future) -> future.cancel(true)); + // Shutdown cleanup executor + if (cleanupExecutor != null) { + getCamelContext().getExecutorServiceManager().shutdownGraceful(cleanupExecutor); + cleanupExecutor = null; + LOG.info("Stopped async task cleanup executor"); + } + + // Cancel and clear all pending tasks + pendingAsyncTasks.forEach((id, entry) -> entry.getFuture().cancel(true)); pendingAsyncTasks.clear(); super.doStop(); } diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java index 154aa50245c8..3a3f3cab6af8 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingConfiguration.java @@ -112,6 +112,11 @@ public class DoclingConfiguration implements Cloneable { @Metadata(description = "Maximum time to wait for async conversion completion in milliseconds", defaultValue = "300000") private long asyncTimeout = 300000; // 5 minutes + @UriParam(label = "advanced") + @Metadata(description = "Time-to-live for pending async conversion tasks in milliseconds. Tasks older than this will be evicted from memory to prevent leaks.", + defaultValue = "86400000") + private long asyncTaskTtl = 86400000; // 24 hours + @UriParam(label = "batch") @Metadata(description = "Number of documents to submit per sub-batch. Documents are partitioned into sub-batches of this size" + " and each sub-batch is processed before starting the next one. Within each sub-batch, up to" @@ -630,6 +635,14 @@ public class DoclingConfiguration implements Cloneable { this.chunkingUseMarkdownTables = chunkingUseMarkdownTables; } + public long getAsyncTaskTtl() { + return asyncTaskTtl; + } + + public void setAsyncTaskTtl(long asyncTaskTtl) { + this.asyncTaskTtl = asyncTaskTtl; + } + public DoclingConfiguration copy() { try { return (DoclingConfiguration) super.clone(); diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java index 3e08671390ec..4129db3858a0 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingProducer.java @@ -159,7 +159,7 @@ public class DoclingProducer extends DefaultProducer { private DoclingConfiguration configuration; private DoclingServeApi doclingServeApi; private ObjectMapper objectMapper; - private Map<String, CompletableFuture<ConvertDocumentResponse>> pendingAsyncTasks; + private Map<String, AsyncTaskEntry> pendingAsyncTasks; private AtomicLong taskIdCounter; public DoclingProducer(DoclingEndpoint endpoint) { @@ -367,10 +367,11 @@ public class DoclingProducer extends DefaultProducer { CompletableFuture<ConvertDocumentResponse> asyncResult = doclingServeApi.convertSourceAsync(request).toCompletableFuture(); - // Generate a unique task ID and store the future for later status checks + // Generate a unique task ID and store the future with timestamp for later status checks String taskId = "task-" + taskIdCounter.incrementAndGet(); - pendingAsyncTasks.put(taskId, asyncResult); - LOG.debug("Started async conversion with task ID: {}", taskId); + AsyncTaskEntry taskEntry = new AsyncTaskEntry(taskId, asyncResult); + pendingAsyncTasks.put(taskId, taskEntry); + LOG.debug("Started async conversion with task ID: {} at {}", taskId, taskEntry.getCreatedAtMs()); // Set task ID in body and header exchange.getIn().setBody(taskId); @@ -425,9 +426,9 @@ public class DoclingProducer extends DefaultProducer { LOG.debug("Checking status for task: {}", taskId); // Check the local pending tasks map first (tasks submitted via SUBMIT_ASYNC_CONVERSION) - CompletableFuture<ConvertDocumentResponse> future = pendingAsyncTasks.get(taskId); - if (future != null) { - return checkLocalAsyncTask(taskId, future); + AsyncTaskEntry taskEntry = pendingAsyncTasks.get(taskId); + if (taskEntry != null) { + return checkLocalAsyncTask(taskId, taskEntry.getFuture()); } // Fall back to server-side task polling diff --git a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingAsyncTaskTtlTest.java b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingAsyncTaskTtlTest.java new file mode 100644 index 000000000000..91ab01758b1f --- /dev/null +++ b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingAsyncTaskTtlTest.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.docling; + +import java.util.concurrent.TimeUnit; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * Test TTL-based cleanup of pending async conversion tasks. + */ +public class DoclingAsyncTaskTtlTest extends CamelTestSupport { + + @Test + public void testAsyncTaskTtlEviction() throws Exception { + // Get the component to access pending tasks map + DoclingComponent component = context.getComponent("docling", DoclingComponent.class); + assertNotNull(component); + + // Configure with a short TTL (2 seconds) for testing + component.getConfiguration().setAsyncTaskTtl(2000); + component.getConfiguration().setUseDoclingServe(true); + component.getConfiguration().setDoclingServeUrl("http://localhost:5001"); + + // Start the component to trigger cleanup scheduler + context.start(); + + // Simulate adding a task entry directly (since we don't have a real docling-serve) + String taskId = "test-task-1"; + AsyncTaskEntry entry = new AsyncTaskEntry(taskId, new java.util.concurrent.CompletableFuture<>()); + component.getPendingAsyncTasks().put(taskId, entry); + + // Verify task is present + assertEquals(1, component.getPendingAsyncTasks().size()); + + // Wait for TTL to expire and cleanup to run + // Cleanup runs every 10% of TTL (minimum 1 minute), but for 2s TTL that's 200ms + // Add buffer for cleanup execution + await().atMost(5, TimeUnit.SECONDS) + .untilAsserted(() -> assertEquals(0, component.getPendingAsyncTasks().size())); + } + + @Test + public void testAsyncTaskNotEvictedBeforeTtl() throws Exception { + // Get the component + DoclingComponent component = context.getComponent("docling", DoclingComponent.class); + assertNotNull(component); + + // Configure with a longer TTL (10 seconds) + component.getConfiguration().setAsyncTaskTtl(10000); + component.getConfiguration().setUseDoclingServe(true); + component.getConfiguration().setDoclingServeUrl("http://localhost:5001"); + + context.start(); + + // Add a task entry + String taskId = "test-task-2"; + AsyncTaskEntry entry = new AsyncTaskEntry(taskId, new java.util.concurrent.CompletableFuture<>()); + component.getPendingAsyncTasks().put(taskId, entry); + + // Verify task is present + assertEquals(1, component.getPendingAsyncTasks().size()); + + // Wait a short time (less than TTL) + Thread.sleep(1000); + + // Task should still be present + assertEquals(1, component.getPendingAsyncTasks().size()); + } + + @Test + public void testMultipleTasksEviction() throws Exception { + // Get the component + DoclingComponent component = context.getComponent("docling", DoclingComponent.class); + assertNotNull(component); + + // Configure with a short TTL + component.getConfiguration().setAsyncTaskTtl(2000); + component.getConfiguration().setUseDoclingServe(true); + component.getConfiguration().setDoclingServeUrl("http://localhost:5001"); + + context.start(); + + // Add multiple task entries + for (int i = 0; i < 5; i++) { + String taskId = "test-task-" + i; + AsyncTaskEntry entry = new AsyncTaskEntry(taskId, new java.util.concurrent.CompletableFuture<>()); + component.getPendingAsyncTasks().put(taskId, entry); + } + + // Verify all tasks are present + assertEquals(5, component.getPendingAsyncTasks().size()); + + // Wait for TTL to expire and cleanup to run + await().atMost(5, TimeUnit.SECONDS) + .untilAsserted(() -> assertEquals(0, component.getPendingAsyncTasks().size())); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + // Empty route - we're testing component-level functionality + from("direct:start") + .to("mock:result"); + } + }; + } + +}
