Showing posts with label queue. Show all posts
Showing posts with label queue. Show all posts

Tuesday, March 20, 2012

conversation_handle in Queue doesn't match "SEND ON CONVERSATION..." value.

When examining the "conversation_handle" column value in the Queue (from: "select * from ProcessQueue"), I find the value of the conversation_handle appears to be different from the "conversation handle" ("SEND ON CONVERSATION @.conversationHandle...") on which the message was sent.

I'm trying to gather all messages for a given Dialog conversation, but am not able to do this because the conversation_handle doesn't appear consistent between messages in the Dialog.

note: the conversation_handle of "BEGIN CONVERSATION TIMER (@.conversationHandle)..." message does appear to be correct in the Queue.

Thoughts on why the conversation_handle listed in the Queue might be different than that of the
"SEND ON CONVERSATION @.conversationHandle..." command that sends the message?

-
-
-


ALTER PROCEDURE [dbo].[SendMessageStoredProcedure]
AS

-- Declare Conversation Handle
DECLARE @.conversationHandle uniqueidentifier;

-- Declare Message
DECLARE @.message nvarchar(max);

-- Begin Transaction
BEGIN TRANSACTION;

-- Begin Dialog from Service1 to Service2 on Contract
BEGIN DIALOG @.conversationHandle
FROM SERVICE ExecuteProcess
TO SERVICE 'ExecuteProcess'
ON CONTRACT Process;


FROM DEBUGGER: @.conversationHandle has value of AC8DF4E0-9F38-DB11-96A2-000CF1D46448

-- Set Message value
DECLARE @.requestDocument xml
SET @.requestDocument = N'<ProcessRequestMessage/>';

-- Start Converstation time
BEGIN CONVERSATION TIMER (@.conversationHandle) TIMEOUT = @.queueSeconds;

-- Send Message
SEND ON CONVERSATION @.conversationHandle MESSAGE TYPE ProcessRequest (@.requestDocument);

-- Commit Transaction
COMMIT TRANSACTION;

-
-
-

RESULTS OF: select * from ProcessQueue;

status priorty q_order conversation_group_id conversation_handle msg_s_# service_name ser_id srv_cont_name ...
1 0 1 AD8DF4E0-9F38-DB11-96A2-000CF1D46448 AC8DF4E0-9F38-DB11-96A2-000CF1D46448 -2 ExecuteProcess 65536 Process 65536 http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer 5 E NULL
1 0 0 AE8DF4E0-9F38-DB11-96A2-000CF1D46448 AF8DF4E0-9F38-DB11-96A2-000CF1D46448 0 ExecuteProcess 65536 Process 65536 ProcessRequest 65536 X 0xFFFE3C004400610074006100620...

Conversation handles uniquely identify a conversation endpoint. Since a dialog has two endpoints (the initiator and the target), it will have two conversation handles. The handle returned by the BEGIN DIALOG statement is the conversation handle at the initiator whereas the one in the target queue is the handle for the target endpoint of the dialog.

Conversation IDs, on the other hand, uniquely identify a conversation. Hence for a dialog, you will notice that the conversation ID is the same at the initiator and the target.

You can see converstaion_handle, conversation_id and other properties of your conversation endpoints by looking at the sys.conversation_endpoints view.

|||Thanks! ...exactly the clarification I needed.

conversation_handle in Queue doesn't match "SEND ON CONVERSATION..." value.

When examining the "conversation_handle" column value in the Queue (from: "select * from ProcessQueue"), I find the value of the conversation_handle appears to be different from the "conversation handle" ("SEND ON CONVERSATION @.conversationHandle...") on which the message was sent.

I'm trying to gather all messages for a given Dialog conversation, but am not able to do this because the conversation_handle doesn't appear consistent between messages in the Dialog.

note: the conversation_handle of "BEGIN CONVERSATION TIMER (@.conversationHandle)..." message does appear to be correct in the Queue.

Thoughts on why the conversation_handle listed in the Queue might be different than that of the
"SEND ON CONVERSATION @.conversationHandle..." command that sends the message?

-
-
-


ALTER PROCEDURE [dbo].[SendMessageStoredProcedure]
AS

-- Declare Conversation Handle
DECLARE @.conversationHandle uniqueidentifier;

-- Declare Message
DECLARE @.message nvarchar(max);

-- Begin Transaction
BEGIN TRANSACTION;

-- Begin Dialog from Service1 to Service2 on Contract
BEGIN DIALOG @.conversationHandle
FROM SERVICE ExecuteProcess
TO SERVICE 'ExecuteProcess'
ON CONTRACT Process;


FROM DEBUGGER: @.conversationHandle has value of AC8DF4E0-9F38-DB11-96A2-000CF1D46448

-- Set Message value
DECLARE @.requestDocument xml
SET @.requestDocument = N'<ProcessRequestMessage/>';

-- Start Converstation time
BEGIN CONVERSATION TIMER (@.conversationHandle) TIMEOUT = @.queueSeconds;

-- Send Message
SEND ON CONVERSATION @.conversationHandle MESSAGE TYPE ProcessRequest (@.requestDocument);

-- Commit Transaction
COMMIT TRANSACTION;

-
-
-

RESULTS OF: select * from ProcessQueue;

status priorty q_order conversation_group_id conversation_handle msg_s_# service_name ser_id srv_cont_name ...
1 0 1 AD8DF4E0-9F38-DB11-96A2-000CF1D46448 AC8DF4E0-9F38-DB11-96A2-000CF1D46448 -2 ExecuteProcess 65536 Process 65536 http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer 5 E NULL
1 0 0 AE8DF4E0-9F38-DB11-96A2-000CF1D46448 AF8DF4E0-9F38-DB11-96A2-000CF1D46448 0 ExecuteProcess 65536 Process 65536 ProcessRequest 65536 X 0xFFFE3C004400610074006100620...

Conversation handles uniquely identify a conversation endpoint. Since a dialog has two endpoints (the initiator and the target), it will have two conversation handles. The handle returned by the BEGIN DIALOG statement is the conversation handle at the initiator whereas the one in the target queue is the handle for the target endpoint of the dialog.

Conversation IDs, on the other hand, uniquely identify a conversation. Hence for a dialog, you will notice that the conversation ID is the same at the initiator and the target.

You can see converstaion_handle, conversation_id and other properties of your conversation endpoints by looking at the sys.conversation_endpoints view.

|||Thanks! ...exactly the clarification I needed.

Conversation Timer problem : Timeout not effective

Hi,

I am using conversation Timer for delaying a message for a few seconds but I can see the message immediately in the queue.

Here is the code i am using. This is a part of a stored procedure I have used.

BEGIN CONVERSATION TIMER ( @.h ) TIMEOUT = @.DelayBySeconds;

SEND ON CONVERSATION @.h

MESSAGE TYPE [sendmsg]

(@.msg);

I am executing this stored procedure with following statements.

exec set_ssb_msg 'test3', 25;

exec set_ssb_msg 'test1', 1;

select * from q1

I was hoping to see just the 'Test1' and see test3 after 25 seconds. But I could see both the messages in a queue as soon as i run the stored proc.

If I execute a receive command on the queue, I am receiving 'test3' first and then 'test1'. This is exactly opposit of what i expected.

Can you please let me know if I am doing anything wrong or missing a step.

Any help is greatly appreciated.

Thanks,

Don.

Conversation timers have no relation whatsoever to sent messages, they affect the local endpoints only. You should expect a DialogTimer message in your sender's queue to show up after 25 and/or 1 seconds. The messages sent are unaffacted by timers. Also, although is not clear in your example, it seems that you're begining a new conversation for each message sent. The message order is only guaranteed within a conversation, and as such your expectations of a certain order on the target queue are not justified.

conversation groups and processing in order on the target end

Is there any way to ensure that messages sent on different dialogs have the same conversation group id on the target queue? I was attempting to set the conversation group id on the dialog before sending but learned that this only works on the initator end.

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=174976&SiteID=1

I have messages that could be sent from different applications (and at slightly different times) that need to processed exclusively (i.e. have the same conversation group id).

Message ordering is guaranteed within a conversation. Is there any reason that stops you from sending all messages on the same conversation?

HTH,
~ Remus

|||Thanks for the reply - Yes, the sending of messages will be distributed and at different times. i.e. 3 different applications will send messages to the same queue. The messages have to be processed exclusively I tried using one queue as both the initiator and target but the converation group IDs were still different. The move conversation command works but only after messages have been received at the target queue.
|||

Having the conversation from one queue to the same queue does not help, as you noticed, the initiator and target conversation don't share the conversation group. The behavior of conversations that are with local (or event the same) service/queues is in every respect the same as conversations that are with remote services/queues.

But in general, trying to use the conversation group to achieve ordering will get you nowhere. Conversation groups only control what messages can be received by a transaction. That is, they're only relevant to locking. Even if you manage to move all three conversations into the same group and all three messages will be present in the queue, the RECEIVE verb will return them in random order! The messages are guaranteed to be in order within a conversation, not within a group. Actually, you can check the RECEIVE verb execution query plan in the SQL Management Studio and you'll see that it has an ORDER BY clause. This will sort the resultset (a.k.a the messages received) by conversation_handle (among other columns), which is a GUID, so basically the order of conversations within a group is random.

The only way to achieve order is to use one single conversation and send all messages on it. It doesn't matter if they are sent at different times, they will be RECEIVEd in the order sent.

The very problem of preserving order between 3 messages sent from 3 distributed locations is, in my opinion, unsolvable. 3 distributed locations means 3 distinct local times. Which is the authoritative time between them? I.e. if message 'two' was sent one minute after message 'one', but the time on location 'two' is two minutes behind, which message should be considered as sent first? Or if 2 of the 3 messages are sent at identical time 05:10:00 AM, which one was sent first? Or what if message one was sent fine, but the machine hosting location two was destroyed by a suden burst of cosmic rays just before message 'two' being sent, and then message 'three' was sent fine, is message 'three' really message 'three' or is message 'two'?
I only see this problem resolvable if the messages are sent using a primitive that serializes the messages (i.e. the conversation).

Also keep in mind that even if you achieve order by using a single conversation, you still won't be guaranteed that you'll RECEIVE all 3 messages at once (in one single RECEIVE resultset). Messages are RECEIVEd as they show up in the queue, so is perfetcly possible to RECEIVE message 'one' and 'two' while message 'three' is still in traffic.

If you can give some more details on what are you trying to do, I feel we can probably think of a way to achieve what you need.

HTH,
~ Remus

|||

Thanks again for the quick reply

I think I may have phrased the problem incorrectly. I only need the messages in a single conversation to be ordered, but I need for the messages in the three different conversations to be processed exclusively (The processing of the messages will be distributed as well). Unfortunately I cannot send all the messages in a single conversation, so I though I could just designate them to a single conversation group so that only one message from any of the three conversations could be processed at one time.

Any suggestions?

|||You can put the three dialogs in the same conversation group but you will need to do it at the target end when you receive the messages - using MOVE CONVERSATION. I don't know of a practical way to do this. I generally send messages out on different dialogs in the same conversation group so the responses are received together. For example, you could have one of your dialogs send a message to the target and when you receive the message on the target queue, open two new dialogs in the same conversation group as the received message and have those two dialogs send out request messages to get the data back. Pretty convoluted but it should work.|||

You can also add an extra message to your conversation. This message is sent first and contains some form of tag or Id based on which when the target receives this first message, it moves the target conversation endpoint into an appropiate group.

So the initiator does normal BEGIN DIALOG, followed by two SEND (one for the tag/id and one for the real payload). The target receives messages normally in a loop, but reacts differently to the two message types:
- if the message is a tag/id message, it finds the appropiate group and moves the conversation into that group
- if the message is normal payload it process it normally, assured that is the only one processing this group

HTH,
~ Remus

Thursday, March 8, 2012

Contract and Queue confusion if named the same plus positioning issue.............

Hello,

The problem I was having regarding re-enable a queue was because it was in another database. I am guessing it did that because the contract and Queues have the same name. I double checked and nothing pointed to that database. I fixed it because I can re-enable the queue in the other database and it is fixed. My question is why did this happen? The other issue I am still having is regarding why the queue got disabled to begin with. I understand that it was because of positioning but do not understand how or why and how to provent it from being disabled.

Thanks,

Scott Allison...

You can have a contract and a queue inside one database with the same name without any conflict. You queue may be getting disabled due to poisoned message detection. You can read about this in Books Online. In short, if you receive from a queue and rollback 5 times consecutively, we detect that the queue probably has a bad message and disable it.

Rushi