简体   繁体   中英

Apache Camel: do not trigger route if previous route run is not complete

I have such a situation:

  • Apache Camel route is triggered by timer
  • route executes massive lengthy task
  • and it is possible for timer to trigger route again while previous run is still underway.

I would like my route NOT to be re-triggered while massive task is underway. That is, timer may issue event but it should somehow not lead to trigger route. When massive task is finished, it should be possible for timer to start route again.

What would be the best way to achieve this behaviour?

This is a dsl version that has worked for me:

private static final AtomicBoolean readyToProcess = new AtomicBoolean(true);

public static boolean readyToProcess() {
    boolean readyToProcess = AlarmRouteBuilder.readyToProcess.get();
    if (readyToProcess) {
        AlarmRouteBuilder.readyToProcess.set(false);
    }
    return readyToProcess;
}

@Override
public void configure() throws Exception {

    from("timer://alarm-poll?period=5s").routeId("alarm-poll")
            .log(LoggingLevel.INFO, "Start Timer")
            .filter(method(AlarmRouteBuilder.class, "readyToProcess"))
            .to("direct:alarm-dostuff")
            .end()
            .log(LoggingLevel.INFO, "End Timer")
    ;

    from("direct:alarm-dostuff").routeId("alarm-dostuff")
//            .process(exchange -> readyToProcess.set(false))
            .process(exchange -> doStuff())
            .process(exchange -> readyToProcess.set(true))
    ;

I would create a bean to hold the running/finished state of the route with methods to set the state and a method to test the state. Then I would do something like this:

<route>
  <from uri="timer:...">
  <filter>
    <method ref="routeStateBean" method="isStopped">
    <to uri="bean:routeStateBean?method=routeStarted"/>
    ....
    <to uri="bean:routeStateBean?method=routeStopped"/>
  </filter>
</route>

Well, my first reflex would be to use the timer 's period option without the fixedRate option (ie set the fixedRate option to false):

So, declaring:

from("timer:myTask?[other_options]&fixedRate=false")
    .to("direct:lengthyProcessingRoute")

should wait for the task to complete before triggering the timer again.

For instance, declaring a route like ( fixedRate is false by default):

from("timer:sender?delay=5s&period=3s")
        .log("Ping!")
        .delay(5000)
        .log("Ping2!");

will always give the output of:

2016-08-26 12:36:48.130  INFO 5775 --- [ timer://sender] route1 : Ping!
2016-08-26 12:36:53.133  INFO 5775 --- [ timer://sender] route1 : Ping2!
2016-08-26 12:36:53.135  INFO 5775 --- [ timer://sender] route1 : Ping!
2016-08-26 12:36:58.138  INFO 5775 --- [ timer://sender] route1 : Ping2!

However, this will only work if your lengthy processing route is synchronous in nature. If it's not, then you would have to do something similar to what JimNicholson is suggesting in his answer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM