One of the basics of building a distributed application that uses the asynchronous communication can be expressed as Do not wait actively for any event! This way, the natural solution based on SQL Service Broker is to use the activation of a stored procedure by the message that arrived to the queue.
The Lesson 2: Creating an Internal Activation Procedure from the official Microsoft tutorial shows how to bind the stored procedure to the message queue. It also suggests the way how the sp should be implemented.
(I am new to SQL. But should not be there one more BEGIN after the CREATE PROCEDURE... AS, and one more END before the GO?)
Do I understand it corectly? See my questions below the code…
CREATE PROCEDURE TargetActivProc
AS
DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
DECLARE @RecvReqMsg NVARCHAR(100);
DECLARE @RecvReqMsgName sysname;
WHILE (1=1)
BEGIN
BEGIN TRANSACTION;
WAITFOR
( RECEIVE TOP(1)
@RecvReqDlgHandle = conversation_handle,
@RecvReqMsg = message_body,
@RecvReqMsgName = message_type_name
FROM TargetQueueIntAct
), TIMEOUT 5000;
IF (@@ROWCOUNT = 0)
BEGIN
ROLLBACK TRANSACTION;
BREAK;
END
IF @RecvReqMsgName =
N'//AWDB/InternalAct/RequestMessage'
BEGIN
DECLARE @ReplyMsg NVARCHAR(100);
SELECT @ReplyMsg =
N'<ReplyMsg>Message for Initiator service.</ReplyMsg>';
SEND ON CONVERSATION @RecvReqDlgHandle
MESSAGE TYPE
[//AWDB/InternalAct/ReplyMessage]
(@ReplyMsg);
END
ELSE IF @RecvReqMsgName =
N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
BEGIN
END CONVERSATION @RecvReqDlgHandle;
END
ELSE IF @RecvReqMsgName =
N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
END CONVERSATION @RecvReqDlgHandle;
END
COMMIT TRANSACTION;
END
GO
When the message arrives, the procedure is called, and it enters to the "infinite" loop. Actually, the loop is not infinite because of the BREAK after the ROLLBACK when no data arrived (after the TIMEOUT).
If the data arrived, the BREAK is skipped. If the expected message arrived, the reply is sent back. If the ...EndDialog or ...Error message is received, the END CONVERSATION is executed. Can also some other kind of message be observed here?
As some message arrived (and was processed) the transaction is commited.
But why the loop now? Is the intention to process the other messages that got stuck in the queue because of the broken communication line in the past? Or because of more messages came at once and could not be processed so quickly?
What happens when another message is queued up, and the stored procedure is still running. Is another working process assigned for its processing? Can another stored procedure be launched in parallel? If yes, then why the loop?
Thanks for your help, Petr
Internal activation is not like a trigger. Specifically, the activated procedure does not get launched for each message that arrived. Instead the procedure is launched when there is something to process and is supposed to dequeue messages contiguously (in a loop) while the SSB infrastructure is monitoring the progress and, if necessary, launches a second procedure to help, up to the max specified. See Understanding Queue Monitors.
Having a loop in the activated procedure is not not strictly required, things should work fine even w/o the loop. The loop should perform better in a very busy environment. See also this old MSDN discussion.