Why is the activation stored procedure not triggering on my SQL Server QUEUE?
I am new to SERVICE BROKER and QUEUE functionality in SQL Server. I've mostly been trying to follow some examples:
- https://sqlperformance.com/2014/03/sql-performance/configuring-service-broker
- https://www.sqlshack.com/using-the-sql-server-service-broker-for-asynchronous-processing/
I can get the manual processing working just fine. If I call a SP that processes the queue, it works as expected. If I understand it correctly, setting the ACTIVATION, PROCEDURE_NAME
for the QUEUE should set this to automatically process messages sent to the queue. However, that is NOT what I am seeing in SQL SERVER v12.0.6433.1
BEGIN TRANSACTION;
CREATE TABLE #DONE
(
ID INT
);
CREATE MESSAGE TYPE CUSTOM_TYPE
AUTHORIZATION XYZ_USER
VALIDATION = NONE;
GO
CREATE CONTRACT POST_CUSTOM_TYPE_MESSAGE_CONTRACT
(CUSTOM_TYPE SENT BY ANY);
GO
CREATE PROCEDURE TESTING.PROCESS_QUEUE AS
BEGIN
DECLARE @HANDLE UNIQUEIDENTIFIER;
DECLARE @MESSAGE_TYPE SYSNAME;
DECLARE @MESSAGE INT;
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION;
WAITFOR (
RECEIVE TOP (1)
@HANDLE = CONVERSATION_HANDLE,
@MESSAGE_TYPE = MESSAGE_TYPE_NAME,
@MESSAGE = MESSAGE_BODY FROM TESTING.CUSTOM_QUEUE), TIMEOUT 1000;
IF (@@ROWCOUNT = 0)
BEGIN
COMMIT TRANSACTION;
BREAK;
END
INSERT INTO #DONE (ID) VALUES (@MESSAGE);
COMMIT TRANSACTION;
END
END
GO
CREATE QUEUE TESTING.CUSTOM_QUEUE
WITH STATUS = ON,
RETENTION = OFF,
ACTIVATION (
PROCEDURE_NAME = TESTING.PROCESS_QUEUE,
MAX_QUEUE_READERS = 5,
EXECUTE AS SELF
),
POISON_MESSAGE_HANDLING ( STATUS = OFF );
GO
CREATE SERVICE CUSTOM_TYPE_SERVICE
AUTHORIZATION XYZ_USER
ON QUEUE TESTING.CUSTOM_QUEUE
(POST_CUSTOM_TYPE_MESSAGE_CONTRACT);
GO
CREATE PROCEDURE TESTING.INSERT_INTO_QUEUE @ID INT AS
BEGIN
BEGIN TRANSACTION;
DECLARE @SERVICE SYSNAME;
SET @SERVICE = 'CUSTOM_TYPE_SERVICE';
DECLARE @CONTRACT SYSNAME;
SET @CONTRACT = 'POST_CUSTOM_TYPE_MESSAGE_CONTRACT';
DECLARE @HANDLE UNIQUEIDENTIFIER;
BEGIN
DIALOG CONVERSATION @HANDLE
FROM SERVICE @SERVICE
TO SERVICE @SERVICE
ON CONTRACT @CONTRACT
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @HANDLE MESSAGE TYPE CUSTOM_TYPE(@ID);
COMMIT TRANSACTION;
END
GO
EXEC TESTING.INSERT_INTO_QUEUE 1;
EXEC TESTING.INSERT_INTO_QUEUE 2;
EXEC TESTING.INSERT_INTO_QUEUE 3;
SELECT *
FROM TESTING.CUSTOM_QUEUE;
SELECT * FROM #DONE;
ROLLBACK TRANSACTION;
I see 3 records in TESTING.CUSTOM_QUEUE
and 0 records in #DONE
.
Am I overlooking something here? Or is there a missing DB setting I need? I am wondering if using a custom SCHEMA (instead of DBO) is causing issues as well. Does anyone have any idea what is going on here?
Solution 1:
Closing the loop based on the brief conversation in the comments above, the key observation is that you're inserting into a queue. The processing of that queue by (in this case internal activation) is inherently asynchronous. If you check the queue right after having put items into it, odds are that those items will not have been processed yet. But if you wait some time, whatever is processing the queue should do what it needs to.
Here is a great article explaining how activation happens.