Telefon Wolakpdx
Telefon Wolakpdx

Reputation: 131

Camel unit of work

I am trying to understand the unit of work concept in Camel. I have a simple question hopefully someone here can help.

If there are multiple routes involved in routing the Excachange for example

from("aws-sqs:Q1").to("direct:processMe");//route1

from("direct:processMe").to("direct:aws-post");//route2

from("direct:aws-post").to("htt4:myservice");//route3

Is the unit of work invoked at the end of each routes? Or only at the end of route3? In my example, will the SQS message be deleted off of SQS once route1 completes? Or will it wait until my message reaches "myservice"?

Thanks.

FOLLOW UP:

I've modified the route slighty:

from("aws-sqs:Q1").to("direct:processMe");//route1

from("direct:processMe").process(
   new Processor(){
       public void process(Exchange exchange) throws Exception {
          throw new RuntimeException("fail on purpose");
       }
   }
).to("direct:aws-post");//route2

from("direct:aws-post").to("http4:myservice");//route3

The thought process is this: If the unit of work is invoked at end of each route then once the message is read from SQS Queue it will be acknowledged as read by the SQS component. On the other hand if unit of work is only invoked once the Exchange is done routing through all routes, then the exception in route 2 will result in the message not being acknowledged and will be available for redelivery once the visibility period expires.

The test showed that the message remains on the Q despite being read by first route. It is picked up again and again (until it ends up in dead letter q). As such I strongly believe that the unit boundary is defined by the end of Exchange being routed.

Upvotes: 8

Views: 3554

Answers (2)

Telefon Wolakpdx
Telefon Wolakpdx

Reputation: 131

I have found a great explanation as to the unit of work boundary:

"The OnCompletion DSL name is used to define an action that is to take place when a Unit of Work is completed.

A Unit of Work is a Camel concept that encompasses an entire exchange. See Section 43.1, “Exchanges”. The onCompletion command has the following features:

  • The scope of the OnCompletion command can be global or per route. A route scope overrides global scope. OnCompletion can be configured to be triggered on success for failure.

  • The onWhen predicate can be used to only trigger the onCompletion in certain situations. You can define whether or not to use a thread pool, though the default is no thread pool."

In case of SQS processing, the consumer defines onCompletion on the exchange. So it is invoked only after the exchange is done routing.

The whole answer can be found here: Apache Camel Development Guide2.11. OnCompletion

Upvotes: 3

stringy05
stringy05

Reputation: 7067

A unit of work is basically a transaction.

By default a message for a route (a camel Exchange) runs inside a single UnitOfWork context.

In your example there are 3 UnitOfWorks set up, starting at each from and finishing at the final to in each route.

I would expect the message from SQS to be consumed after the 1st route finishes. To test, you could add in a sleep to allow you to check the queue.

from("direct:processMe").process(new Processor() 
        { void process() {  try  { Thread.sleep(60000L) } catch (Exception e) { } } 
    }).to("direct:aws-post")

If you want the message to remain on the queue until myservice gets the message then you need to put the processing in a single route.

Upvotes: 2

Related Questions