-- Ten skrypt tworzy obiekty Service Brokera i procedurę składowaną 

CREATE DATABASE LogReceiveExample
GO
USE LogReceiveExample
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'YourSecurePassword1!'
GO
ALTER DATABASE LogReceiveExample SET TRUSTWORTHY ON
GO
-- Możesz nie potrzebować tego kodu. Używam go, ponieważ pozwala uruchomić przykład w laptopie
-- niepodłączonym do domeny. Inna możliwość to utworzenie baz danych za pomocą konta uwierzytelnionego
-- użytkownika systemu SQL Server, zamiast uwierzytelnionego użytkownika systemu Windows.
-- Jeśli uruchamiasz przykład na serwerze podłączonym do domeny, ten wiersz jest niepotrzebny
ALTER AUTHORIZATION ON DATABASE::LogReceiveExample TO SA
GO

-- Tworzenie obiektów Service Brokera definiujących konwersację
CREATE MESSAGE TYPE LoginMessage
AUTHORIZATION dbo
VALIDATION = NONE
GO

CREATE CONTRACT LoginContract
AUTHORIZATION dbo
(LoginMessage SENT BY ANY)
GO

-- W tej tabeli zapisywane są rekordy przesłane od klientów
CREATE TABLE dbo.LoginRecords
(LoginEntry varchar(MAX))
GO

CREATE PROCEDURE dbo.ReceiveQueueHandler
AS 
RETURN;
GO

ALTER PROCEDURE dbo.ReceiveQueueHandler
AS
BEGIN -- ReceiveQueueHandler
	DECLARE  @dialog_handle UNIQUEIDENTIFIER, @messagetype nvarchar(128);
	-- Tworzenie zmiennej tabelowej używanej do przechowywania odebranych komunikatów
	DECLARE @LoginMessage TABLE (
	[conversation_handle] uniqueidentifier,
	message_type_name nvarchar(128),
	[message_body] varchar(MAX)
	)
	-- Główna pętla pobierająca dane
	WHILE (1 = 1)
		BEGIN	
		BEGIN TRY
			BEGIN TRANSACTION;

			WAITFOR (
				RECEIVE TOP (1000) -- Pobieranie za każdym razem wielu komunikatów to wydajniejsze podejście
					[conversation_handle], 
					[message_type_name],
					CAST(message_body AS varchar(MAX)) AS LoginEntry
				FROM LoginReceiveQueue
				INTO @LoginMessage
			), TIMEOUT 100;
			-- Jeśli nie otrzymano komunikatów, można zakończyć pracę
			IF @@ROWCOUNT = 0 
				BEGIN
					COMMIT TRANSACTION;
					BREAK;
				END
			ELSE 
				BEGIN
					-- Sprawdzanie, czy otrzymano komunikaty systemowe
					SELECT TOP (1) @dialog_handle = [conversation_handle], 
						 @messagetype = [message_type_name]
					FROM @LoginMessage
					WHERE [message_type_name] IN 
					(N'http://schemas.microsoft.com/SQL/ServiceBroker/Error', 
					N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
					-- Obsługa komunikatów systemowych
					IF @@ROWCOUNT > 0
					BEGIN 
						IF @messagetype = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
							BEGIN
								-- Rejestrowanie błędu w dzienniku aplikacji
								END CONVERSATION @dialog_handle;
							END
						ELSE IF @messagetype = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
							BEGIN
								END CONVERSATION @dialog_handle;
							END
						END
					END
					-- Wstawianie otrzymanych rekordów do tabeli
					INSERT INTO dbo.LoginRecords
					SELECT [message_body] AS LoginEntry FROM @LoginMessage
						
					COMMIT TRANSACTION
				
		END TRY 
		Begin Catch
			Rollback Transaction;
			
			DECLARE @ErrorMessage NVARCHAR(4000);
			DECLARE @ErrorSeverity INT;
			DECLARE @ErrorState INT;
			DECLARE @ErrorNumber INT;
			DECLARE @ErrorLine INT;
			DECLARE @ErrorProcedure NVARCHAR(128);
			SET		@ErrorLine = ERROR_LINE();
			SET		@ErrorSeverity = ERROR_SEVERITY();
			SET		@ErrorState = ERROR_STATE();
			SET		@ErrorNumber = ERROR_NUMBER();
			SET		@ErrorMessage = ERROR_MESSAGE();
			SET		@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), 'None');
			RAISERROR (99124, @ErrorSeverity, 1 , @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorProcedure, @ErrorLine, @ErrorMessage);
		End Catch;
	END -- WHILE
END -- ReceiveQueueHandler
GO


CREATE QUEUE LoginReceiveQueue
WITH STATUS=ON,
     RETENTION=OFF,
     ACTIVATION
         (STATUS=ON,
          PROCEDURE_NAME=dbo.ReceiveQueueHandler,
          MAX_QUEUE_READERS=10,
          EXECUTE AS OWNER),
     POISON_MESSAGE_HANDLING (STATUS = ON);
GO

CREATE SERVICE LoginReceiveSvc
AUTHORIZATION dbo
ON QUEUE dbo.LoginReceiveQueue
(LoginContract)
GO

-- SELECT * FROM LoginReceiveQueue



