Tuesday, March 20, 2012

quiesce then End Conversation

I want to reuse conversations to minimize overhead during bursts of activity. Remus' article on reusing conversations (http://blogs.msdn.com/remusrusanu/archive/2007/05/02/recycling-conversations.aspx) is great. (I know you are reading this Remus, thanks.)

I was wondering if there is a simpler way of ending a cached conversation - Quiesce the conversation (Stop using it), then after some period of time, end it.

I create a conversation, cache it in RLY_Conversations, and use it for 50 seconds. After 1 minute, the dialog timer servicing proc ends the conversation. There will be no messages sent around the time the End Conversation takes place, thus no race conditions.

Do you see any problems with this method?

Select @.DialogHandle = [conversation_handle]

From RLY_Conversations

Where TableName = @.TableName and IsActive = 1 And

CreatedTmstp > dateadd(ss, -50, getdate())

if @.DialogHandle is null

Begin

-- initialize a conversation and record it in our reuse table

BEGIN DIALOG CONVERSATION @.DialogHandle

FROM SERVICE FirstHostRelayService

TO SERVICE 'SecondHostRelayService'

ON CONTRACT RelayContractSentByAny

WITH ENCRYPTION=OFF ;

-- cache the dialog handle to minimize dialog creation overhead.

Insert into RLY_Conversations (

TableName, conversation_handle, conversation_id, is_initiator, service_contract_id,

conversation_group_id, service_id, lifetime, state, state_desc, IsActive, CreatedBy, CreatedTmstp

)

Select @.TableName, conversation_handle, conversation_id, is_initiator, service_contract_id,

conversation_group_id, service_id, lifetime, state, state_desc, 1, 'Setup', getdate()

From sys.conversation_endpoints

Where conversation_handle = @.DialogHandle;

-- initiate housekeeping process

BEGIN CONVERSATION TIMER ( @.DialogHandle )

TIMEOUT = 60;

End

Hi Bill,

Thanks for reading my blog!

I'm not sure I follow the question, but if I understand correctly you begin a dialog, use it for 50 seconds and then end it, based on th timer, 10 seconds later. If that is correct, I would recommend against it.

For once, if the target never sends any message you should not end the dialog from the sender's side first, as per http://blogs.msdn.com/remusrusanu/archive/2006/04/06/570578.aspx. I can't stress the importance of this, I am faced every day with people reporting some problem that could had been avoided by not using this fire-and-forget pattern.

Second, altohugh I'm not familiar with your application, I think you are running on some very tight budgets of time when relying on the application to finish it's work in 50 seconds and allowing only a 10 seconds margin for the timer to pop and quiesce the dialog. The SEND operations could be delayed by a lock, the application logic might be delayed a bit, the database might hit a log growth or a datafile growth, there might be a temporary resource constraint (memory, execution threads etc). Anything that delayes the 50 seconds SEND time might cause a race between a SEND and the timer trying to quiesce operation. Is just my opinion that in the persisted, transacted database operations world anything measured in seconds will eventually run into problems in production, even more so when talking about asynchronous operations like messaging. How about starting the 60 seconds timer after every SEND? Using BEGIN CONVERSATION TIMER again when a timer is active has the effect of resting the timer to the new value (there is only one timer per dialog). This way the timer would be continously updated and if no SEND occurs for 60 seconds, the timer will pop.

HTH,

~ Remus

No comments:

Post a Comment