After the MQTT transport closes the session on RPC delivery timeout,
the server re-queues the RPC asynchronously. The test was asserting
the RPC status immediately after the client disconnect latch fired,
before the server-side re-queuing had completed — so the status was
still SENT instead of the expected QUEUED.
Replace the direct doGet assertion with an Awaitility poll that waits
up to DEFAULT_WAIT_TIMEOUT_SECONDS for the status to become QUEUED.
Fixes flaky: MqttV5CloseTransportSessionOnRpcDeliveryTimeoutIntegrationTest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use ID token claims as the source of truth for Apple OAuth2 attributes
- Added Apple mapper type to OAuth2 client data validation
- Consolidated duplicated validation logic for BASIC, GITHUB, and APPLE mapper types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The lastCommit field was shared across all repository keys, causing
MissingObjectException when multiple repositories were registered.
When onUpdate fired for repo A it overwrote lastCommit, and subsequent
listFiles/getFileContent calls for repo B used repo A's commit whose
tree objects don't exist in repo B's object database.
Changed to a per-key Map<String, RevCommit> so each repository's
resolved commit is stored and retrieved independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a TbRuleChainInputNode has `forwardMsgToDefaultRuleChain=true` and the originator's
default rule chain is the same as the rule chain containing this node, the message enters
an infinite loop: the node forwards to the default rule chain, which routes back to the
same node, which forwards again, causing unbounded recursion and 100% CPU on rule-engine.
Fix: detect the loop in DefaultTbContext.input() by checking whether the calling rule node
is already present in the message's return stack (TbMsgProcessingCtx). On the second+
iteration the stack already contains the (ruleChainId, ruleNodeId) pair of the node,
so the call is a cycle. In that case tellFailure() is called with a descriptive message
and a WARN log is emitted instead of re-enqueuing the message.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delay and deduplication rule nodes were creating brand new TbMsg objects
instead of copying the original, which reset the ruleNodeExecCounter to 0.
This allowed bypassing the maxRuleNodeExecutionsPerMessage limit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TBEL 1.2.9 fixes two issues that caused TBEL scripts to fail or produce
incorrect results when executed multiple times:
1. Thread-safety: OptimizerFactory.defaultOptimizer was not volatile,
so worker threads could use DynamicOptimizer instead of the intended
SafeReflectiveOptimizer, leading to intermittent script failures.
2. MethodAccessor coercion: methods with ExecutionContext parameter
(e.g. bytesToExecutionArrayList) failed on re-execution because the
coercion fallback path did not handle ExecutionContext injection.
Also add @RepeatedTest for parseBytes_Test to verify stability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve the commit once in onUpdate() and reuse the cached RevCommit
for listFiles and getFileContent operations, instead of resolving
the branch ref on every call. Added RevCommit-accepting overloads
to GitRepository for listFilesAtCommit and getFileContentAtCommit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds page-level byte-size tracking in TbResultSet.allRows() using
ExecutionInfo.getResponseSizeInBytes() to fail early when accumulated
result set size exceeds the configurable limit (default 50MB).
Also fixes pre-existing bugs where onFailure callbacks in
CassandraBaseTimeseriesDao only logged errors but never completed
the future, causing callers to hang indefinitely on failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove redundant manual X-Forwarded-For header parsing in
RestAuthenticationDetails. The getClientIP() method duplicated
functionality already provided by Spring's ForwardedHeaderFilter
when server.forward_headers_strategy is configured.
Now uses request.getRemoteAddr() directly, which respects the
configured forward_headers_strategy setting (default: framework).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>