public async Task ProcessEventsAsync(EventProcessorHostPartition context, IEnumerable <EventData> messages) { var events = messages.ToArray(); var triggerInput = new EventHubTriggerInput { Events = events, PartitionContext = context }; TriggeredFunctionData input = null; if (_singleDispatch) { // Single dispatch int eventCount = triggerInput.Events.Length; List <Task> invocationTasks = new List <Task>(); for (int i = 0; i < eventCount; i++) { if (_cts.IsCancellationRequested) { break; } EventHubTriggerInput eventHubTriggerInput = triggerInput.GetSingleEventTriggerInput(i); input = new TriggeredFunctionData { TriggerValue = eventHubTriggerInput, TriggerDetails = eventHubTriggerInput.GetTriggerDetails(context) }; Task task = TryExecuteWithLoggingAsync(input, triggerInput.Events[i]); invocationTasks.Add(task); } // Drain the whole batch before taking more work if (invocationTasks.Count > 0) { await Task.WhenAll(invocationTasks).ConfigureAwait(false); } } else { // Batch dispatch input = new TriggeredFunctionData { TriggerValue = triggerInput, TriggerDetails = triggerInput.GetTriggerDetails(context) }; using (_logger.BeginScope(GetLinksScope(triggerInput.Events))) { await _executor.TryExecuteAsync(input, _cts.Token).ConfigureAwait(false); } } // Checkpoint if we processed any events. // Don't checkpoint if no events. This can reset the sequence counter to 0. // Note: we intentionally checkpoint the batch regardless of function // success/failure. EventHub doesn't support any sort "poison event" model, // so that is the responsibility of the user's function currently. E.g. // the function should have try/catch handling around all event processing // code, and capture/log/persist failed events, since they won't be retried. if (events.Any()) { await CheckpointAsync(events.Last(), context).ConfigureAwait(false); } }
public async Task ProcessEventsAsync(EventProcessorHostPartition context, IEnumerable <EventData> messages) { var events = messages.ToArray(); EventData eventToCheckpoint = null; var triggerInput = new EventHubTriggerInput { Events = events, ProcessorPartition = context }; if (_singleDispatch) { // Single dispatch int eventCount = triggerInput.Events.Length; for (int i = 0; i < eventCount; i++) { if (_cts.IsCancellationRequested) { break; } EventHubTriggerInput eventHubTriggerInput = triggerInput.GetSingleEventTriggerInput(i); TriggeredFunctionData input = new TriggeredFunctionData { TriggerValue = eventHubTriggerInput, TriggerDetails = eventHubTriggerInput.GetTriggerDetails(context) }; await _executor.TryExecuteAsync(input, _cts.Token).ConfigureAwait(false); eventToCheckpoint = events[i]; } } else { // Batch dispatch TriggeredFunctionData input = new TriggeredFunctionData { TriggerValue = triggerInput, TriggerDetails = triggerInput.GetTriggerDetails(context) }; await _executor.TryExecuteAsync(input, _cts.Token).ConfigureAwait(false); eventToCheckpoint = events.LastOrDefault(); } // Checkpoint if we processed any events. // Don't checkpoint if no events. This can reset the sequence counter to 0. // Note: we intentionally checkpoint the batch regardless of function // success/failure. EventHub doesn't support any sort "poison event" model, // so that is the responsibility of the user's function currently. E.g. // the function should have try/catch handling around all event processing // code, and capture/log/persist failed events, since they won't be retried. if (eventToCheckpoint != null) { await CheckpointAsync(eventToCheckpoint, context).ConfigureAwait(false); } }