Author |
Message
|
KoGor |
Posted: Wed Apr 04, 2012 5:19 am Post subject: Error handler for messages in MQ Group |
|
|
Voyager
Joined: 09 Nov 2005 Posts: 81 Location: Moscow,Russia.
|
Hi All!
I'm trying to develop an error handler that could manage possible errors in my message flow. Now I choose a way and want to make sure that it is a good way to do it.
I have a message flow that handles messages that send as MQ Group. We use MQ Group for our own segmentation algorithm at application level to send big files. We do not use MQ segmentation. So as I said message flow receives MQ Group. All messages is persistent. I have selected following options for MQInput node:
Transaction mode = Yes
Order mode = By Queue Order
Logical order = Yes
All message available = Yes
Commit by message group = yes
Message flow:
MQIN -> ComputeRoute -> MQOUT
(catch terminal)
|
v
ComputeError
|
v
THROW
An error can happen any time, for example in the middle of MQ Group processing. So I need the whole MQ Group to be backout’ed, including messages that were processed successfully before an errror. After error happened a message goes into “ComputeError” node. I logged MQGroupID in message flow shared variable and throw an exception to backout a message. For the rest messages from the MQGroup in node “ComputeRoute” I’m checking if this message is the first in MQGroup and that its MQGroupID is not the same as in shared variable. A code sample here:
Code: |
IF MsgSeqNumber = 1 THEN
-- First message in MQ GROUP
-- We check updates in DB only when new message arrived.
-- we've put already in this queue that's why we continue to put message segments in old queue
CALL ClearSharedMemmoryVars();
SET NewMsg = TRUE;
END IF;
IF Root.MQMD.GroupId = SDSErrorGroupId THEN
-- return file into input queue and process it in special flow
THROW USER EXCEPTION VALUES('Backout to the end of MQ Group, after the one of previous messages failed.');
END IF;
RETURN NewMsg;
|
After the last message in group will be backout’ed by “THROW USER EXCEPTION VALUES” thw whole MQ Group must be moved to the backout queue, that I set on input queue. And separate message flow will handle this messages (a one MQ Group)
I was thinking to connect MQIN (false terminal) and do not use MQ backout mechanism. But I’m not sure that messages, that already processed will be backouted if I use the false terminal.
So I’d like to know if this way to handle error is common for MQ Groups or there is more simple and foolproof algorithm?
Thank you for your comments in advance! |
|
Back to top |
|
 |
fjb_saper |
Posted: Wed Apr 04, 2012 8:31 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
I am somewhat confused here.
Is there a reason for not using the checkbox on the MQInput node to only deliver an entire group? (sorry working from memory here)?
Would that not make all your extra handling redundant?  _________________ MQ & Broker admin |
|
Back to top |
|
 |
KoGor |
Posted: Wed Apr 04, 2012 10:33 pm Post subject: |
|
|
Voyager
Joined: 09 Nov 2005 Posts: 81 Location: Moscow,Russia.
|
Sorry, fjb_saper but what checkbox are you talking about? I'm said that I have checked following checkboes:
Transaction mode = Yes
Order mode = By Queue Order
Logical order = Yes
All message available = Yes
Commit by message group = yes
Are you talking about them? |
|
Back to top |
|
 |
Esa |
Posted: Thu Apr 05, 2012 1:13 am Post subject: Re: Error handler for messages in MQ Group |
|
|
 Grand Master
Joined: 22 May 2008 Posts: 1387 Location: Finland
|
KoGor wrote: |
I was thinking to connect MQIN (false terminal) and do not use MQ backout mechanism. But I’m not sure that messages, that already processed will be backouted if I use the false terminal.
So I’d like to know if this way to handle error is common for MQ Groups or there is more simple and foolproof algorithm?
|
Interesting. If you mean not backing out the messages, but implementing your own group exception handling mechanism. And you are going to do this by wiring MQInput nodes failure terminal to your exception handling code, if i have understood correctly?
If you wire MQInput.failure, the messages will be backed out, but they will never end up in the backout queue. Instead, they will be read again by the MQInput and forwarded to failure terminal.
Now what happens if you get an exception in the middle of the group? The transaction will be backed out. Will that result in some of the messages having backout count of 1 and some of them 0? Or will they all have backout count of 1?
Nevertheless, the logical way the MQInput node should handle this is to forward all messages of the group to failure terminal, regardless their backout count. If this is how the node works, your approach should work.
This is something too interesting to be left untested. I think you have just ruined my Easter holiday. |
|
Back to top |
|
 |
KoGor |
Posted: Thu Apr 05, 2012 2:37 am Post subject: |
|
|
Voyager
Joined: 09 Nov 2005 Posts: 81 Location: Moscow,Russia.
|
Actually I want to use just the MQ backout mechanism and do not invent a bicycle. I did wire catch terminal on my schema and left MQInput.Failure terminal unwired. If MQInput.Failure terminal is not connected I reckon on such MQ group behavior. For example message group contain five messages. Message flow processed two messages successfully and an error happened at the third message. I record its MQ group ID in shared variable and throw exception. This message goes back into input queue as failure terminal is not connected and then MQInput read the next message – the fourth and tries to process it. So I check its MQGroup ID with shared variable and throw exception again. And do this till the last message in MQ group. Only after that the whole MQ group is backouted in queue, defined in input queue property.
As I understand if I connect MQInput.Failure terminal to MQOutput, the third message goes into this queue and the whole MQ group wil never be backouted. If message flow handle the fourth and fifth messages correctly then in message flow out queue will be MQ group without third message. And group will be inconsistent. I did not find description how message broker works with MQ groups any way so I invented such algorithm which backouted whole MQ group. |
|
Back to top |
|
 |
Esa |
Posted: Thu Apr 05, 2012 3:31 am Post subject: |
|
|
 Grand Master
Joined: 22 May 2008 Posts: 1387 Location: Finland
|
Sounds better, but I think you may still be reinventing a wheel. Before starting to implement such construct you should make sure that your initial assumptions are correct.
A simple test setup could be a flow that has (a trace node and) a throw node wired from MQInput.catch. Have you tested what happens if you get an exception with the third message of a group of five? Is the whole group backed out or is only the third message backed out and the rest committed?
The InfoCenter does not say much about this, so you will have to test it yourself. It may well be the case that 'commit by message group' also means 'backout by message group' and you don't need any custom logic.
Kogor wrote: |
Message flow processed two messages successfully and an error happened at the third message. I record its MQ group ID in shared variable and throw exception. This message goes back into input queue as failure terminal is not connected and then MQInput read the next message – the fourth and tries to process it. |
You are making a false assumption here. If you throw an exception in catch path, that will cause a rollback of the current transcation. In our case the transaction spans the whole message group. Which means that the message MQInput reads after the rollback should be the first message of the group. If failure terminal is not wired and backout treshold of the queue is 0, the message is moved in the backout queue. This is done expicitly by the MQInput node, not by MQ.
Have you tested that it does not automatically move the whole group in the backout queue? This is what I would expect in the first place, if 'commit by message group' is selected. |
|
Back to top |
|
 |
Esa |
Posted: Fri Apr 06, 2012 5:00 am Post subject: |
|
|
 Grand Master
Joined: 22 May 2008 Posts: 1387 Location: Finland
|
You are right. An exception in the middle of a group splits the group in two. Messages before and including the message that got the exception are backed out, but the messages that come after are committed.
MQOutput operates statelessly with message groups even if 'commit by message group' is selected. My educated guess is that it just issues a commit every time a message has 'last message of group' flag on.
Backing out by message group would require maintaining state by message group about the same way you are doing in your flow. Would it make the nodes performance worse? No, not for ordinary flows that do not commit by group, if it is implemented properly. In my opinion you should open a PMR. At least you would get an official explanation (to share with us).
If you used MQ segmentation instead, you would not have this problem. But you would have another, more serious one. MQ would automatically reassemble the segments when the flow gets the message. There is no way to turn off MQGMO_COMPLETE_MSG for an MQInput node, as far as I know. I think this is one of the reasons why you are using grouping for segmentation of large messages. MQ segmentation would result in performance problems in the flow because of huge input messages. And your flow would have to resegment the message for the target application.
The InfoCenter says that Message Broker supports message segmentation only partially. The reason is probably the same as with grouped messages. If an exception happens with some segment, MQInput node would have to back out all the segments. IMHO breaking a segmented message is way less acceptable than breaking a group. Supporting processing of individual segments would require maintaining state, which is obviously something that developers of the product don't want to implement.
The exception handler you have described seems to me a correct way to solve the problem. But it is not foolproof. If the execution group is restarted after the first part of a group has been backed out, the semi-persistent shared cache is cleared and the remaining messages will be committed. The flow is processing large messages. Depending on how much processing the flow does and how skillfully the code is crafted, processing a group may take something between one minute and half an hour, or even more. This makes the probablity of an EG restart after a partial backout too high to be acceptable.
A better solution is to cache last succesful sequence number for every group, not only when an exception has occurred. The flow should throw an exception if the sequence number of the current message is too high compared to the cached value or the cached value is missing for a message with sequence number larger than 1. |
|
Back to top |
|
 |
mqjeff |
Posted: Fri Apr 06, 2012 5:05 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
I encourage interested parties in this thread to open PMRs and file RFEs. |
|
Back to top |
|
 |
KoGor |
Posted: Tue Apr 10, 2012 8:15 am Post subject: |
|
|
Voyager
Joined: 09 Nov 2005 Posts: 81 Location: Moscow,Russia.
|
Thank you all for your help!
I will open PMR I guess. For now I will reconsider my exception handler and try to improve it. At least I know where I am going now I was not sure that this was just bad designed messaged flow and I did not know a simple solution how to handle errors for messages in MQ Groups.
I will post a complete solution a little bit latter. As soon as I receive answer from IBM and also test my exception handler.
Meanwhile any advice is welcome!  |
|
Back to top |
|
 |
|