Commit c7bd951b authored by dwentzel's avatar dwentzel

adding monolog_pattern.sql

parent 58a08048
/*
This is the source code for http://www.davewentzel.com/content/service-broker-demystified-can-i-model-monologs-yes-you-can
This demos the equivalent of a "monolog", which is the most common messaging pattern, and one that Service Broker
does not support out-of-the-box. This pattern is still a dialog, but is the simplest form.
*/
--basic setup
USE master
GO
CREATE DATABASE SBTest
GO
ALTER DATABASE SBTest SET NEW_BROKER
GO
USE SBTest
GO
--Even though we want to model a monolog we still need a sender and receiver.
--The receiver is where the important work is done. The sender is merely there
--for completeness in the dialog.
--Set it up...
CREATE QUEUE SenderQ;
CREATE QUEUE ReceiverQ;
CREATE SERVICE SenderSvc ON QUEUE SenderQ;
CREATE SERVICE ReceiverSvc ON QUEUE ReceiverQ ([DEFAULT]);
GO
--to get the monolog pattern to work the Sender must have an activator proc.
--It's sole job is to E
CREATE PROCEDURE SenderQ_ActivatorProcedure
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@mt sysname,
@h uniqueidentifier;
--this can be made far more performant and resilient, but this is the most
--basic pattern
RECEIVE TOP (1)
@mt = message_type_name,
@h = conversation_handle
FROM SenderQ;
IF @mt = (N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
BEGIN
END CONVERSATION @h;
END
END;
GO
--now attach the activator proc to the Q.
--Here we set the STATUS to OFF for the demo, we'll enable it below.
ALTER QUEUE SenderQ
WITH ACTIVATION
(
procedure_name = dbo.SenderQ_ActivatorProcedure,
max_queue_readers = 1,
EXECUTE AS OWNER,
STATUS = OFF
);
GO
--The sender is responsible for pushing the asynchronous message to the receiver.
--The COMMIT is the "synchronous" transaction boundary. The "message" is the asynchronous
--process we want to run in an autonomous transaction.
BEGIN TRANSACTION
DECLARE @h UNIQUEIDENTIFIER;
BEGIN DIALOG @h
FROM SERVICE [SenderSvc]
TO SERVICE 'ReceiverSvc'
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @h ('This is the message payload');
--note that we SEND but we do *not* END CONVERSATION.
--if we did that would be the dreaded "fire-and-forget" anti-pattern.
--Remember: The target always ENDs CONVERSATION first!
--END CONVERSATION @h;
COMMIT;
--everything seems ok so far
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from SenderQ
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from ReceiverQ
--now receiver processes the message
BEGIN TRAN
DECLARE @rh UNIQUEIDENTIFIER;
WAITFOR(
RECEIVE
TOP(1) @rh = conversation_handle
FROM ReceiverQ
), TIMEOUT 2000 ;
--do whatever work you want to do HERE
--note that we first END CONVERSATION on the receiver side.
END CONVERSATION @rh;
COMMIT
GO
--everything still looks good
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from SenderQ
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from ReceiverQ
--the activator is not yet enabled on the SenderQ which is why we still
--see it, waiting for acknowledgement.
--Let's enable the activator and check again
ALTER QUEUE SenderQ WITH ACTIVATION (STATUS = ON);
GO
--and now the message is automatically acknowledged and the conversation is ended
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from SenderQ
select conversation_handle, message_type_name, convert(xml,message_body) as MsgBody from ReceiverQ
--basic cleanup
USE master;
GO
DROP DATABASE SBTest;
GO
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment