Saturday, June 30, 2007

Service Broker--Within a database

Database Name: Adata

USE Adata
GO
/* Master Key must be created. */
CREATE MASTER KEY ENCRYPTION BY PASSWORD='password'
GO
ALTER DATABASE Adata SET ENABLE_BROKER
GO
CREATE MESSAGE TYPE [initMessage] VALIDATION=NONE;
GO
CREATE MESSAGE TYPE [respMessage] VALIDATION=NONE;
GO
CREATE CONTRACT mContract
( [initMessage] sent by Initiator,[respMessage] sent by target )
GO

USE Adata
GO
CREATE QUEUE mQueue WITH STATUS=ON,RETENTION=ON
GO
CREATE QUEUE pQueue WITH STATUS=ON, RETENTION=ON;
GO
CREATE SERVICE mService ON QUEUE mQueue(mContract);
GO
CREATE SERVICE pService ON QUEUE pQueue(mContract);
GO

/* CODE BLOCK (1) */

USE Adata
GO
SET NOCOUNT ON
DECLARE @id uniqueidentifier
BEGIN TRAN
BEGIN DIALOG @id
FROM SERVICE mService TO SERVICE 'pService'
ON CONTRACT [mContract] WITH LIFETIME=600;

SEND ON CONVERSATION @id
MESSAGE TYPE initMessage
(N'service is good.')
COMMIT

GO


/* CODE BLOCK (2) */

USE Adata
GO
SET NOCOUNT ON
DECLARE @id uniqueidentifier;
DECLARE @body nvarchar(max);
DECLARE @type sysname;
BEGIN TRAN
WAITFOR(
RECEIVE TOP (1)
@type=message_type_name,
@id=conversation_handle,
@body=message_body
FROM [pQueue]
),TIMEOUT 60;

SEND ON CONVERSATION @id
MESSAGE TYPE [respMessage]
(N'what matters?');

END CONVERSATION @id;

COMMIT

GO

Understand the message queue
Run code block (1)
SELECT conversation_handle,service_name FROM mQueue
SELECT conversation_handle,service_name FROM pQueue











Both mQueue and pQueue include the same conversation_handle. Each queue includes many records, because the message has not been retrieved.

Modifying the CODE BLOCK (2) as following:
/*SEND ON CONVERSATION @id
MESSAGE TYPE [respMessage]
(N'what matters?');*/

Run the code block (2)



The pQueue is empty because all messages are retrieved and END CONVERSATION @id statement. However, messages are still in the queue until timeout.


To avoid the piling up of the message in a queue, END CONVERSATION @id statement should be added in code block (1).

END CONVERSATION @id in CODE BLOCK (2) does not delete the entry in sending queue (mQueue).

If you can retrieve the conversation_handle a queue, you can run:

SEND ON CONVERSATION @id
MESSAGE TYPE [respMessage]
(N'what matters?');

Both mQueue and pQueue have conversation_handle.

When you send a message and run the END CONVERSATION @id statement, the entry in sending queue is deleted.

But the entry is still in receiving queue. When you run the CODE BLOCK (2) and run the END CONVERSATION @id, the entry in receiving queue is deleted.