Federico Mariani created CAMEL-24090:
----------------------------------------

             Summary: camel-file: eagerly-added idempotent keys are not drained 
when pollDirectory throws mid-poll - scanned files are never consumed (List 
drain overload missed by CAMEL-21830)
                 Key: CAMEL-24090
                 URL: https://issues.apache.org/jira/browse/CAMEL-24090
             Project: Camel
          Issue Type: Bug
          Components: camel-ftp, camel-file
    Affects Versions: 4.21.0
            Reporter: Federico Mariani
         Attachments: 
FileConsumerIdempotentEagerKeyLeakOnPollErrorIssueTest.java

h3. Problem
With {{idempotent=true}} (implied by {{noop=true}}) and default 
{{idempotentEager=true}}, keys are added to the idempotent repository during 
directory scanning ({{isValidFile}} -> {{notUnique}}). If {{pollDirectory}} 
then throws (FTP disconnect mid-scan, I/O error in a subdirectory, filter 
expression error), the catch in {{GenericFileConsumer.poll()}} 
(GenericFileConsumer.java:146-157) drains via the *List* overload of 
{{removeExcessiveInProgressFiles}} (line 310-315), which only removes 
in-progress keys - the eagerly-added idempotent keys stay behind:
{code:java}
protected void removeExcessiveInProgressFiles(List<GenericFile<T>> files) {
    for (GenericFile file : files) {
        String key = file.getAbsoluteFilePath();
        endpoint.getInProgressRepository().remove(key);
        // no removeExcessiveIdempotentFile(...), unlike the Deque overload 
above it
    }
}
{code}
Every subsequent poll sees {{add(key) == false}} -> the never-processed files 
are treated as already consumed and silently skipped forever (until 1000-entry 
LRU eviction/restart for the memory repo; permanently for persistent repos). 
Affects file, FTP, FTPS and SFTP consumers - remote consumers are the likeliest 
trigger (mid-scan disconnect).

h3. History
CAMEL-21830 (130bde60462b, Mar 2025) fixed exactly this leak in the *Deque* 
overload used for batch draining, adding {{removeExcessiveIdempotentFile(file, 
null)}} there - the List overload used on the poll-exception path was 
overlooked. The asymmetry between the two drain methods shows this is an 
oversight, not intent.

h3. Suggested fix
Mirror the Deque overload: in the List drain, when {{isIdempotentEager()}} and 
an idempotent repository is configured, call 
{{removeExcessiveIdempotentFile(file, null)}}. Consider extracting a shared 
drain helper so a third incarnation cannot appear.

h3. Reproducer
Attached failing JUnit test (place in 
{{core/camel-core/src/test/java/org/apache/camel/component/file/}}, where the 
file component tests live). A filter throws on the second file during the first 
poll only; the first file's eagerly-added key leaks and the file is never 
consumed on subsequent polls.

----
_This issue was researched and filed by Claude Code on behalf of [~croway] 
(GitHub: Croway), as part of a deep code review of camel-file and camel-ftp. A 
failing JUnit reproducer is attached; it fails deterministically on current 
main (4.22.0-SNAPSHOT)._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to