Monday, March 26, 2012

Poison Message. The conversation endpoint is not in a valid state for SEND.

Hi all, i searched everywhere but couldn't find any info on the following error that i'm currently receiving:

"The conversation endpoint is not in a valid state for SEND. The current endpoint state is 'DI'."

I understand that this is due to some problem in my send/receive protocol but how do i fix this problem so that i can continue with my testing? Right now i'm forced to drop my entire test database and reinstall everytime this message shows up because i can't send/receive any messages at that point. Is there anyway to get rid of it?

Thanks in advance. This is driving me nuts.

DI stands for DISCONNECTED INBOUND and the conversation goes into this state when the peer has ended the conversation. If you try to send on a conversation in this state you'll get this error. You need to establish a clear protocol on who'w ending the conversation and how, because what s likely happening one side (initiator?) issues the END CONVERSATION verb and ends the conversation while the target is still trying to respond.

|||I think i found a solution to my own problem.

This is from the Microsoft online book:
http://download.microsoft.com/download/f/8/5/f8520d64-f109-4111-b0b0-51f1f6d2d220/Rational_Press_Service_Broker_Sample.pdf


If you look at the example in Chapter 1, you will notice that only one end of the conversation

was ended. In Figure 2.3, you can see one conversation with a state of “DI” (meaning

“disconnected inbound”), indicating that the opposite endpoint was ended with an END

CONVERSATION command but this endpoint of the conversation hasn’t been ended yet.

The other conversation state is “ER” (or “error”) because it has been open long enough

that the timeout has expired and the conversation ended with an error. If you execute an

END CONVERSATION command specifying the conversation_handle for the row in

the sys.conversation_endpoints table, it will go away.

Remembering to end all conversations is a very important programming practice. If you

forget to do this, you will fi nd thousands of rows in the sys.conversation_endpoints table

after your application has run for awhile.

If anyone has other ideas then please let me know.

Cheers!!
|||Thanks Remus for the reply, here is my sending protocol:

declare @.dh uniqueidentifier;
declare @.Message nvarchar(500);

SET @.Message = N'<MessageTypes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/"><TransactionID>12345</TransactionID><MessageType>Swap</MessageType><Source>OMS</Source><IsCancel>false</IsCancel></MessageTypes>';

BEGIN DIALOG CONVERSATION @.dh
FROM SERVICE ClientServiceOMS
TO SERVICE 'TranProcessorService'
ON CONTRACT TradeCon
WITH ENCRYPTION = OFF;

SEND ON CONVERSATION @.dh
MESSAGE TYPE MessageTypes(@.Message)

END CONVERSATION @.dh;

And here is my receiving protocol (I removed all error handling for simplicity):

CREATE PROCEDURE ServiceProc
AS
DECLARE @.MsgXml xml, @.MsgTypeName nvarchar(128),
@.dh uniqueidentifier, @.Message nvarchar(500);

SET @.ErrNS = 'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
SET @.EndDlgNS = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'

BEGIN TRAN;

WAITFOR (RECEIVE TOP(1)
@.MsgXml = CAST(message_body as xml),
@.MsgTypeName = message_type_name,
@.dh = conversation_handle
FROM ServiceQue) timeout 1000;

-- Send reply message
SET @.Message = N'<ResponseMessage><Message>Received</Message></ResponseMessage>';
SEND ON CONVERSATION @.dh
MESSAGE TYPE ResponseMessage(@.Message);

END CONVERSATION @.dh;
PRINT '(ServiceProc) Reply Message Sent Successfully.'

COMMIT TRAN

So are my "END CONVERSATION" statements in the correct place?

Thanks a lot.
|||Hello again, I just wanted to clairfy that the receiving procedure is called automatically by the receiving queue to process the messages. So i guess i'm not understanding exactly when to end the conversation.

The above receiving procedure is incorrect, here is the correct version:

CREATE PROCEDURE ServiceProc
AS
DECLARE @.MsgXml xml, @.MsgTypeName nvarchar(128),
@.dh uniqueidentifier, @.Message nvarchar(500);

BEGIN TRAN;

WAITFOR (RECEIVE TOP(1)
@.MsgXml = CAST(message_body as xml),
@.MsgTypeName = message_type_name,
@.dh = conversation_handle
FROM ServiceQue), TIMEOUT 1000;

-- Send reply message
SET @.Message = N'<ResponseMessage><Message>Received</Message></ResponseMessage>';
SEND ON CONVERSATION @.dh
MESSAGE TYPE ResponseMessage(@.Message);

END CONVERSATION @.dh;
PRINT '(ServiceProc) Reply Message Sent Successfully.'

COMMIT TRAN

I really appreciate all the help.

Thanks
|||

Scorpio8 wrote:

BEGIN DIALOG CONVERSATION @.dh
FROM SERVICE ClientServiceOMS
TO SERVICE 'TranProcessorService'
ON CONTRACT TradeCon
WITH ENCRYPTION = OFF;

SEND ON CONVERSATION @.dh
MESSAGE TYPE MessageTypes(@.Message)

END CONVERSATION @.dh;

For one, you are doing fire-and-forget and that has some problems, see here: http://blogs.msdn.com/remusrusanu/archive/2006/04/06/570578.aspx. Second, the target is trying to respond on a conversation that was already ended by the initiator (hence the error you're getting).

Remove the END CONVERSATION on the sending side, have the initiator wait for the response from the target and end it's side of the conversation after it received a response.

|||Thank you very much Remus, that article and your other articles were very helpful. I got everything working now. But even though all the conversations end up gracefully i still end up with an entry in the sys.conversation_endpoints queue on both database instances:

select state, state_desc from sys.conversation_endpoints

state state_desc
CD CLOSED

Do i need to clear this queue every now and then or should it automatically clear up when the conversations end?

|||

Hi, i found an answer to my question in the book "Pro SQL Server 2005 Service Broker" which i got over the weekend, great book. The answer is on page 59:

"As soon as you process the EndDialog message on the initiator side, the conversation will end on both sides and then discarded from memory. However, for security reasons, it takes about 30 minutes until the initiator's conversation endpoint is deleted from sys.conversation_enpoints catalog view."

Just how in the heck were we mortals supposed to figure this out by ourselves!! lol

No comments:

Post a Comment