Andrea Cosentino created CAMEL-26408:
----------------------------------------
Summary: camel-openfga - batchCheck applies the single-request
await timeout to the whole fan-out
Key: CAMEL-26408
URL: https://issues.apache.org/jira/browse/CAMEL-26408
Project: Camel
Issue Type: Bug
Reporter: Andrea Cosentino
Found during a camel-openfga quality review (reading {{main}} on
4.24.0-SNAPSHOT).
h4. What happens
{{OpenFgaAuthorizer.awaitTimeout()}}
(components/camel-openfga/src/main/java/org/apache/camel/component/openfga/OpenFgaAuthorizer.java,
lines 163-167) computes the per-exchange wait bound as {{(connectTimeout +
readTimeout) * (maxRetries + 1) + AWAIT_SAFETY_MARGIN_MILLIS}} — about 85s with
the 10000 / 10000 / 3 defaults. That is the right bound for a single
{{check()}}: one connect + one request per attempt, across the first attempt
and every retry, plus a margin.
{{OpenFgaProducer.batchCheck()}} (OpenFgaProducer.java, lines 192-194) hands
that same {{awaitTimeoutMillis}} to {{authorizer.await(() ->
client.clientBatchCheck(requests, options))}}. {{clientBatchCheck}} issues one
check request per object with at most {{maxParallelRequests}} (default 10) in
flight, i.e. {{ceil(n / maxParallelRequests)}} serialized waves for n objects.
The whole batch is one future, so {{await}}'s
{{future.get(awaitTimeoutMillis)}} bounds the *entire* fan-out by a budget
sized for a *single* request.
h4. Impact
Under high per-check latency (a slow or degraded OpenFGA server) and a large
body, the batch's wall-clock can exceed the single-request bound; the
Camel-level {{future.get}} then cancels an in-progress batch and the exchange
fails with a misleading {{"Timed out after 85000ms ..."}}. It fails *closed*
({{batchCheck}} has no {{failOpen}} — returning the objects it never managed to
filter would be the leak the filtering prevents), so this is a robustness /
diagnostics bug, not a security issue. The default timeouts make it latent: it
only bites when individual checks are slow and the batch is large.
h4. Proposed fix
Scale the await bound for the batch path by the number of waves — multiply by
{{ceil(requests.size() / maxParallelRequests)}} when awaiting a
{{clientBatchCheck}} — so the batch is given the budget its fan-out actually
needs. At minimum, document that {{batchCheck}}'s effective bound is the
single-request bound regardless of size, and make the timeout message name the
knob to raise. Include a unit test (a mocked client whose future completes
after the single-request bound but within the scaled bound).
Related but distinct: CAMEL-26197 (other {{batchCheck}} bugs in the same
method).
_Claude Code on behalf of oscerd_
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)