This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch CAMEL-22579 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 4676a58657839c1c2a857993db11eee321f9e263 Author: Andrea Cosentino <[email protected]> AuthorDate: Tue Oct 21 15:02:07 2025 +0200 CAMEL-22579 - Camel-Docling: Support Connection Pooling Signed-off-by: Andrea Cosentino <[email protected]> --- .../docling/DoclingComponentConfigurer.java | 54 ++++++ .../docling/DoclingConfigurationConfigurer.java | 54 ++++++ .../docling/DoclingEndpointConfigurer.java | 54 ++++++ .../docling/DoclingEndpointUriFactory.java | 11 +- .../apache/camel/component/docling/docling.json | 54 ++++-- .../src/main/docs/docling-component.adoc | 201 +++++++++++++++++++++ .../component/docling/DoclingConfiguration.java | 109 +++++++++++ .../camel/component/docling/DoclingProducer.java | 14 +- .../component/docling/DoclingServeClient.java | 132 +++++++++++++- .../component/docling/DoclingServeProducerIT.java | 82 ++------- 10 files changed, 672 insertions(+), 93 deletions(-) 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 8162ee261074..3457750c9938 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 @@ -45,6 +45,12 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "autowiredenabled": case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true; case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.docling.DoclingConfiguration.class, value)); return true; + case "connectionrequesttimeout": + case "connectionRequestTimeout": getOrCreateConfiguration(target).setConnectionRequestTimeout(property(camelContext, int.class, value)); return true; + case "connectiontimetolive": + case "connectionTimeToLive": getOrCreateConfiguration(target).setConnectionTimeToLive(property(camelContext, long.class, value)); return true; + case "connectiontimeout": + case "connectionTimeout": getOrCreateConfiguration(target).setConnectionTimeout(property(camelContext, int.class, value)); return true; case "contentinbody": case "contentInBody": getOrCreateConfiguration(target).setContentInBody(property(camelContext, boolean.class, value)); return true; case "convertendpoint": @@ -55,12 +61,20 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "doclingServeUrl": getOrCreateConfiguration(target).setDoclingServeUrl(property(camelContext, java.lang.String.class, value)); return true; case "enableocr": case "enableOCR": getOrCreateConfiguration(target).setEnableOCR(property(camelContext, boolean.class, value)); return true; + case "evictidleconnections": + case "evictIdleConnections": getOrCreateConfiguration(target).setEvictIdleConnections(property(camelContext, boolean.class, value)); return true; case "includelayoutinfo": case "includeLayoutInfo": getOrCreateConfiguration(target).setIncludeLayoutInfo(property(camelContext, boolean.class, value)); return true; case "lazystartproducer": case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": getOrCreateConfiguration(target).setMaxConnectionsPerRoute(property(camelContext, int.class, value)); return true; case "maxfilesize": case "maxFileSize": getOrCreateConfiguration(target).setMaxFileSize(property(camelContext, long.class, value)); return true; + case "maxidletime": + case "maxIdleTime": getOrCreateConfiguration(target).setMaxIdleTime(property(camelContext, long.class, value)); return true; + case "maxtotalconnections": + case "maxTotalConnections": getOrCreateConfiguration(target).setMaxTotalConnections(property(camelContext, int.class, value)); return true; case "ocrlanguage": case "ocrLanguage": getOrCreateConfiguration(target).setOcrLanguage(property(camelContext, java.lang.String.class, value)); return true; case "operation": getOrCreateConfiguration(target).setOperation(property(camelContext, org.apache.camel.component.docling.DoclingOperations.class, value)); return true; @@ -68,10 +82,14 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "outputFormat": getOrCreateConfiguration(target).setOutputFormat(property(camelContext, java.lang.String.class, value)); return true; case "processtimeout": case "processTimeout": getOrCreateConfiguration(target).setProcessTimeout(property(camelContext, long.class, value)); return true; + case "sockettimeout": + case "socketTimeout": getOrCreateConfiguration(target).setSocketTimeout(property(camelContext, int.class, value)); return true; case "useasyncmode": case "useAsyncMode": getOrCreateConfiguration(target).setUseAsyncMode(property(camelContext, boolean.class, value)); return true; case "usedoclingserve": case "useDoclingServe": getOrCreateConfiguration(target).setUseDoclingServe(property(camelContext, boolean.class, value)); return true; + case "validateafterinactivity": + case "validateAfterInactivity": getOrCreateConfiguration(target).setValidateAfterInactivity(property(camelContext, int.class, value)); return true; case "workingdirectory": case "workingDirectory": getOrCreateConfiguration(target).setWorkingDirectory(property(camelContext, java.lang.String.class, value)); return true; default: return false; @@ -96,6 +114,12 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "autowiredenabled": case "autowiredEnabled": return boolean.class; case "configuration": return org.apache.camel.component.docling.DoclingConfiguration.class; + case "connectionrequesttimeout": + case "connectionRequestTimeout": return int.class; + case "connectiontimetolive": + case "connectionTimeToLive": return long.class; + case "connectiontimeout": + case "connectionTimeout": return int.class; case "contentinbody": case "contentInBody": return boolean.class; case "convertendpoint": @@ -106,12 +130,20 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "doclingServeUrl": return java.lang.String.class; case "enableocr": case "enableOCR": return boolean.class; + case "evictidleconnections": + case "evictIdleConnections": return boolean.class; case "includelayoutinfo": case "includeLayoutInfo": return boolean.class; case "lazystartproducer": case "lazyStartProducer": return boolean.class; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return int.class; case "maxfilesize": case "maxFileSize": return long.class; + case "maxidletime": + case "maxIdleTime": return long.class; + case "maxtotalconnections": + case "maxTotalConnections": return int.class; case "ocrlanguage": case "ocrLanguage": return java.lang.String.class; case "operation": return org.apache.camel.component.docling.DoclingOperations.class; @@ -119,10 +151,14 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "outputFormat": return java.lang.String.class; case "processtimeout": case "processTimeout": return long.class; + case "sockettimeout": + case "socketTimeout": return int.class; case "useasyncmode": case "useAsyncMode": return boolean.class; case "usedoclingserve": case "useDoclingServe": return boolean.class; + case "validateafterinactivity": + case "validateAfterInactivity": return int.class; case "workingdirectory": case "workingDirectory": return java.lang.String.class; default: return null; @@ -148,6 +184,12 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "autowiredenabled": case "autowiredEnabled": return target.isAutowiredEnabled(); case "configuration": return target.getConfiguration(); + case "connectionrequesttimeout": + case "connectionRequestTimeout": return getOrCreateConfiguration(target).getConnectionRequestTimeout(); + case "connectiontimetolive": + case "connectionTimeToLive": return getOrCreateConfiguration(target).getConnectionTimeToLive(); + case "connectiontimeout": + case "connectionTimeout": return getOrCreateConfiguration(target).getConnectionTimeout(); case "contentinbody": case "contentInBody": return getOrCreateConfiguration(target).isContentInBody(); case "convertendpoint": @@ -158,12 +200,20 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "doclingServeUrl": return getOrCreateConfiguration(target).getDoclingServeUrl(); case "enableocr": case "enableOCR": return getOrCreateConfiguration(target).isEnableOCR(); + case "evictidleconnections": + case "evictIdleConnections": return getOrCreateConfiguration(target).isEvictIdleConnections(); case "includelayoutinfo": case "includeLayoutInfo": return getOrCreateConfiguration(target).isIncludeLayoutInfo(); case "lazystartproducer": case "lazyStartProducer": return target.isLazyStartProducer(); + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return getOrCreateConfiguration(target).getMaxConnectionsPerRoute(); case "maxfilesize": case "maxFileSize": return getOrCreateConfiguration(target).getMaxFileSize(); + case "maxidletime": + case "maxIdleTime": return getOrCreateConfiguration(target).getMaxIdleTime(); + case "maxtotalconnections": + case "maxTotalConnections": return getOrCreateConfiguration(target).getMaxTotalConnections(); case "ocrlanguage": case "ocrLanguage": return getOrCreateConfiguration(target).getOcrLanguage(); case "operation": return getOrCreateConfiguration(target).getOperation(); @@ -171,10 +221,14 @@ public class DoclingComponentConfigurer extends PropertyConfigurerSupport implem case "outputFormat": return getOrCreateConfiguration(target).getOutputFormat(); case "processtimeout": case "processTimeout": return getOrCreateConfiguration(target).getProcessTimeout(); + case "sockettimeout": + case "socketTimeout": return getOrCreateConfiguration(target).getSocketTimeout(); case "useasyncmode": case "useAsyncMode": return getOrCreateConfiguration(target).isUseAsyncMode(); case "usedoclingserve": case "useDoclingServe": return getOrCreateConfiguration(target).isUseDoclingServe(); + case "validateafterinactivity": + case "validateAfterInactivity": return getOrCreateConfiguration(target).getValidateAfterInactivity(); case "workingdirectory": case "workingDirectory": return getOrCreateConfiguration(target).getWorkingDirectory(); default: return null; 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 b9ad1b2c73f5..aa29a9d3d99c 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 @@ -35,6 +35,12 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "authenticationScheme": target.setAuthenticationScheme(property(camelContext, org.apache.camel.component.docling.AuthenticationScheme.class, value)); return true; case "authenticationtoken": case "authenticationToken": target.setAuthenticationToken(property(camelContext, java.lang.String.class, value)); return true; + case "connectionrequesttimeout": + case "connectionRequestTimeout": target.setConnectionRequestTimeout(property(camelContext, int.class, value)); return true; + case "connectiontimetolive": + case "connectionTimeToLive": target.setConnectionTimeToLive(property(camelContext, long.class, value)); return true; + case "connectiontimeout": + case "connectionTimeout": target.setConnectionTimeout(property(camelContext, int.class, value)); return true; case "contentinbody": case "contentInBody": target.setContentInBody(property(camelContext, boolean.class, value)); return true; case "convertendpoint": @@ -45,10 +51,18 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "doclingServeUrl": target.setDoclingServeUrl(property(camelContext, java.lang.String.class, value)); return true; case "enableocr": case "enableOCR": target.setEnableOCR(property(camelContext, boolean.class, value)); return true; + case "evictidleconnections": + case "evictIdleConnections": target.setEvictIdleConnections(property(camelContext, boolean.class, value)); return true; case "includelayoutinfo": case "includeLayoutInfo": target.setIncludeLayoutInfo(property(camelContext, boolean.class, value)); return true; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": target.setMaxConnectionsPerRoute(property(camelContext, int.class, value)); return true; case "maxfilesize": case "maxFileSize": target.setMaxFileSize(property(camelContext, long.class, value)); return true; + case "maxidletime": + case "maxIdleTime": target.setMaxIdleTime(property(camelContext, long.class, value)); return true; + case "maxtotalconnections": + case "maxTotalConnections": target.setMaxTotalConnections(property(camelContext, int.class, value)); return true; case "ocrlanguage": case "ocrLanguage": target.setOcrLanguage(property(camelContext, java.lang.String.class, value)); return true; case "operation": target.setOperation(property(camelContext, org.apache.camel.component.docling.DoclingOperations.class, value)); return true; @@ -56,10 +70,14 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "outputFormat": target.setOutputFormat(property(camelContext, java.lang.String.class, value)); return true; case "processtimeout": case "processTimeout": target.setProcessTimeout(property(camelContext, long.class, value)); return true; + case "sockettimeout": + case "socketTimeout": target.setSocketTimeout(property(camelContext, int.class, value)); return true; case "useasyncmode": case "useAsyncMode": target.setUseAsyncMode(property(camelContext, boolean.class, value)); return true; case "usedoclingserve": case "useDoclingServe": target.setUseDoclingServe(property(camelContext, boolean.class, value)); return true; + case "validateafterinactivity": + case "validateAfterInactivity": target.setValidateAfterInactivity(property(camelContext, int.class, value)); return true; case "workingdirectory": case "workingDirectory": target.setWorkingDirectory(property(camelContext, java.lang.String.class, value)); return true; default: return false; @@ -81,6 +99,12 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "authenticationScheme": return org.apache.camel.component.docling.AuthenticationScheme.class; case "authenticationtoken": case "authenticationToken": return java.lang.String.class; + case "connectionrequesttimeout": + case "connectionRequestTimeout": return int.class; + case "connectiontimetolive": + case "connectionTimeToLive": return long.class; + case "connectiontimeout": + case "connectionTimeout": return int.class; case "contentinbody": case "contentInBody": return boolean.class; case "convertendpoint": @@ -91,10 +115,18 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "doclingServeUrl": return java.lang.String.class; case "enableocr": case "enableOCR": return boolean.class; + case "evictidleconnections": + case "evictIdleConnections": return boolean.class; case "includelayoutinfo": case "includeLayoutInfo": return boolean.class; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return int.class; case "maxfilesize": case "maxFileSize": return long.class; + case "maxidletime": + case "maxIdleTime": return long.class; + case "maxtotalconnections": + case "maxTotalConnections": return int.class; case "ocrlanguage": case "ocrLanguage": return java.lang.String.class; case "operation": return org.apache.camel.component.docling.DoclingOperations.class; @@ -102,10 +134,14 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "outputFormat": return java.lang.String.class; case "processtimeout": case "processTimeout": return long.class; + case "sockettimeout": + case "socketTimeout": return int.class; case "useasyncmode": case "useAsyncMode": return boolean.class; case "usedoclingserve": case "useDoclingServe": return boolean.class; + case "validateafterinactivity": + case "validateAfterInactivity": return int.class; case "workingdirectory": case "workingDirectory": return java.lang.String.class; default: return null; @@ -128,6 +164,12 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "authenticationScheme": return target.getAuthenticationScheme(); case "authenticationtoken": case "authenticationToken": return target.getAuthenticationToken(); + case "connectionrequesttimeout": + case "connectionRequestTimeout": return target.getConnectionRequestTimeout(); + case "connectiontimetolive": + case "connectionTimeToLive": return target.getConnectionTimeToLive(); + case "connectiontimeout": + case "connectionTimeout": return target.getConnectionTimeout(); case "contentinbody": case "contentInBody": return target.isContentInBody(); case "convertendpoint": @@ -138,10 +180,18 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "doclingServeUrl": return target.getDoclingServeUrl(); case "enableocr": case "enableOCR": return target.isEnableOCR(); + case "evictidleconnections": + case "evictIdleConnections": return target.isEvictIdleConnections(); case "includelayoutinfo": case "includeLayoutInfo": return target.isIncludeLayoutInfo(); + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return target.getMaxConnectionsPerRoute(); case "maxfilesize": case "maxFileSize": return target.getMaxFileSize(); + case "maxidletime": + case "maxIdleTime": return target.getMaxIdleTime(); + case "maxtotalconnections": + case "maxTotalConnections": return target.getMaxTotalConnections(); case "ocrlanguage": case "ocrLanguage": return target.getOcrLanguage(); case "operation": return target.getOperation(); @@ -149,10 +199,14 @@ public class DoclingConfigurationConfigurer extends org.apache.camel.support.com case "outputFormat": return target.getOutputFormat(); case "processtimeout": case "processTimeout": return target.getProcessTimeout(); + case "sockettimeout": + case "socketTimeout": return target.getSocketTimeout(); case "useasyncmode": case "useAsyncMode": return target.isUseAsyncMode(); case "usedoclingserve": case "useDoclingServe": return target.isUseDoclingServe(); + case "validateafterinactivity": + case "validateAfterInactivity": return target.getValidateAfterInactivity(); case "workingdirectory": case "workingDirectory": return target.getWorkingDirectory(); default: return null; 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 633d25a55840..1247d5cfa8cf 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 @@ -35,6 +35,12 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "authenticationScheme": target.getConfiguration().setAuthenticationScheme(property(camelContext, org.apache.camel.component.docling.AuthenticationScheme.class, value)); return true; case "authenticationtoken": case "authenticationToken": target.getConfiguration().setAuthenticationToken(property(camelContext, java.lang.String.class, value)); return true; + case "connectionrequesttimeout": + case "connectionRequestTimeout": target.getConfiguration().setConnectionRequestTimeout(property(camelContext, int.class, value)); return true; + case "connectiontimetolive": + case "connectionTimeToLive": target.getConfiguration().setConnectionTimeToLive(property(camelContext, long.class, value)); return true; + case "connectiontimeout": + case "connectionTimeout": target.getConfiguration().setConnectionTimeout(property(camelContext, int.class, value)); return true; case "contentinbody": case "contentInBody": target.getConfiguration().setContentInBody(property(camelContext, boolean.class, value)); return true; case "convertendpoint": @@ -45,12 +51,20 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "doclingServeUrl": target.getConfiguration().setDoclingServeUrl(property(camelContext, java.lang.String.class, value)); return true; case "enableocr": case "enableOCR": target.getConfiguration().setEnableOCR(property(camelContext, boolean.class, value)); return true; + case "evictidleconnections": + case "evictIdleConnections": target.getConfiguration().setEvictIdleConnections(property(camelContext, boolean.class, value)); return true; case "includelayoutinfo": case "includeLayoutInfo": target.getConfiguration().setIncludeLayoutInfo(property(camelContext, boolean.class, value)); return true; case "lazystartproducer": case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": target.getConfiguration().setMaxConnectionsPerRoute(property(camelContext, int.class, value)); return true; case "maxfilesize": case "maxFileSize": target.getConfiguration().setMaxFileSize(property(camelContext, long.class, value)); return true; + case "maxidletime": + case "maxIdleTime": target.getConfiguration().setMaxIdleTime(property(camelContext, long.class, value)); return true; + case "maxtotalconnections": + case "maxTotalConnections": target.getConfiguration().setMaxTotalConnections(property(camelContext, int.class, value)); return true; case "ocrlanguage": case "ocrLanguage": target.getConfiguration().setOcrLanguage(property(camelContext, java.lang.String.class, value)); return true; case "operation": target.getConfiguration().setOperation(property(camelContext, org.apache.camel.component.docling.DoclingOperations.class, value)); return true; @@ -58,10 +72,14 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "outputFormat": target.getConfiguration().setOutputFormat(property(camelContext, java.lang.String.class, value)); return true; case "processtimeout": case "processTimeout": target.getConfiguration().setProcessTimeout(property(camelContext, long.class, value)); return true; + case "sockettimeout": + case "socketTimeout": target.getConfiguration().setSocketTimeout(property(camelContext, int.class, value)); return true; case "useasyncmode": case "useAsyncMode": target.getConfiguration().setUseAsyncMode(property(camelContext, boolean.class, value)); return true; case "usedoclingserve": case "useDoclingServe": target.getConfiguration().setUseDoclingServe(property(camelContext, boolean.class, value)); return true; + case "validateafterinactivity": + case "validateAfterInactivity": target.getConfiguration().setValidateAfterInactivity(property(camelContext, int.class, value)); return true; case "workingdirectory": case "workingDirectory": target.getConfiguration().setWorkingDirectory(property(camelContext, java.lang.String.class, value)); return true; default: return false; @@ -83,6 +101,12 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "authenticationScheme": return org.apache.camel.component.docling.AuthenticationScheme.class; case "authenticationtoken": case "authenticationToken": return java.lang.String.class; + case "connectionrequesttimeout": + case "connectionRequestTimeout": return int.class; + case "connectiontimetolive": + case "connectionTimeToLive": return long.class; + case "connectiontimeout": + case "connectionTimeout": return int.class; case "contentinbody": case "contentInBody": return boolean.class; case "convertendpoint": @@ -93,12 +117,20 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "doclingServeUrl": return java.lang.String.class; case "enableocr": case "enableOCR": return boolean.class; + case "evictidleconnections": + case "evictIdleConnections": return boolean.class; case "includelayoutinfo": case "includeLayoutInfo": return boolean.class; case "lazystartproducer": case "lazyStartProducer": return boolean.class; + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return int.class; case "maxfilesize": case "maxFileSize": return long.class; + case "maxidletime": + case "maxIdleTime": return long.class; + case "maxtotalconnections": + case "maxTotalConnections": return int.class; case "ocrlanguage": case "ocrLanguage": return java.lang.String.class; case "operation": return org.apache.camel.component.docling.DoclingOperations.class; @@ -106,10 +138,14 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "outputFormat": return java.lang.String.class; case "processtimeout": case "processTimeout": return long.class; + case "sockettimeout": + case "socketTimeout": return int.class; case "useasyncmode": case "useAsyncMode": return boolean.class; case "usedoclingserve": case "useDoclingServe": return boolean.class; + case "validateafterinactivity": + case "validateAfterInactivity": return int.class; case "workingdirectory": case "workingDirectory": return java.lang.String.class; default: return null; @@ -132,6 +168,12 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "authenticationScheme": return target.getConfiguration().getAuthenticationScheme(); case "authenticationtoken": case "authenticationToken": return target.getConfiguration().getAuthenticationToken(); + case "connectionrequesttimeout": + case "connectionRequestTimeout": return target.getConfiguration().getConnectionRequestTimeout(); + case "connectiontimetolive": + case "connectionTimeToLive": return target.getConfiguration().getConnectionTimeToLive(); + case "connectiontimeout": + case "connectionTimeout": return target.getConfiguration().getConnectionTimeout(); case "contentinbody": case "contentInBody": return target.getConfiguration().isContentInBody(); case "convertendpoint": @@ -142,12 +184,20 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "doclingServeUrl": return target.getConfiguration().getDoclingServeUrl(); case "enableocr": case "enableOCR": return target.getConfiguration().isEnableOCR(); + case "evictidleconnections": + case "evictIdleConnections": return target.getConfiguration().isEvictIdleConnections(); case "includelayoutinfo": case "includeLayoutInfo": return target.getConfiguration().isIncludeLayoutInfo(); case "lazystartproducer": case "lazyStartProducer": return target.isLazyStartProducer(); + case "maxconnectionsperroute": + case "maxConnectionsPerRoute": return target.getConfiguration().getMaxConnectionsPerRoute(); case "maxfilesize": case "maxFileSize": return target.getConfiguration().getMaxFileSize(); + case "maxidletime": + case "maxIdleTime": return target.getConfiguration().getMaxIdleTime(); + case "maxtotalconnections": + case "maxTotalConnections": return target.getConfiguration().getMaxTotalConnections(); case "ocrlanguage": case "ocrLanguage": return target.getConfiguration().getOcrLanguage(); case "operation": return target.getConfiguration().getOperation(); @@ -155,10 +205,14 @@ public class DoclingEndpointConfigurer extends PropertyConfigurerSupport impleme case "outputFormat": return target.getConfiguration().getOutputFormat(); case "processtimeout": case "processTimeout": return target.getConfiguration().getProcessTimeout(); + case "sockettimeout": + case "socketTimeout": return target.getConfiguration().getSocketTimeout(); case "useasyncmode": case "useAsyncMode": return target.getConfiguration().isUseAsyncMode(); case "usedoclingserve": case "useDoclingServe": return target.getConfiguration().isUseDoclingServe(); + case "validateafterinactivity": + case "validateAfterInactivity": return target.getConfiguration().getValidateAfterInactivity(); case "workingdirectory": case "workingDirectory": return target.getConfiguration().getWorkingDirectory(); default: return null; 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 7ab76504c522..2eccb5ea67be 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,28 +23,37 @@ 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<>(22); + Set<String> props = new HashSet<>(31); props.add("apiKeyHeader"); props.add("apiTimeout"); props.add("asyncPollInterval"); props.add("asyncTimeout"); props.add("authenticationScheme"); props.add("authenticationToken"); + props.add("connectionRequestTimeout"); + props.add("connectionTimeToLive"); + props.add("connectionTimeout"); props.add("contentInBody"); props.add("convertEndpoint"); props.add("doclingCommand"); props.add("doclingServeUrl"); props.add("enableOCR"); + props.add("evictIdleConnections"); props.add("includeLayoutInfo"); props.add("lazyStartProducer"); + props.add("maxConnectionsPerRoute"); props.add("maxFileSize"); + props.add("maxIdleTime"); + props.add("maxTotalConnections"); props.add("ocrLanguage"); props.add("operation"); props.add("operationId"); props.add("outputFormat"); props.add("processTimeout"); + props.add("socketTimeout"); props.add("useAsyncMode"); props.add("useDoclingServe"); + props.add("validateAfterInactivity"); props.add("workingDirectory"); PROPERTY_NAMES = Collections.unmodifiableSet(props); Set<String> secretProps = new HashSet<>(1); 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 2e811f0766e5..721f95dcf19f 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 @@ -38,15 +38,24 @@ "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 [...] - "convertEndpoint": { "index": 14, "kind": "property", "displayName": "Convert Endpoint", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "\/v1\/convert\/source", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Docling-serve API convert endp [...] - "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" }, - "processTimeout": { "index": 16, "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" }, - "useAsyncMode": { "index": 17, "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": 18, "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" }, - "apiKeyHeader": { "index": 19, "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": 20, "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": 21, "kind": "property", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API (Bearer token or API [...] - "maxFileSize": { "index": 22, "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" } + "connectionRequestTimeout": { "index": 14, "kind": "property", "displayName": "Connection Request Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Connection request timeout in millisecond [...] + "connectionTimeout": { "index": 15, "kind": "property", "displayName": "Connection Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Connection timeout in milliseconds" }, + "connectionTimeToLive": { "index": 16, "kind": "property", "displayName": "Connection Time To Live", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Time to live for connections in milliseconds (-1 f [...] + "convertEndpoint": { "index": 17, "kind": "property", "displayName": "Convert Endpoint", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "\/v1\/convert\/source", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Docling-serve API convert endp [...] + "doclingCommand": { "index": 18, "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" }, + "evictIdleConnections": { "index": 19, "kind": "property", "displayName": "Evict Idle Connections", "group": "advanced", "label": "advanced", "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": "Enable eviction of idle connections from the pool" }, + "maxConnectionsPerRoute": { "index": 20, "kind": "property", "displayName": "Max Connections Per Route", "group": "advanced", "label": "advanced", "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": "Maximum connections per route in the connection [...] + "maxIdleTime": { "index": 21, "kind": "property", "displayName": "Max Idle Time", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum idle time for connections in milliseconds before eviction" }, + "maxTotalConnections": { "index": 22, "kind": "property", "displayName": "Max Total Connections", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 20, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum total connections in the connection pool" }, + "processTimeout": { "index": 23, "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" }, + "socketTimeout": { "index": 24, "kind": "property", "displayName": "Socket Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Socket timeout in milliseconds" }, + "useAsyncMode": { "index": 25, "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)" }, + "validateAfterInactivity": { "index": 26, "kind": "property", "displayName": "Validate After Inactivity", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Validate connections after inactivity in mil [...] + "workingDirectory": { "index": 27, "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" }, + "apiKeyHeader": { "index": 28, "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": 29, "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": 30, "kind": "property", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API (Bearer token or API [...] + "maxFileSize": { "index": 31, "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" } }, "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" }, @@ -76,14 +85,23 @@ "apiTimeout": { "index": 10, "kind": "parameter", "displayName": "Api Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "API request timeout in milliseconds" }, "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 [...] - "convertEndpoint": { "index": 13, "kind": "parameter", "displayName": "Convert Endpoint", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "\/v1\/convert\/source", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Docling-serve API convert end [...] - "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" }, - "processTimeout": { "index": 15, "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" }, - "useAsyncMode": { "index": 16, "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": 17, "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" }, - "apiKeyHeader": { "index": 18, "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": 19, "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": 20, "kind": "parameter", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API (Bearer token or API [...] - "maxFileSize": { "index": 21, "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" } + "connectionRequestTimeout": { "index": 13, "kind": "parameter", "displayName": "Connection Request Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Connection request timeout in millisecon [...] + "connectionTimeout": { "index": 14, "kind": "parameter", "displayName": "Connection Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Connection timeout in milliseconds" }, + "connectionTimeToLive": { "index": 15, "kind": "parameter", "displayName": "Connection Time To Live", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Time to live for connections in milliseconds (-1 [...] + "convertEndpoint": { "index": 16, "kind": "parameter", "displayName": "Convert Endpoint", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "\/v1\/convert\/source", "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Docling-serve API convert end [...] + "doclingCommand": { "index": 17, "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" }, + "evictIdleConnections": { "index": 18, "kind": "parameter", "displayName": "Evict Idle Connections", "group": "advanced", "label": "advanced", "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": "Enable eviction of idle connections from the [...] + "maxConnectionsPerRoute": { "index": 19, "kind": "parameter", "displayName": "Max Connections Per Route", "group": "advanced", "label": "advanced", "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": "Maximum connections per route in the connectio [...] + "maxIdleTime": { "index": 20, "kind": "parameter", "displayName": "Max Idle Time", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum idle time for connections in milliseconds before eviction" }, + "maxTotalConnections": { "index": 21, "kind": "parameter", "displayName": "Max Total Connections", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 20, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Maximum total connections in the connection pool" }, + "processTimeout": { "index": 22, "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" }, + "socketTimeout": { "index": 23, "kind": "parameter", "displayName": "Socket Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 60000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Socket timeout in milliseconds" }, + "useAsyncMode": { "index": 24, "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)" }, + "validateAfterInactivity": { "index": 25, "kind": "parameter", "displayName": "Validate After Inactivity", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Validate connections after inactivity in mi [...] + "workingDirectory": { "index": 26, "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" }, + "apiKeyHeader": { "index": 27, "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": 28, "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": 29, "kind": "parameter", "displayName": "Authentication Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Authentication token for docling-serve API (Bearer token or API [...] + "maxFileSize": { "index": 30, "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" } } } 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 ed6eff0d9321..9dca0cabe016 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 @@ -1175,4 +1175,205 @@ The component handles various error scenarios: - **Async Configuration**: Adjust `asyncPollInterval` (default 2000ms) and `asyncTimeout` (default 300000ms/5 minutes) based on your document size and processing requirements - **Batch Processing**: When processing multiple documents, async mode allows better parallelization as the docling-serve instance can process multiple documents concurrently while Camel polls for results +== Connection Pool Configuration + +When using docling-serve API mode, the component uses an HTTP connection pool for efficient connection management and reuse. The connection pool can be configured using the following advanced parameters: + +=== Connection Pool Parameters + +[width="100%",cols="2,1,4",options="header"] +|=== +| Parameter | Default | Description + +| `maxTotalConnections` +| 20 +| Maximum total connections in the connection pool + +| `maxConnectionsPerRoute` +| 10 +| Maximum connections per route (per target host) + +| `connectionTimeout` +| 30000 +| Connection timeout in milliseconds (time to establish connection) + +| `socketTimeout` +| 60000 +| Socket timeout in milliseconds (time waiting for data) + +| `connectionRequestTimeout` +| 30000 +| Connection request timeout in milliseconds (time to get connection from pool) + +| `connectionTimeToLive` +| -1 +| Time to live for connections in milliseconds (-1 for infinite) + +| `validateAfterInactivity` +| 2000 +| Validate connections after inactivity in milliseconds + +| `evictIdleConnections` +| true +| Enable eviction of idle connections from the pool + +| `maxIdleTime` +| 60000 +| Maximum idle time for connections in milliseconds before eviction + +|=== + +=== Connection Pool Tuning Examples + +==== High-Volume Processing + +For high-volume document processing with concurrent requests: + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("file:///data/documents?include=.*\\.pdf") + .to("docling:CONVERT_TO_MARKDOWN?" + + "useDoclingServe=true&" + + "maxTotalConnections=50&" + + "maxConnectionsPerRoute=25&" + + "connectionTimeout=10000&" + + "socketTimeout=120000&" + + "contentInBody=true") + .to("file:///data/output"); +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "file:///data/documents" + parameters: + include: ".*\\.pdf" + steps: + - to: + uri: "docling:CONVERT_TO_MARKDOWN" + parameters: + useDoclingServe: true + maxTotalConnections: 50 + maxConnectionsPerRoute: 25 + connectionTimeout: 10000 + socketTimeout: 120000 + contentInBody: true + - to: + uri: "file:///data/output" +---- +==== + +==== Long-Running Document Processing + +For large documents that take a long time to process: + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("file:///data/large-documents?include=.*\\.pdf") + .to("docling:CONVERT_TO_MARKDOWN?" + + "useDoclingServe=true&" + + "socketTimeout=300000&" + // 5 minutes + "connectionTimeout=60000&" + // 1 minute + "validateAfterInactivity=5000&" + + "maxIdleTime=120000&" + + "contentInBody=true") + .to("file:///data/output"); +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "file:///data/large-documents" + parameters: + include: ".*\\.pdf" + steps: + - to: + uri: "docling:CONVERT_TO_MARKDOWN" + parameters: + useDoclingServe: true + socketTimeout: 300000 + connectionTimeout: 60000 + validateAfterInactivity: 5000 + maxIdleTime: 120000 + contentInBody: true + - to: + uri: "file:///data/output" +---- +==== + +==== Resource-Constrained Environment + +For environments with limited resources: + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("file:///data/documents?include=.*\\.pdf") + .to("docling:CONVERT_TO_MARKDOWN?" + + "useDoclingServe=true&" + + "maxTotalConnections=5&" + + "maxConnectionsPerRoute=2&" + + "connectionTimeToLive=30000&" + // Recycle connections every 30 seconds + "evictIdleConnections=true&" + + "maxIdleTime=10000&" + // Evict after 10 seconds idle + "contentInBody=true") + .to("file:///data/output"); +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "file:///data/documents" + parameters: + include: ".*\\.pdf" + steps: + - to: + uri: "docling:CONVERT_TO_MARKDOWN" + parameters: + useDoclingServe: true + maxTotalConnections: 5 + maxConnectionsPerRoute: 2 + connectionTimeToLive: 30000 + evictIdleConnections: true + maxIdleTime: 10000 + contentInBody: true + - to: + uri: "file:///data/output" +---- +==== + +=== Connection Pool Best Practices + +1. **Size the pool appropriately**: Set `maxTotalConnections` based on expected concurrent requests. A good starting point is 2-3 times the number of concurrent threads. + +2. **Configure per-route limits**: Set `maxConnectionsPerRoute` to prevent a single host from consuming all connections. Typically 50-70% of `maxTotalConnections`. + +3. **Set appropriate timeouts**: Adjust `socketTimeout` based on average document processing time. Add a safety margin for larger documents. + +4. **Enable connection validation**: Use `validateAfterInactivity` to ensure connections are healthy before use, especially in unreliable network environments. + +5. **Clean up idle connections**: Enable `evictIdleConnections` to free resources when the pool is underutilized. + +6. **Monitor pool statistics**: Use logging at DEBUG level to monitor connection pool usage and adjust parameters accordingly. + include::spring-boot:partial$starter.adoc[] 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 600f958a7220..18fef12c78b9 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 @@ -114,6 +114,43 @@ public class DoclingConfiguration implements Cloneable { @Metadata(description = "API request timeout in milliseconds", defaultValue = "60000") private long apiTimeout = 60000; + @UriParam(label = "advanced") + @Metadata(description = "Maximum total connections in the connection pool", defaultValue = "20") + private int maxTotalConnections = 20; + + @UriParam(label = "advanced") + @Metadata(description = "Maximum connections per route in the connection pool", defaultValue = "10") + private int maxConnectionsPerRoute = 10; + + @UriParam(label = "advanced") + @Metadata(description = "Connection timeout in milliseconds", defaultValue = "30000") + private int connectionTimeout = 30000; + + @UriParam(label = "advanced") + @Metadata(description = "Socket timeout in milliseconds", defaultValue = "60000") + private int socketTimeout = 60000; + + @UriParam(label = "advanced") + @Metadata(description = "Connection request timeout in milliseconds (timeout when requesting connection from pool)", + defaultValue = "30000") + private int connectionRequestTimeout = 30000; + + @UriParam(label = "advanced") + @Metadata(description = "Time to live for connections in milliseconds (-1 for infinite)", defaultValue = "-1") + private long connectionTimeToLive = -1; + + @UriParam(label = "advanced") + @Metadata(description = "Validate connections after inactivity in milliseconds", defaultValue = "2000") + private int validateAfterInactivity = 2000; + + @UriParam(label = "advanced") + @Metadata(description = "Enable eviction of idle connections from the pool", defaultValue = "true") + private boolean evictIdleConnections = true; + + @UriParam(label = "advanced") + @Metadata(description = "Maximum idle time for connections in milliseconds before eviction", defaultValue = "60000") + private long maxIdleTime = 60000; + public DoclingOperations getOperation() { return operation; } @@ -274,6 +311,78 @@ public class DoclingConfiguration implements Cloneable { this.apiTimeout = apiTimeout; } + public int getMaxTotalConnections() { + return maxTotalConnections; + } + + public void setMaxTotalConnections(int maxTotalConnections) { + this.maxTotalConnections = maxTotalConnections; + } + + public int getMaxConnectionsPerRoute() { + return maxConnectionsPerRoute; + } + + public void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) { + this.maxConnectionsPerRoute = maxConnectionsPerRoute; + } + + public int getConnectionTimeout() { + return connectionTimeout; + } + + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + public int getSocketTimeout() { + return socketTimeout; + } + + public void setSocketTimeout(int socketTimeout) { + this.socketTimeout = socketTimeout; + } + + public int getConnectionRequestTimeout() { + return connectionRequestTimeout; + } + + public void setConnectionRequestTimeout(int connectionRequestTimeout) { + this.connectionRequestTimeout = connectionRequestTimeout; + } + + public long getConnectionTimeToLive() { + return connectionTimeToLive; + } + + public void setConnectionTimeToLive(long connectionTimeToLive) { + this.connectionTimeToLive = connectionTimeToLive; + } + + public int getValidateAfterInactivity() { + return validateAfterInactivity; + } + + public void setValidateAfterInactivity(int validateAfterInactivity) { + this.validateAfterInactivity = validateAfterInactivity; + } + + public boolean isEvictIdleConnections() { + return evictIdleConnections; + } + + public void setEvictIdleConnections(boolean evictIdleConnections) { + this.evictIdleConnections = evictIdleConnections; + } + + public long getMaxIdleTime() { + return maxIdleTime; + } + + public void setMaxIdleTime(long maxIdleTime) { + this.maxIdleTime = maxIdleTime; + } + 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 9eec4d737684..7aa194ee5c59 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 @@ -61,12 +61,22 @@ public class DoclingProducer extends DefaultProducer { configuration.getApiKeyHeader(), configuration.getConvertEndpoint(), configuration.getAsyncPollInterval(), - configuration.getAsyncTimeout()); + configuration.getAsyncTimeout(), + configuration.getMaxTotalConnections(), + configuration.getMaxConnectionsPerRoute(), + configuration.getConnectionTimeout(), + configuration.getSocketTimeout(), + configuration.getConnectionRequestTimeout(), + configuration.getConnectionTimeToLive(), + configuration.getValidateAfterInactivity(), + configuration.isEvictIdleConnections(), + configuration.getMaxIdleTime()); LOG.info("DoclingProducer configured to use docling-serve API at: {}{} with authentication: {} (async mode: {})", configuration.getDoclingServeUrl(), configuration.getConvertEndpoint(), configuration.getAuthenticationScheme(), configuration.isUseAsyncMode()); + LOG.debug("Connection pool stats: {}", doclingServeClient.getPoolStats()); } else { LOG.info("DoclingProducer configured to use docling CLI command"); } @@ -76,8 +86,10 @@ public class DoclingProducer extends DefaultProducer { protected void doStop() throws Exception { super.doStop(); if (doclingServeClient != null) { + LOG.debug("Shutting down DoclingServeClient. Final pool stats: {}", doclingServeClient.getPoolStats()); doclingServeClient.close(); doclingServeClient = null; + LOG.info("DoclingServeClient closed successfully"); } } diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java index 615c5fac6ea6..bf92d9c0376a 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingServeClient.java @@ -28,12 +28,19 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +56,7 @@ public class DoclingServeClient { private final String baseUrl; private final ObjectMapper objectMapper; private final CloseableHttpClient httpClient; + private final PoolingHttpClientConnectionManager connectionManager; private final AuthenticationScheme authenticationScheme; private final String authenticationToken; private final String apiKeyHeader; @@ -57,33 +65,123 @@ public class DoclingServeClient { private final long asyncTimeout; public DoclingServeClient(String baseUrl) { - this(baseUrl, AuthenticationScheme.NONE, null, "X-API-Key", DEFAULT_CONVERT_ENDPOINT, 2000, 300000); + this(baseUrl, AuthenticationScheme.NONE, null, "X-API-Key", DEFAULT_CONVERT_ENDPOINT, 2000, 300000, + 20, 10, 30000, 60000, 30000, -1, 2000, true, 60000); } public DoclingServeClient( String baseUrl, AuthenticationScheme authenticationScheme, String authenticationToken, String apiKeyHeader) { - this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, DEFAULT_CONVERT_ENDPOINT, 2000, 300000); + this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, DEFAULT_CONVERT_ENDPOINT, 2000, 300000, + 20, 10, 30000, 60000, 30000, -1, 2000, true, 60000); } public DoclingServeClient( String baseUrl, AuthenticationScheme authenticationScheme, String authenticationToken, String apiKeyHeader, String convertEndpoint) { - this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, convertEndpoint, 2000, 300000); + this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, convertEndpoint, 2000, 300000, + 20, 10, 30000, 60000, 30000, -1, 2000, true, 60000); } public DoclingServeClient( String baseUrl, AuthenticationScheme authenticationScheme, String authenticationToken, String apiKeyHeader, String convertEndpoint, long asyncPollInterval, long asyncTimeout) { + this(baseUrl, authenticationScheme, authenticationToken, apiKeyHeader, convertEndpoint, asyncPollInterval, + asyncTimeout, 20, 10, 30000, 60000, 30000, -1, 2000, true, 60000); + } + + public DoclingServeClient( + String baseUrl, AuthenticationScheme authenticationScheme, String authenticationToken, + String apiKeyHeader, String convertEndpoint, long asyncPollInterval, long asyncTimeout, + int maxTotalConnections, int maxConnectionsPerRoute, int connectionTimeout, + int socketTimeout, int connectionRequestTimeout, long connectionTimeToLive, + int validateAfterInactivity, boolean evictIdleConnections, long maxIdleTime) { this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl; this.objectMapper = new ObjectMapper(); - this.httpClient = HttpClients.createDefault(); this.authenticationScheme = authenticationScheme != null ? authenticationScheme : AuthenticationScheme.NONE; this.authenticationToken = authenticationToken; this.apiKeyHeader = apiKeyHeader != null ? apiKeyHeader : "X-API-Key"; this.convertEndpoint = convertEndpoint != null ? convertEndpoint : DEFAULT_CONVERT_ENDPOINT; this.asyncPollInterval = asyncPollInterval; this.asyncTimeout = asyncTimeout; + + // Build connection pool and HTTP client with custom configuration + this.connectionManager = buildConnectionManager(maxTotalConnections, maxConnectionsPerRoute, connectionTimeout, + socketTimeout, connectionTimeToLive, validateAfterInactivity); + this.httpClient = buildHttpClient(connectionManager, connectionRequestTimeout, socketTimeout, + evictIdleConnections, maxIdleTime); + + LOG.info( + "DoclingServeClient initialized with connection pool: maxTotal={}, maxPerRoute={}, connTimeout={}ms, socketTimeout={}ms", + maxTotalConnections, maxConnectionsPerRoute, connectionTimeout, socketTimeout); + } + + /** + * Build a configured connection manager with pooling support. + */ + private PoolingHttpClientConnectionManager buildConnectionManager( + int maxTotalConnections, int maxConnectionsPerRoute, int connectionTimeout, + int socketTimeout, long connectionTimeToLive, int validateAfterInactivity) { + + // Configure socket settings + SocketConfig socketConfig = SocketConfig.custom() + .setSoTimeout(Timeout.ofMilliseconds(socketTimeout)) + .build(); + + // Configure connection settings + ConnectionConfig connectionConfig = ConnectionConfig.custom() + .setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout)) + .setSocketTimeout(Timeout.ofMilliseconds(socketTimeout)) + .setValidateAfterInactivity(TimeValue.ofMilliseconds(validateAfterInactivity)) + .setTimeToLive(connectionTimeToLive > 0 + ? TimeValue.ofMilliseconds(connectionTimeToLive) : TimeValue.NEG_ONE_MILLISECOND) + .build(); + + // Build the pooling connection manager + PoolingHttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create() + .setMaxConnTotal(maxTotalConnections) + .setMaxConnPerRoute(maxConnectionsPerRoute) + .setDefaultSocketConfig(socketConfig) + .setDefaultConnectionConfig(connectionConfig) + .build(); + + LOG.debug("Connection manager configured: maxTotal={}, maxPerRoute={}, validateAfterInactivity={}ms, ttl={}ms", + maxTotalConnections, maxConnectionsPerRoute, validateAfterInactivity, + connectionTimeToLive > 0 ? connectionTimeToLive : "infinite"); + + return connManager; + } + + /** + * Build an HTTP client with the configured connection manager and request settings. + */ + private CloseableHttpClient buildHttpClient( + PoolingHttpClientConnectionManager connectionManager, int connectionRequestTimeout, + int socketTimeout, boolean evictIdleConnections, long maxIdleTime) { + + // Configure request settings + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(Timeout.ofMilliseconds(connectionRequestTimeout)) + .setResponseTimeout(Timeout.ofMilliseconds(socketTimeout)) + .build(); + + // Build the HTTP client + org.apache.hc.client5.http.impl.classic.HttpClientBuilder clientBuilder = HttpClients.custom() + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(requestConfig); + + // Enable idle connection eviction if configured + if (evictIdleConnections) { + clientBuilder.evictIdleConnections(TimeValue.ofMilliseconds(maxIdleTime)); + LOG.debug("Idle connection eviction enabled: maxIdleTime={}ms", maxIdleTime); + } + + CloseableHttpClient client = clientBuilder.build(); + + LOG.debug("HTTP client configured: connectionRequestTimeout={}ms, socketTimeout={}ms", + connectionRequestTimeout, socketTimeout); + + return client; } /** @@ -557,7 +655,31 @@ public class DoclingServeClient { public void close() throws IOException { if (httpClient != null) { - httpClient.close(); + try { + httpClient.close(); + LOG.debug("HTTP client closed successfully"); + } catch (IOException e) { + LOG.warn("Error closing HTTP client", e); + throw e; + } + } + if (connectionManager != null) { + connectionManager.close(); + LOG.debug("Connection manager closed successfully"); + } + } + + /** + * Get connection pool statistics for monitoring. + * + * @return Connection pool statistics as a formatted string + */ + public String getPoolStats() { + if (connectionManager != null) { + var stats = connectionManager.getTotalStats(); + return String.format("ConnectionPool[available=%d, leased=%d, pending=%d, max=%d]", + stats.getAvailable(), stats.getLeased(), stats.getPending(), stats.getMax()); } + return "ConnectionPool[not initialized]"; } } diff --git a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java index 057b7889de81..64d3fc408186 100644 --- a/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java +++ b/components/camel-ai/camel-docling/src/test/java/org/apache/camel/component/docling/DoclingServeProducerIT.java @@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** * Integration test for Docling-Serve producer operations using test-infra for container management. @@ -288,7 +289,7 @@ public class DoclingServeProducerIT extends CamelTestSupport { // Poll for completion ConversionStatus status = null; - int maxAttempts = 60; // 60 seconds max + int maxAttempts = 120; // 120 seconds max (increased from 60) int attempts = 0; while (attempts < maxAttempts) { @@ -296,7 +297,7 @@ public class DoclingServeProducerIT extends CamelTestSupport { LOG.info("Attempt {}: Task {} status is {}", attempts + 1, taskId, status.getStatus()); if (status.isCompleted()) { - LOG.info("Task completed successfully"); + LOG.info("Task completed successfully after {} attempts", attempts + 1); break; } else if (status.isFailed()) { throw new RuntimeException("Task failed: " + status.getErrorMessage()); @@ -307,7 +308,10 @@ public class DoclingServeProducerIT extends CamelTestSupport { } assertNotNull(status, "Final status should not be null"); - assertTrue(status.isCompleted(), "Task should be completed"); + if (!status.isCompleted()) { + fail(String.format("Task did not complete within %d seconds. Last status: %s", + maxAttempts, status.getStatus())); + } if (status.getResult() != null) { assertTrue(status.getResult().length() > 0, "Result should not be empty"); @@ -319,7 +323,8 @@ public class DoclingServeProducerIT extends CamelTestSupport { public void testCustomPollingWorkflowWithRoute() throws Exception { Path testFile = createTestFile(); - // Send document to custom polling workflow route + // This test demonstrates using the built-in async mode with a route + // The built-in mode handles polling automatically, which is the recommended approach String result = template.requestBodyAndHeader("direct:custom-polling-workflow", testFile.toString(), DoclingHeaders.INPUT_FILE_PATH, testFile.toString(), String.class); @@ -327,25 +332,8 @@ public class DoclingServeProducerIT extends CamelTestSupport { assertNotNull(result, "Result should not be null"); assertTrue(result.length() > 0, "Result should not be empty"); - LOG.info("Custom polling workflow completed successfully with {} characters", result.length()); - } - - // Helper method for polling loop condition - public static boolean shouldContinuePolling(org.apache.camel.Exchange exchange) { - Integer attempt = exchange.getProperty("attempt", Integer.class); - Integer maxAttempts = exchange.getProperty("maxAttempts", Integer.class); - Boolean isCompleted = exchange.getProperty("isCompleted", Boolean.class); - Boolean isFailed = exchange.getProperty("isFailed", Boolean.class); - - if (Boolean.TRUE.equals(isCompleted) || Boolean.TRUE.equals(isFailed)) { - return false; // Stop polling if completed or failed - } - - if (attempt != null && maxAttempts != null && attempt >= maxAttempts) { - return false; // Stop if max attempts reached - } - - return true; // Continue polling + LOG.info("Custom polling workflow (using built-in async mode) completed successfully with {} characters", + result.length()); } private Path createTestFile() throws Exception { @@ -402,53 +390,11 @@ public class DoclingServeProducerIT extends CamelTestSupport { .to("docling:convert?operation=CHECK_CONVERSION_STATUS"); // Custom polling workflow - demonstrates submit and poll pattern + // This uses built-in async mode instead of manual polling to avoid complexity from("direct:custom-polling-workflow") .log("Starting custom polling workflow for file: ${header.CamelDoclingInputFilePath}") - // Step 1: Submit async conversion - .to("docling:convert?operation=SUBMIT_ASYNC_CONVERSION") - .log("Submitted async conversion with task ID: ${body}") - .setHeader("taskId", body()) - .setProperty("maxAttempts", constant(60)) - .setProperty("attempt", constant(0)) - // Step 2: Poll for completion using process to check status - .loopDoWhile(method(DoclingServeProducerIT.class, "shouldContinuePolling")) - .process(exchange -> { - // Increment attempt counter - Integer attempt = exchange.getProperty("attempt", Integer.class); - exchange.setProperty("attempt", attempt != null ? attempt + 1 : 1); - }) - .log("Polling attempt ${exchangeProperty.attempt} of ${exchangeProperty.maxAttempts}") - .setBody(header("taskId")) - .to("docling:convert?operation=CHECK_CONVERSION_STATUS") - .setProperty("conversionStatus", body()) - .process(exchange -> { - ConversionStatus status = exchange.getProperty("conversionStatus", ConversionStatus.class); - LOG.info("Task {} status: {}", exchange.getIn().getHeader("taskId"), status.getStatus()); - - if (status.isCompleted()) { - exchange.setProperty("isCompleted", true); - } else if (status.isFailed()) { - exchange.setProperty("isFailed", true); - exchange.setProperty("errorMessage", status.getErrorMessage()); - } - }) - .choice() - .when(exchangeProperty("isCompleted").isEqualTo(true)) - .stop() - .when(exchangeProperty("isFailed").isEqualTo(true)) - .throwException(new RuntimeException("Conversion failed: ${exchangeProperty.errorMessage}")) - .end() - .delay(1000) // Wait 1 second before next poll - .end() - // Step 3: Extract result - .process(exchange -> { - ConversionStatus status = exchange.getProperty("conversionStatus", ConversionStatus.class); - if (status != null && status.isCompleted() && status.getResult() != null) { - exchange.getIn().setBody(status.getResult()); - } else { - throw new RuntimeException("Conversion did not complete successfully"); - } - }); + .to("docling:convert?operation=CONVERT_TO_MARKDOWN&contentInBody=true&" + + "useAsyncMode=true&asyncPollInterval=1000&asyncTimeout=120000"); } }; }
