Hi, I'd like to investigate ... but for that I need a full reproducer. Can
you provide* one, please?

* Either as a test in the Camel Core code base or one that I can quickly
clone and run.

Thanks

On Thu, Aug 24, 2023 at 6:54 PM Tim Janusz <tjan...@guidewire.com> wrote:

> Hi all,
>
> We're currently trying to upgrade our Camel from 3.20.2, spring boot 2.7.12
> running on Java 11 to spring.boot.version=3.1.2 and camel.version=4.0.0
> running on Java 17.
>
> We are seeing weird behaviour in one of our applications where our SEDA
> component just 'hangs' after a specific set of interactions involving
> dynamically adding/removing routes via the dynamicRouter feature.
>
> Some notes:
>  - We use SEDA component (where things seem to hang)
>  - flow is basically:
>   initialize camel,
>   process msg1 to create dynamic route and process message on it,
>   process msg2 which deletes route,
>   process msg3 which re-creates route and processes it,
>   process msg4 which deletes route,
>   process msg5 which re-creates route and HANGS at this point
>  - Basically the 2nd time we delete the route and re-create again (which
> has the same name as before) is when we see the 'hang' for processing
> (super weird)
>  - This only happens in version 4.x same code works fine in 3.x
>
> We're really wondering what could've changed between version 3.x and 4.x
> that causes this now to hang?
>
> I've included some sudo code below with log snippets to help clarify
>
> Our main RouteBuilder creates these two
>     from("servlet:dialcommand")
>       .routeId("dialCommandServletRoute")
>       .convertBodyTo(String::class.java)
>       .to("seda:dialcommandqueue?timeout=$commandTimeout")
>       .removeHeader("args")
>
>
>
> from("seda:dialcommandqueue?concurrentConsumers=$concurrentConsumerCount&timeout=$commandTimeout")
>       .setExchangePattern(ExchangePattern.InOut)
>       .routeId("dialcommandprocess")
>       .dynamicRouter { it: Exchange -> dialDynamicRouting(it) }
>
> Our dynamic router logic is like this:
> fun dialDynamicRouting(exchange: Exchange): String? {
>
>  // when we need to kill a route
>    is KillRoute -> {
>      context.routeController.stopRoute(routeId)
>      context.removeRoute(routeId)
>
> exchange.`in`.body = success("OK", exchange.`in`.getHeader("id",
> String::class.java))
>      return null
>
>  // when we add a new route dynamically
>     val dialCommandRoute = createDialCommandRoute(routeId, contextId,
> contextKey, concurrency)
>     // add to camel context
>     context.addRoutes(dialCommandRoute)
>     context.getRoute(routeId).properties["contextId"] = contextId
> return dialCommandRoute.from
>
> The "createDialCommandRoute" logic dynamic router created uses this type of
> code
>     from(from)
>       .routeId(routeId)
>       .process {
>         val message = it.`in`
>         val body = message.body
>         if (body is DialCommand<*>) {
>           body.id = message.getHeader("id", String::class.java) ?:
> body.standardOptions.id ?: body.id
>           body.configureLogContext()
>         }
>       }.id("[$routeId] prepare command object")
>       .log(LoggingLevel.INFO, "[\${headers.id}] \${body.procName}")
>       .process { it: Exchange -> it.`in`.body = run(it) }
>   }
>
> With DEBUG level logging enabled we can see where it hangs is basically
> right between when it would normally
> process items off that newly created route.
>
> Log Sample 1: Example logs of a valid run where it creates the new route
> and start processing it
> 2023-08-22  INFO 54168 --- [ialcommandqueue]
> c.g.dm.automation.etl.route.Operator     : Route dialCommandRoute-6fddd8cf
> does not exist. This command (RecoverUnfinishedOperations) will create the
> route.
> 2023-08-22  INFO 54168 --- [ialcommandqueue]
> c.g.dm.automation.etl.route.Operator     : Creating route:
> dialCommandRoute-6fddd8cf
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.impl.engine.AbstractCamelContext   :
> seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 converted to
> endpoint: seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 by
> component: org.apache.camel.component.seda.SedaComponent@4a23350
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Warming up route id:
> dialCommandRoute-6fddd8cf having autoStartup=true
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Route: dialCommandRoute-6fddd8cf
> >>> Route[seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 ->
> null]
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Starting consumer (order: 1004)
> on route: dialCommandRoute-6fddd8cf
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.BaseExecutorServiceManager     : Created new ThreadPool for
> source:
> Consumer[seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0] with
> name: seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0. ->
> org.apache.camel.util.concurrent.RejectableThreadPoolExecutor@10881933
> [Running,
> pool size = 0, active threads = 0, queued tasks = 0, completed tasks =
> 0][seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0]
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Route: dialCommandRoute-6fddd8cf
> started and consuming from: seda://dialcommand:6fddd8cf
>
> -- NOTE: this is where we see it now runs our route's process method on
> different thread
> 2023-08-22  INFO 54168 --- [  e70c0565-main] dialCommandRoute-6fddd8cf
>            : [e70c0565] dhRecoverUnfinishedOperations
> 2023-08-22  INFO 54168 --- [  e70c0565-main]
> c.g.d.a.etl.cli.command.DialCommand      : Beginning
> dhRecoverUnfinishedOperations
> 2023-08-22  INFO 54168 --- [  e70c0565-main]
> c.g.d.a.etl.cli.command.DialCommand      : Completed
> dhRecoverUnfinishedOperations
> 2023-08-22  INFO 54168 --- [ialcommandqueue] dialcommandprocess
>           : [e70c0565] {"id":"e70c0565","status":"OK"}
>
> Log Sample 2: Example logs snippet of where it creates the new route but
> just hangs on us after creation is complete
> 2023-08-22  INFO 54168 --- [ialcommandqueue]
> c.g.dm.automation.etl.route.Operator     : Route dialCommandRoute-6fddd8cf
> does not exist. This command (RecoverUnfinishedOperations) will create the
> route.
> 2023-08-22  INFO 54168 --- [ialcommandqueue]
> c.g.dm.automation.etl.route.Operator     : Creating route:
> dialCommandRoute-6fddd8cf
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.impl.engine.AbstractCamelContext   :
> seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 converted to
> endpoint: seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 by
> component: org.apache.camel.component.seda.SedaComponent@4a23350
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Warming up route id:
> dialCommandRoute-6fddd8cf having autoStartup=true
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Route: dialCommandRoute-6fddd8cf
> >>> Route[seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0 ->
> null]
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Starting consumer (order: 1005)
> on route: dialCommandRoute-6fddd8cf
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.BaseExecutorServiceManager     : Created new ThreadPool for
> source:
> Consumer[seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0] with
> name: seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0. ->
> org.apache.camel.util.concurrent.RejectableThreadPoolExecutor@5c41c3f8
> [Running,
> pool size = 0, active threads = 0, queued tasks = 0, completed tasks =
> 0][seda://dialcommand:6fddd8cf?concurrentConsumers=8&timeout=0]
> 2023-08-22 DEBUG 54168 --- [ialcommandqueue]
> o.a.c.i.e.InternalRouteStartupManager    : Route: dialCommandRoute-6fddd8cf
> started and consuming from: seda://dialcommand:6fddd8cf
> -- NOTE here is where we'd normally see the route thread be running like
> above but we don't and it just hangs at this point!
>  [  e70c0565-main] dialCommandRoute-6fddd8cf                : [e70c0565]
> dhRecoverUnfinishedOperations (THIS LOG NEVER HAPPENS!!)
>
> Additionally, we can also tell that our routes/endpoints are being
> created/destroyed correctly if we log out context route/endpoint info
> seda://dialcommandqueue?timeout=0,
> seda://dialcommandqueue?concurrentConsumers=20&timeout=0,
> seda://dialcommand:9591ba9e?concurrentConsumers=8&timeout=0 (NEW ENDPOINT
> EXAMPLE)
> servlet://dialcommand, direct://defaultCommand
>
> Lastly, when it hangs we can see that the SEDA component thinks its up and
> running
> INFO 59169 --- [ialcommandqueue] c.g.dm.automation.etl.route.Operator     :
> ### SEDA info: currQueueSize: 0, endPointSize: 1000, queueSize: 0,
> queue.remainCapacity: 1000, stoppingOrStopped: false, suspended: false,
> isRunAllowed: true, isStarted: true, status: Started
>
> We're totally stumped at this point as to what could be causing this issue?
>


-- 
Otavio R. Piske
http://orpiske.net

Reply via email to