гуру, вопрос по Broker

Winnipuh
Дата: 22.01.2009 12:32:26
процедура из БОЛ

CREATE PROCEDURE ProcessExpenseReport
AS
BEGIN
  WHILE (1 = 1)
    BEGIN
      BEGIN TRANSACTION ;
      DECLARE @conversationHandle UNIQUEIDENTIFIER ;
      DECLARE @messageBody VARBINARY(MAX) ;
      DECLARE @messageTypeName NVARCHAR(256) ;

      SAVE TRANSACTION UndoReceive ;

        WAITFOR ( 
                  RECEIVE TOP(1)
                    @messageTypeName = message_type_name,
                    @messageBody = message_body,
                    @conversationHandle = conversation_handle
                    FROM ExpenseQueue
                 ), TIMEOUT 500 ;

        IF @@ROWCOUNT = 0
        BEGIN
          ROLLBACK TRANSACTION ;
          BREAK ;
        END ;

        -- Typical message processing loop: dispatch to a stored
        -- procedure based on the message type name.  End conversation
        -- with an error for unknown message types.

        -- Process expense report messages. If processing fails,
        -- roll back to the save point and track the failed message.

        IF (@messageTypeName =
              '//Adventure-Works.com/AccountsPayable/ExpenseReport')
          BEGIN
            DECLARE @expenseReport NVARCHAR(MAX) ;
            SET @expenseReport = CAST(@messageBody AS NVARCHAR(MAX)) ;
            EXEC AdventureWorks.dbo.AddExpenseReport
              @report = @expenseReport ;
            IF @@ERROR <> 0
             BEGIN
               ROLLBACK TRANSACTION UndoReceive ;
               EXEC TrackMessage @conversationHandle ;
             END ;
            ELSE
             BEGIN
               EXEC AdventureWorks.dbo.ClearMessageTracking
                 @conversationHandle ;
             END ;
           END ;
        ELSE

        -- For error messages and end dialog messages, end the
        -- conversation.

        IF (@messageTypeName =
              'http://schemas.microsoft.com/SQL/ServiceBroker/Error' OR
             @messageTypeName =
              'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
          BEGIN
            END CONVERSATION @conversationHandle ;
            EXEC dbo.ClearMessageTracking @conversationHandle ;
          END ;


         COMMIT TRANSACTION ;
    END ;
END ;


хочу сделать так, чтобы в случае плохого сообщения оно все равно забиралось из очереди, чтобы действия процедур-обработчиков откатывались, но чтобы можно ыбло сделать записи в таблицах-логах.

Что если сделать так:

CREATE PROCEDURE ProcessExpenseReport
AS
BEGIN
  WHILE (1 = 1)
    BEGIN
      BEGIN TRANSACTION ;
      DECLARE @conversationHandle UNIQUEIDENTIFIER ;
      DECLARE @messageBody VARBINARY(MAX) ;
      DECLARE @messageTypeName NVARCHAR(256) ;

------------------      [i]SAVE TRANSACTION UndoReceive ;[/i]

        WAITFOR ( 
                  RECEIVE TOP(1)
                    @messageTypeName = message_type_name,
                    @messageBody = message_body,
                    @conversationHandle = conversation_handle
                    FROM ExpenseQueue
                 ), TIMEOUT 500 ;

        IF @@ROWCOUNT = 0
        BEGIN
          ROLLBACK TRANSACTION ;
          BREAK ;
        END ;

[b]     SAVE TRANSACTION UndoReceive ;[/b]
        -- Typical message processing loop: dispatch to a stored
        -- procedure based on the message type name.  End conversation
        -- with an error for unknown message types.

        -- Process expense report messages. If processing fails,
        -- roll back to the save point and track the failed message.

        IF (@messageTypeName =
              '//Adventure-Works.com/AccountsPayable/ExpenseReport')
          BEGIN
            DECLARE @expenseReport NVARCHAR(MAX) ;
            SET @expenseReport = CAST(@messageBody AS NVARCHAR(MAX)) ;
            EXEC AdventureWorks.dbo.AddExpenseReport
              @report = @expenseReport ;
            IF @@ERROR <> 0
             BEGIN
               ROLLBACK TRANSACTION UndoReceive ;
               EXEC TrackMessage @conversationHandle ;
             END ;
            ELSE
             BEGIN
               EXEC AdventureWorks.dbo.ClearMessageTracking
                 @conversationHandle ;
             END ;
           END ;
        ELSE

        -- For error messages and end dialog messages, end the
        -- conversation.

        IF (@messageTypeName =
              'http://schemas.microsoft.com/SQL/ServiceBroker/Error' OR
             @messageTypeName =
              'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
          BEGIN
            END CONVERSATION @conversationHandle ;
            EXEC dbo.ClearMessageTracking @conversationHandle ;
          END ;


         COMMIT TRANSACTION ;
    END ;
END ;
Mnior
Дата: 22.01.2009 17:05:25
Winnipuh
Что если ...
Вы так говорите словно есть некоторый обязательный способ ("серебрянная пуля") работы с очередями. И при чём здесь очереди?:
Сделать А. Затем Б. Если Б вызвало ошибку, то откатить Б и сделать В.
BEGIN TRANSACTION;
-- Get Message (Receive)
SAVE TRANSACTION Undo;
-- BEGIN TRY
	-- Do something (EXEC)
-- END TRY BEGIN CATCH
	ROLLBACK TRANSACTION Undo;
	-- Save to LOG
-- END CATCH
COMMIT TRANSACTION;
Ну и?!
А что делать, если транзакция не фиксируемая? :)
А сообшения можно потерять? - Может ну их транзакции?
Winnipuh
хочу сделать так, чтобы в случае плохого сообщения оно все равно забиралось из очереди
Ну так блин EXEC TrackMessage @conversationHandle; это и делает после 3х попыток. Переделайте эту процедуру по своему.