protected virtual async Task ExecuteMessageHandlerAsync( EventArgs messageEventArgs, ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc, bool automaticFinalizationEnabled = true ) { messageEventArgs.AssertNotNull(nameof(messageEventArgs)); receivedItemHandlerAsyncDelegateFunc.AssertNotNull(nameof(receivedItemHandlerAsyncDelegateFunc)); AzureServiceBusReceivedItem <TUniqueIdentifier, TPayload> azureServiceBusReceivedItem = null; //FIRST attempt to convert the Message into an AzureServiceBus Received Item.... try { //Initialize the MessageHandler facade for processing the Azure Service Bus message... azureServiceBusReceivedItem = await CreateReceivedItemAsync( messageEventArgs, //Force Dead-lettering if there is any issue with initialization! true ).AssertNotNull(nameof(azureServiceBusReceivedItem)); } catch (Exception exc) { var messageException = new Exception("The message could not be correctly initialized due to unexpected exception." + " It must be Dead lettered to prevent blocking of the Service Bus as it will never be" + " processed successfully.", exc); this.Options.ErrorHandlerCallback?.Invoke(messageException); } //IF the Received Item is successfully initialized then process it! if (azureServiceBusReceivedItem != null) { try { //Execute the delegate to handle/process the published item... await receivedItemHandlerAsyncDelegateFunc(azureServiceBusReceivedItem).ConfigureAwait(false); //If necessary, we need to Finalize the item with Azure Service Bus (Complete/Abandon) based on the Status returned on the item! if (automaticFinalizationEnabled && !azureServiceBusReceivedItem.IsStatusFinalized) { await azureServiceBusReceivedItem.SendFinalizedStatusToAzureServiceBusAsync().ConfigureAwait(false); } } catch (Exception exc) { this.Options.ErrorHandlerCallback?.Invoke(exc); //Always attempt to Reject/Abandon the message if any unhandled exceptions are thrown... if (!azureServiceBusReceivedItem.IsStatusFinalized) { //Finalize the status as set by the Delegate function if it's not already Finalized! //NOTE: We ALWAYS do this even if autoMessageFinalizationEnabled is false to prevent BLOCKING and risk of Infinite Loops... await azureServiceBusReceivedItem.SendFinalizedStatusToAzureServiceBusAsync().ConfigureAwait(false); } } } }
public virtual Task StartReceivingAsync( ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc, CancellationToken cancellationToken = default ) { if (this.IsProcessing) { return(Task.CompletedTask); } return(StartReceivingInternalAsync(receivedItemHandlerAsyncDelegateFunc, cancellationToken: cancellationToken)); }
protected virtual async Task StartReceivingInternalAsync( ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc, bool autoMessageFinalizationEnabled = true, CancellationToken cancellationToken = default ) { //Ensure we are set to have started Processing... this.IsProcessing = true; //Validate handler and other references... receivedItemHandlerAsyncDelegateFunc.AssertNotNull(nameof(receivedItemHandlerAsyncDelegateFunc)); //Complete full Handler Initialization with provided options, etc... //NOTE: IF FIFO Processing is enabled we use Azure Session Processor; otherwise default Processor is used. if (Options.FifoEnforcedReceivingEnabled) { if (this.ServiceBusSessionProcessor == null) { this.ServiceBusSessionProcessor = GetAzureServiceBusSessionProcessor(); this.ServiceBusSessionProcessor.ProcessMessageAsync += async(messageEventArgs) => { await ExecuteMessageHandlerAsync( //Note: We Must use the MessageSession as the Client for processing messages with the Locked Session! messageEventArgs, receivedItemHandlerAsyncDelegateFunc, autoMessageFinalizationEnabled ).ConfigureAwait(false); }; //Wire up the Error/Exception Handler... this.ServiceBusSessionProcessor.ProcessErrorAsync += ExceptionReceivedHandlerAsync; } //Kick off processing!!! if (!this.ServiceBusSessionProcessor.IsProcessing) { await this.ServiceBusSessionProcessor.StartProcessingAsync(cancellationToken); } } else { if (this.ServiceBusProcessor == null) { this.ServiceBusProcessor = GetAzureServiceBusProcessor(); //Wire up the Handler... this.ServiceBusProcessor.ProcessMessageAsync += async(messageEventArgs) => { await ExecuteMessageHandlerAsync( messageEventArgs, receivedItemHandlerAsyncDelegateFunc, autoMessageFinalizationEnabled ).ConfigureAwait(false); }; //Wire up the Error/Exception Handler... this.ServiceBusProcessor.ProcessErrorAsync += ExceptionReceivedHandlerAsync; } //Kick off processing!!! if (!this.ServiceBusProcessor.IsProcessing) { await this.ServiceBusProcessor.StartProcessingAsync(cancellationToken); } } }