oscerd opened a new pull request, #26115:
URL: https://github.com/apache/camel/pull/26115

   Found by a source audit of `components/camel-infinispan`.
   
   ### The problem
   
   `InfinispanAggregationRepository` implements 
`RecoverableAggregationRepository`, but it keeps a single cache
   keyed by the aggregation correlation key and has no recovery store, so all 
four recovery methods work on the
   wrong key space:
   
   | method | contract | what it did |
   |---|---|---|
   | `remove(ctx, key, exchange)` | move the holder into a recovery store keyed 
by **exchange id** | plain `cache.remove(key)` — the completed exchange is gone 
|
   | `confirm(ctx, exchangeId)` | delete it from the recovery store | 
`cache.remove(exchangeId)` against the correlation-keyed cache — never matches |
   | `scan(ctx)` | return **exchange ids** to recover | returns the correlation 
keys of aggregations still in progress |
   | `recover(ctx, exchangeId)` | load a completed, unconfirmed exchange | 
returns an exchange that is still aggregating |
   
   With `useRecovery` defaulting to `true`, the consequences are visible at 
runtime:
   
   * `AggregateProcessor` treats the `scan()` result as exchange ids and checks 
it against
     `inProgressCompleteExchanges`, so the duplicate-delivery guard never 
matches;
   * the still-open aggregation is marked `CamelRedelivered` and re-submitted 
on every recovery interval
     (default 5s);
   * after `maximumRedeliveries` (default 3) it goes to the dead letter channel;
   * and an exchange that genuinely failed after completion can never be 
recovered, which is the whole point of
     the interface.
   
   Neither the remote nor the embedded subclass overrides these methods, so 
both are affected.
   
   ### The change
   
   A completed exchange is kept in the same cache under a 
`camel-recovery:<exchange id>` key until it is
   confirmed. `scan()` reports those ids, `recover()` reads them, `confirm()` 
deletes one, and `getKeys()`
   filters them out so it still reports only the aggregations in progress. 
`scan()` returns an empty set when
   `useRecovery=false`.
   
   The recovery entry is keyed by `exchange.getExchangeId()` of the exchange 
handed to `remove()`, which is what
   `JdbcAggregationRepository` does (`final String confirmKey = 
exchange.getExchangeId()`), so the confirm path
   lines up with the canonical implementation.
   
   **On the single-cache design.** `RedisAggregationRepository` and 
`JdbcAggregationRepository` use a second
   map/table for the recovery store, and that was the first thing I tried. For 
Hot Rod it means the user has to
   provision a second cache server-side — a deployment change I do not think 
belongs in a bug fix — so this
   keeps one cache and namespaces the recovery keys instead. If you would 
rather have the second cache with an
   option to name it, say so and I will rework it.
   
   ### Tests
   
   The three existing tests encoded the broken key space — `testConfirmExist` 
confirmed with a correlation key
   while the exchanges carried `Exchange_N` ids, `testScan` named its result 
`exchangeIdSet` and asserted
   correlation keys, `testRecover` recovered by correlation key. They are 
rewritten around the real contract
   (add → remove → scan sees the exchange id → recover returns it → confirm 
clears it) in both the embedded
   test and the remote IT, plus a new test that `getKeys()` ignores recovery 
entries.
   
   `mvn clean install` on `components/camel-infinispan` is green — 111 remote 
tests, including the rewritten
   `InfinispanRemoteAggregationRepositoryOperationsIT` against a Hot Rod 
testcontainer, and 12 embedded
   aggregation tests. Full reactor `mvn clean install -DskipTests -Dquickly` 
green. Upgrade-guide entry added
   for 4.23.
   
   ---
   _Claude Code on behalf of oscerd_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to