Skip to content

Commit 22a687b

Browse files
authored
CAMEL-23459: Add TTL cleanup for pending async tasks to prevent memory leak
Fix a memory leak in the camel-docling component where pending async conversion tasks accumulated indefinitely in the shared `pendingAsyncTasks` map (e.g. when the consumer that would normally poll the result is removed or never started). Each pending task is now wrapped in an `AsyncTaskEntry` carrying a creation timestamp. A background scheduler — interval = 10% of the TTL, floor 1s — evicts entries older than `asyncTaskTtl` (default 24h). The eviction is additive and backward-compatible: normal task consumption is unchanged, and only tasks that would never be claimed are removed. Lifecycle/eviction logging is at DEBUG. Includes a new `DoclingAsyncTaskTtlTest` (Awaitility-based, no `Thread.sleep`) covering eviction-after-TTL, no-eviction-before-TTL, and multi-task eviction. Pre-existing `DoclingAsyncConversionTest` was updated to use the new `AsyncTaskEntry` wrapper (was throwing `ClassCastException`). Top-level catalog/DSL artifacts regenerated. Closes #23125
1 parent b2c58eb commit 22a687b

15 files changed

Lines changed: 535 additions & 180 deletions

File tree

catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json

Lines changed: 81 additions & 79 deletions
Large diffs are not rendered by default.

components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingComponentConfigurer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
3636
case "apiKeyHeader": getOrCreateConfiguration(target).setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true;
3737
case "asyncpollinterval":
3838
case "asyncPollInterval": getOrCreateConfiguration(target).setAsyncPollInterval(property(camelContext, long.class, value)); return true;
39+
case "asynctaskttl":
40+
case "asyncTaskTtl": getOrCreateConfiguration(target).setAsyncTaskTtl(property(camelContext, long.class, value)); return true;
3941
case "asynctimeout":
4042
case "asyncTimeout": getOrCreateConfiguration(target).setAsyncTimeout(property(camelContext, long.class, value)); return true;
4143
case "authenticationscheme":
@@ -144,6 +146,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
144146
case "apiKeyHeader": return java.lang.String.class;
145147
case "asyncpollinterval":
146148
case "asyncPollInterval": return long.class;
149+
case "asynctaskttl":
150+
case "asyncTaskTtl": return long.class;
147151
case "asynctimeout":
148152
case "asyncTimeout": return long.class;
149153
case "authenticationscheme":
@@ -253,6 +257,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
253257
case "apiKeyHeader": return getOrCreateConfiguration(target).getApiKeyHeader();
254258
case "asyncpollinterval":
255259
case "asyncPollInterval": return getOrCreateConfiguration(target).getAsyncPollInterval();
260+
case "asynctaskttl":
261+
case "asyncTaskTtl": return getOrCreateConfiguration(target).getAsyncTaskTtl();
256262
case "asynctimeout":
257263
case "asyncTimeout": return getOrCreateConfiguration(target).getAsyncTimeout();
258264
case "authenticationscheme":

components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingConfigurationConfigurer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
2929
case "apiKeyHeader": target.setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true;
3030
case "asyncpollinterval":
3131
case "asyncPollInterval": target.setAsyncPollInterval(property(camelContext, long.class, value)); return true;
32+
case "asynctaskttl":
33+
case "asyncTaskTtl": target.setAsyncTaskTtl(property(camelContext, long.class, value)); return true;
3234
case "asynctimeout":
3335
case "asyncTimeout": target.setAsyncTimeout(property(camelContext, long.class, value)); return true;
3436
case "authenticationscheme":
@@ -132,6 +134,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
132134
case "apiKeyHeader": return java.lang.String.class;
133135
case "asyncpollinterval":
134136
case "asyncPollInterval": return long.class;
137+
case "asynctaskttl":
138+
case "asyncTaskTtl": return long.class;
135139
case "asynctimeout":
136140
case "asyncTimeout": return long.class;
137141
case "authenticationscheme":
@@ -236,6 +240,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
236240
case "apiKeyHeader": return target.getApiKeyHeader();
237241
case "asyncpollinterval":
238242
case "asyncPollInterval": return target.getAsyncPollInterval();
243+
case "asynctaskttl":
244+
case "asyncTaskTtl": return target.getAsyncTaskTtl();
239245
case "asynctimeout":
240246
case "asyncTimeout": return target.getAsyncTimeout();
241247
case "authenticationscheme":

components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointConfigurer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
2929
case "apiKeyHeader": target.getConfiguration().setApiKeyHeader(property(camelContext, java.lang.String.class, value)); return true;
3030
case "asyncpollinterval":
3131
case "asyncPollInterval": target.getConfiguration().setAsyncPollInterval(property(camelContext, long.class, value)); return true;
32+
case "asynctaskttl":
33+
case "asyncTaskTtl": target.getConfiguration().setAsyncTaskTtl(property(camelContext, long.class, value)); return true;
3234
case "asynctimeout":
3335
case "asyncTimeout": target.getConfiguration().setAsyncTimeout(property(camelContext, long.class, value)); return true;
3436
case "authenticationscheme":
@@ -134,6 +136,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
134136
case "apiKeyHeader": return java.lang.String.class;
135137
case "asyncpollinterval":
136138
case "asyncPollInterval": return long.class;
139+
case "asynctaskttl":
140+
case "asyncTaskTtl": return long.class;
137141
case "asynctimeout":
138142
case "asyncTimeout": return long.class;
139143
case "authenticationscheme":
@@ -240,6 +244,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
240244
case "apiKeyHeader": return target.getConfiguration().getApiKeyHeader();
241245
case "asyncpollinterval":
242246
case "asyncPollInterval": return target.getConfiguration().getAsyncPollInterval();
247+
case "asynctaskttl":
248+
case "asyncTaskTtl": return target.getConfiguration().getAsyncTaskTtl();
243249
case "asynctimeout":
244250
case "asyncTimeout": return target.getConfiguration().getAsyncTimeout();
245251
case "authenticationscheme":

components/camel-ai/camel-docling/src/generated/java/org/apache/camel/component/docling/DoclingEndpointUriFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ public class DoclingEndpointUriFactory extends org.apache.camel.support.componen
2323
private static final Set<String> SECRET_PROPERTY_NAMES;
2424
private static final Map<String, String> MULTI_VALUE_PREFIXES;
2525
static {
26-
Set<String> props = new HashSet<>(51);
26+
Set<String> props = new HashSet<>(52);
2727
props.add("abortOnError");
2828
props.add("apiKeyHeader");
2929
props.add("asyncPollInterval");
30+
props.add("asyncTaskTtl");
3031
props.add("asyncTimeout");
3132
props.add("authenticationScheme");
3233
props.add("authenticationToken");

0 commit comments

Comments
 (0)