etzel-mes opened a new pull request, #28789:
URL: https://github.com/apache/camel/pull/28789
# Description
JIRA: CAMEL-26444 (filed by me as mardonius; follow-up to CAMEL-24899).
**What went wrong.** CAMEL-24899 keeps the content of the route files that
loaded (`lastGoodContent`) and, when a reload fails, loads the failed file from
that content. `RouteWatcherReloadStrategy` filled it only after a successful
`updateRoutes` in `onRouteReload`, never with the routes loaded at startup.
Until the first successful reload since start, a failed reload therefore had
nothing to go back to:
- `camel run only.camel.yaml --dev`: the first broken save logs "Reload
failed and there are no previous routes to restore" and the route stops. After
one good save, a broken save keeps the previous version running.
- The on-demand reload (`camel run --source-dir`, `/q/dev/reload`) passes
every file as changed, so the first failed reload since start restored no file
at all.
- When nothing was restored, the routes that the partial load had added
before the failure kept running (`m1` of a file whose `m2` failed), although
the warning says that the application runs without routes.
**The change** (`RouteWatcherReloadStrategy`):
- When the strategy starts, it remembers the content of the sources of the
routes that run, collected as `onRouteReload` collects them (that selection is
now one method, `addRouteSources`). The context starts the strategy, a deferred
service, after the routes. The supervising route controller starts the routes
after the context, and the strategy together with the first route it starts, so
the routes it has yet to start are taken from `getControlledRoutes()`.
- With no routes at startup, the supervising route controller starts the
strategy with the first route a reload adds, in the middle of that reload. A
flag set at the beginning of `onRouteReload` keeps those routes out of the
startup content; otherwise a file that fails after its first route was added
would be "restored" from its broken content.
- `restorePreviousRoutes` removes what a partial load left (routes, route
templates, endpoints) also when there is nothing to restore, as it already did
before a restore, so nothing of the failed file runs.
- `route-reload.adoc` gets a short section on what a failed reload keeps
running; the user manual did not describe it yet.
**Existing tests.** Two assertions change.
- `RouteReloadRollbackTest#aFailedReloadRestoresThePreviousRoutes` asserted
that route `bad` is gone after its file failed to reload. It was written for
CAMEL-24860, a day before CAMEL-24899, when a failed reload loaded only the
other files again from disk and a failed file could not come back. CAMEL-24899
kept the content in memory, but only after a successful reload, so the
assertion still held.
- `RouteReloadBatchTest#aBatchWithOneBrokenFileStillLoadsTheOthers`
(CAMEL-25032) checks that the good file of a failed batch gets through. Its
last line, that `shop` is gone, records the same gap.
On main, with one successful reload before the broken save, both flows keep
the previous version of the broken file running; I checked both. Both tests now
expect the version loaded at startup. That is what CAMEL-24860 asks for ("keep
the old ones when the new fail"), and what CAMEL-24899 asks for ("keep the last
successfully loaded route definitions").
Three tests began with a successful reload only to get around the gap ("one
successful reload, so the content that runs is remembered"):
-
`RouteReloadRollbackTest#theOnlyRouteFileKeepsItsPreviousVersionWhenTheSaveIsBroken`
(CAMEL-24899)
- `RouteReloadOnDemandRemovedFileTest#aFileRestoredFromMemoryCanBeRemoved`
(CAMEL-25427)
-
`RouteReloadPropertiesRetryTest#aReloadThatFailedOnAMissingPropertyLoadsWhenThePropertyArrives`
(CAMEL-25032)
That reload is removed, so they start from the content loaded at startup,
and each of them fails on main. With the startup content kept, those tests no
longer check what a successful reload remembers. The last step of the new
single-file test now checks it: a broken save after a good one goes back to the
good one, not to the version loaded at startup.
No upgrade guide entry: there is nothing to migrate, and a failed reload in
dev mode keeps more running than before.
**Verification.**
- Three new tests in `RouteReloadRollbackTest`, each red on main and green
with the change:
- `theFirstBrokenSaveAfterStartGoesBackToTheVersionLoadedAtStartup`: the
four steps of the JIRA reproduction, with the strategy added to the context
before it starts, as Camel Main adds it.
-
`theFirstFailedOnDemandReloadAfterStartGoesBackToEveryFileLoadedAtStartup`:
`RouteOnDemandReloadStrategy` as `camel run --source-dir` sets it up, with the
supervising route controller.
- `aFailedReloadWithNothingToGoBackToLeavesNoneOfItsRoutesRunning`: the
first route file fails after its first route was added, with the supervising
route controller.
- The three tests without their first reload fail on main as well.
- Mutants: without `getControlledRoutes()` the on-demand test fails. Without
the flag, or without the cleanup, the last test fails. If the content of a
successful reload is not remembered, the last step of the single-file test
fails; before that step was added, every reload test passed with this mutant.
- `*Reload*Test` of camel-core (50), camel-xml-io-dsl (4) and camel-yaml-dsl
(20), and `SemanticDeclarationDslTest` of camel-semantic, which subclasses the
strategy. The four changed test classes five runs in a row with
`-Dsurefire.rerunFailingTestsCount=0`.
- End to end with Camel Main, the file watcher (500 ms) and timer routes,
with the default and the supervising route controller (`initialDelay` 1000):
the first broken save logs "The previous routes were restored (1 route(s)
running, 1 from the last loaded content of the changed file)" and v1 keeps
ticking; with a two-route file whose second route breaks, both routes keep
ticking. On main the same runs log "there are no previous routes to restore",
v1 stops, and in the two-route case `m1` keeps ticking while `m2` stops.
- `-Psourcecheck` on camel-support and camel-yaml-dsl; the formatter and
impsort leave no changes. No root build.
@davsclaus @gnodet could you have a look? (I cannot request reviewers.)
# Target
- [x] I checked that the commit is targeting the correct branch (Camel 4
uses the `main` branch)
# Tracking
- [x] If this is a large change, bug fix, or code improvement, I checked
there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for
the change (usually before you start working on it).
# Apache Camel coding standards and style
- [x] I checked that each commit in the pull request has a meaningful
subject line and body.
- [ ] I have run `mvn clean install -DskipTests` locally from root folder
and I have committed all auto-generated changes.
# AI-assisted contributions
- [x] If this PR includes AI-generated code, commits have proper
co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR
description identifies the AI tool used.
The code and tests were written with Claude Code (Claude Opus 5.5) under my
direction; the commit carries the `Co-authored-by` trailer.
_Claude Code on behalf of etzel-mes_
🤖 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]