예제 #1
0
        private async Task ReleaseMessage(Message msg, MessageReleaseAction releaseAction, Stopwatch roundtripStopwatch)
        {
            switch (releaseAction.Kind)
            {
            case MessageReleaseActionKind.Complete:
                await msg.SafeCompleteAsync(
                    this.subscription,
                    client,
                    success =>
                {
                    if (success)
                    {
                        this.dynamicThrottling.NotifyWorkCompleted();
                    }
                    else
                    {
                        this.dynamicThrottling.NotifyWorkCompletedWithError();
                    }
                },
                    logger,
                    roundtripStopwatch);

                break;

            case MessageReleaseActionKind.Abandon:
                await msg.SafeAbandonAsync(
                    this.subscription,
                    client,
                    success => {
                    dynamicThrottling.NotifyWorkCompletedWithError();
                },
                    logger,
                    roundtripStopwatch);

                break;

            case MessageReleaseActionKind.DeadLetter:
                await msg.SafeDeadLetterAsync(
                    this.subscription,
                    client,
                    releaseAction.DeadLetterReason,
                    releaseAction.DeadLetterDescription,
                    success => {
                    this.dynamicThrottling.NotifyWorkCompletedWithError();
                },
                    logger,
                    roundtripStopwatch);

                break;

            default:
                break;
            }
        }
예제 #2
0
        /*
         * /// <summary>
         * /// Receives the messages in an asynchronous loop and closes the session once there are no more messages.
         * /// </summary>
         * private async Task ReceiveMessagesAndCloseSession(IMessageSession session, Message message, CancellationToken cancellationToken)
         * {
         *  CountdownEvent unreleasedMessages = new CountdownEvent(1);
         *
         *  Func<bool, Task> closeSession = async (bool success) =>
         *  {
         *      Func<Task> doClose = () =>
         *          {
         *              try
         *              {
         *                  unreleasedMessages.Signal();
         *                  if (!unreleasedMessages.Wait(15000, cancellationToken))
         *                  {
         *                      logger.LogWarning("Waited for pending unreleased messages before closing session in subscription {0} but they did not complete in time", this.subscription);
         *                  }
         *              }
         *              catch (OperationCanceledException)
         *              {
         *              }
         *              finally
         *              {
         *                  unreleasedMessages.Dispose();
         *              }
         *
         *              return receiveRetryPolicy.ExecuteAsync(
         *                  async () =>
         *                  {
         *                      try {
         *                           await session.CloseAsync();
         *
         *                          if (success)
         *                          {
         *                              dynamicThrottling.NotifyWorkCompleted();
         *                          }
         *                          else
         *                          {
         *                              dynamicThrottling.NotifyWorkCompletedWithError();
         *                          }
         *
         *                          return Task.CompletedTask;
         *                      }
         *                      catch (Exception ex)
         *                      {
         *                          logger.LogError("An unrecoverable error occurred while trying to close a session in subscription {1}:\r\n{0}", ex, this.subscription);
         *                          dynamicThrottling.NotifyWorkCompletedWithError();
         *                          return Task.CompletedTask;
         *                      }
         *                  });
         *          };
         *
         *      if (this.requiresSequentialProcessing)
         *      {
         *          await doClose();
         *      }
         *      else
         *      {
         *          // Allow some time for releasing the messages before closing. Also, continue in a non I/O completion thread in order to block.
         *          await Task.Delay(200).ContinueWith(t => doClose());
         *      }
         *  };
         *
         *  // Declare an action to receive the next message in the queue or closes the session if cancelled.
         *  Func<Message, Task> receiveNext = null;
         *
         *  // Declare an action acting as a callback whenever a non-transient exception occurs while receiving or processing messages.
         *  Func<Exception, Task> recoverReceive = null;
         *
         *  // Declare an action responsible for the core operations in the message receive loop.
         *  Func<Message, Task> receiveMessage = ((msg) =>
         *  {
         *      // Use a retry policy to execute the Receive action in an asynchronous and reliable fashion.
         *      //await this.receiveRetryPolicy.ExecuteAsync
         *      //(
         *          //() =>
         *          //{
         *              try
         *              {
         *                  // Start receiving a new message asynchronously.
         *                  // Does not wait for new messages to arrive in a session. If no further messages we will just close the session.
         *                  //var msg = await session.ReceiveAsync(TimeSpan.Zero);
         *
         *                  // Process the message once it was successfully received
         *                  // Check if we actually received any messages.
         *                  if (msg != null)
         *                  {
         *                      var roundtripStopwatch = Stopwatch.StartNew();
         *
         *                      unreleasedMessages.AddCount();
         *
         *                      //return Task.Run(async () =>
         *                      //{
         *                          var releaseAction = MessageReleaseAction.AbandonMessage;
         *                          Task releaseTask = null;
         *                          try
         *                          {
         *
         *                              // Make sure the process was told to stop receiving while it was waiting for a new message.
         *                              if (!cancellationToken.IsCancellationRequested)
         *                              {
         *                                  try
         *                                  {
         *                                      releaseAction = this.InvokeMessageHandler(msg);
         *                                  }
         *                                  catch
         *                                  {
         *                                      throw;
         *                                  }
         *                                  finally
         *                                  {
         *                                      if (roundtripStopwatch.Elapsed > TimeSpan.FromSeconds(45))
         *                                      {
         *                                          this.dynamicThrottling.Penalize();
         *                                      }
         *                                  }
         *                              }
         *                          }
         *                          finally
         *                          {
         *                              // Ensure that any resources allocated by a BrokeredMessage instance are released.
         *                              if (this.requiresSequentialProcessing)
         *                              {
         *                                  //releaseTask = session.CompleteAsync(msg.SystemProperties.LockToken);
         *
         *                                  releaseTask = this.ReleaseMessage(session, msg, releaseAction,
         *                                      async () => { await receiveNext(msg); },
         *                                      async () => { await closeSession(false); },
         *                                      unreleasedMessages, roundtripStopwatch);
         *                              }
         *                              else
         *                              {
         *                                  // Receives next without waiting for the message to be released.
         *                                  releaseTask = this.ReleaseMessage(session, msg, releaseAction,
         *                                      () => { },
         *                                      () => { this.dynamicThrottling.Penalize(); },
         *                                      unreleasedMessages, roundtripStopwatch);
         *                              }
         *                          }
         *
         *                          return releaseTask;
         *                      //});
         *                  }
         *                  else
         *                  {
         *                      // no more messages in the session, close it and do not continue receiving
         *                      return closeSession(true);
         *                  }
         *              }
         *              catch (Exception ex)
         *              {
         *                  // Invoke a custom action to indicate that we have encountered an exception and
         *                  // need further decision as to whether to continue receiving messages.
         *                  return recoverReceive(ex);
         *              }
         *          //});
         *  });
         *
         *  // Initialize an action to receive the next message in the queue or closes the session if cancelled.
         *  receiveNext = async (msg) =>
         *  {
         *      if (!cancellationToken.IsCancellationRequested)
         *      {
         *          // Continue receiving and processing new messages until told to stop.
         *          await receiveMessage(msg);
         *      }
         *      else
         *      {
         *          await closeSession(true);
         *      }
         *  };
         *
         *  // Initialize a custom action acting as a callback whenever a non-transient exception occurs while receiving or processing messages.
         *  recoverReceive = async (ex) =>
         *  {
         *      // Just log an exception. Do not allow an unhandled exception to terminate the message receive loop abnormally.
         *      logger.LogError("An unrecoverable error occurred while trying to receive a new message from subscription {1}:\r\n{0}", ex, this.subscription);
         *
         *      // Cannot continue to receive messages from this session.
         *      await closeSession(false);
         *  };
         *
         *  // Start receiving messages asynchronously for the session.
         *  await receiveNext(message);
         * }
         */
        private async Task ReleaseMessage(IMessageSession session, Message msg, MessageReleaseAction releaseAction,
                                          Action completeReceive, Action onReleaseError, Stopwatch roundtripStopwatch)
        {
            switch (releaseAction.Kind)
            {
            case MessageReleaseActionKind.Complete:
                await msg.SafeCompleteAsync(
                    this.subscription,
                    session,
                    operationSucceeded =>
                {
                    if (operationSucceeded)
                    {
                        completeReceive();
                    }
                    else
                    {
                        onReleaseError();
                    }
                },
                    logger,
                    roundtripStopwatch);

                break;

            case MessageReleaseActionKind.Abandon:
                this.dynamicThrottling.Penalize();
                await msg.SafeAbandonAsync(
                    this.subscription,
                    session,
                    succeeded => onReleaseError(),
                    logger,
                    roundtripStopwatch);

                break;

            case MessageReleaseActionKind.DeadLetter:
                this.dynamicThrottling.Penalize();
                await msg.SafeDeadLetterAsync(
                    this.subscription,
                    session,
                    releaseAction.DeadLetterReason,
                    releaseAction.DeadLetterDescription,
                    operationSucceeded =>
                {
                    if (operationSucceeded)
                    {
                        completeReceive();
                    }
                    else
                    {
                        onReleaseError();
                    }
                },
                    logger,
                    roundtripStopwatch);

                break;

            default:
                break;
            }
        }