Skip to content

[backport camel-4.22.x] CAMEL-24957: Fix flaky test MessageHistoryExceptionRouteTest - #27013

Merged
oscerd merged 2 commits into
apache:camel-4.22.xfrom
oscerd:backport/26855-to-camel-4.22.x
Sep 28, 2026
Merged

oscerd merged 2 commits into
apache:camel-4.22.xfrom
oscerd:backport/26855-to-camel-4.22.x

Conversation

@oscerd

@oscerd oscerd commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Backport of #26855

Cherry-pick of #26855 onto camel-4.22.x.

Original PR: #26855 - CAMEL-24957: Fix flaky test MessageHistoryExceptionRouteTest
Original author: @tmielke
Target branch: camel-4.22.x

Why it is needed on 4.22.x

On camel-4.22.x, PR CI tests every module that depends on a changed core module. So a core backport runs camel-opentelemetry-metrics, and there MessageHistoryExceptionRouteTest.testMetricsHistory fails all three surefire attempts:

  • first expected: <5> but was: <4>
  • then ConditionTimeout on both reruns

These are exactly the two failure modes #26855 fixed on main. It currently blocks #26895, the 4.22.x backport of CAMEL-24973 (run 36427587057), and will block any other core backport to this branch.

#26855 was rebase-merged, so it is two commits on main: 36503c92 and d9e938af. Both are cherry-picked here. Both applied cleanly, and together their diff is identical to #26855's. It is test code only, in AbstractOpenTelemetryTestSupport, MessageHistoryExceptionRouteTest and MessageHistoryTest.

Verified on camel-4.22.x:

  • full reactor mvn clean install -DskipTests -DskipITs: green
  • camel-opentelemetry-metrics module tests: 89 unit tests and 5 ITs green, MessageHistoryExceptionRouteTest and MessageHistoryTest included

Original description

Fixes two distinct failure modes in MessageHistoryExceptionRouteTest.testMetricsHistory().

Failure 1 — Race condition (expected: <5> but was: <4>):
Metric recording via nodeProcessingDone() happens asynchronously on seda threads. MockEndpoint.assertIsSatisfied() only waits for mock endpoints to receive messages, not for metrics to be flushed. The bare assertEquals() calls could run before all nodeProcessingDone() callbacks had fired. Fix: wrap all metric count assertions in a single await().untilAsserted() block.

Failure 2 — Cleanup failure on rerun (ConditionTimeoutException):
CamelOpenTelemetryExtension implements BeforeEachCallback and AfterEachCallback, but the otelExtension field in AbstractOpenTelemetryTestSupport was missing @RegisterExtension, so JUnit never invoked those lifecycle methods. On a test retry in the same JVM the SDK was neither reset nor reinitialized, causing metrics to be undetectable. Fix: add @RegisterExtension to otelExtension in AbstractOpenTelemetryTestSupport.

Claude Code on behalf of @oscerd

🤖 Generated with Claude Code

Two distinct failure modes were addressed:

1. Race condition (Failure 1 - "expected: <5> but was: <4>"):
   Metric recording via nodeProcessingDone() happens asynchronously on
   seda threads. MockEndpoint.assertIsSatisfied() only waits for mock
   endpoints to receive messages, not for metrics to be flushed. The
   bare assertEquals() calls could run before all nodeProcessingDone()
   callbacks had fired. Fix: wrap all metric count assertions in a
   single await().untilAsserted() block.

2. Cleanup failure on rerun (Failure 2 - ConditionTimeoutException):
   CamelOpenTelemetryExtension implements BeforeEachCallback and
   AfterEachCallback, but the otelExtension field in
   AbstractOpenTelemetryTestSupport was missing @RegisterExtension, so
   JUnit never invoked those lifecycle methods. On a test retry in the
   same JVM the SDK was neither reset nor reinitialized, causing metrics
   to be undetectable. Fix: add @RegisterExtension to otelExtension in
   AbstractOpenTelemetryTestSupport.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
(cherry picked from commit 36503c9)
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd oscerd added the backport indicate that a Pull request is a backport from a fix from the main branch label Sep 28, 2026

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two changes included here are correct: @RegisterExtension was indeed missing, and wrapping all metric assertions in await().untilAsserted() properly fixes the race. Both hunks are identical to the original #26855.

However, the cherry-pick is incomplete. The original PR #26855 fixed 3 files, but this backport only includes 2 — MessageHistoryTest.java is missing. That test has the exact same race pattern (bare assertEquals() after MockEndpoint.assertIsSatisfied() on async seda-thread metrics) and will flake on camel-4.22.x for the same reason.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus

Copy link
Copy Markdown
Contributor

Thanks for the backport. It is missing one of the three files from #26855. On main, the fix also wraps the metric assertions of MessageHistoryTest in await().untilAsserted(...):

// Metric recording via nodeProcessingDone() happens asynchronously on seda threads,
// so all metric assertions need to be wrapped in await() to avoid a race with mock receipt.
await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
    // there should be 3 names
    assertEquals(3, getAllPointData(DEFAULT_CAMEL_MESSAGE_HISTORY_METER_NAME).size());
    assertEquals(count / 2, getPointData("route1", "foo").getCount());
    assertEquals(count / 2, getPointData("route2", "bar").getCount());
    assertEquals(count / 2, getPointData("route2", "baz").getCount());
});

On camel-4.22.x that test still asserts right after MockEndpoint.assertIsSatisfied(context), which is the same race that made MessageHistoryExceptionRouteTest fail on #26895. Could you add it, so the backport matches #26855?

Claude Code on behalf of davsclaus

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

Apply the same await().untilAsserted() guard to the bare assertEquals()
calls after MockEndpoint.assertIsSatisfied() in MessageHistoryTest.
The seda: endpoints dispatch asynchronously, so metric recording via
nodeProcessingDone() can lag behind mock receipt, causing the same
'expected: <5> but was: <4>' flakiness as in MessageHistoryExceptionRouteTest.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
(cherry picked from commit d9e938a)
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review after new commits: the previous finding (incomplete cherry-pick — MessageHistoryTest.java was missing) is now addressed. The backport includes all 3 files from #26855 with identical diffs. Clean test-only backport, no issues.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-opentelemetry-metrics

🔬 Scalpel shadow comparison — Scalpel: 1 tested, 0 compile-only — current: 9 all tested

Maveniverse Scalpel detected 1 affected modules (current approach: 9).

Modules only in current approach (8)
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin

Skip-tests mode would test 1 modules (1 direct + 0 downstream), skip tests for 0 (generated code, meta-modules)

Modules Scalpel would test (1)
  • camel-opentelemetry-metrics

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (9 modules)
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Launcher :: Container
  • Camel :: Opentelemetry Metrics
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@oscerd oscerd added the test label Sep 28, 2026
@oscerd oscerd self-assigned this Sep 28, 2026
@oscerd oscerd added this to the 4.22.2 milestone Sep 28, 2026
@oscerd
oscerd merged commit 9ef3820 into apache:camel-4.22.x Sep 28, 2026
4 checks passed
@oscerd
oscerd deleted the backport/26855-to-camel-4.22.x branch September 28, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport indicate that a Pull request is a backport from a fix from the main branch components test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants