onkami
onkami

Reputation: 9411

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

I have such a situation:

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?

Upvotes: 8

Views: 5956

Answers (3)

Thomas Newman
Thomas Newman

Reputation: 194

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))
    ;

Upvotes: 3

Miloš Milivojević
Miloš Milivojević

Reputation: 5369

Well, my first reflex would be to use the timer's period option without the fixedRate option (i.e. 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.

Upvotes: 3

JimNicholson
JimNicholson

Reputation: 351

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>

Upvotes: 1

Related Questions