public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages)
            {
                var triggerInput = new EventHubTriggerInput
                {
                    Events           = messages.ToArray(),
                    PartitionContext = context
                };

                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;
                        }

                        var input = new TriggeredFunctionData
                        {
                            TriggerValue = triggerInput.GetSingleEventTriggerInput(i)
                        };
                        Task task = _executor.TryExecuteAsync(input, _cts.Token);
                        invocationTasks.Add(task);
                    }

                    // Drain the whole batch before taking more work
                    if (invocationTasks.Count > 0)
                    {
                        await Task.WhenAll(invocationTasks);
                    }
                }
                else
                {
                    // Batch dispatch
                    var input = new TriggeredFunctionData
                    {
                        TriggerValue = triggerInput
                    };

                    await _executor.TryExecuteAsync(input, _cts.Token);
                }
                // Dispose all messages to help with memory pressure. If this is missed, the finalizer thread will still get them.
                bool hasEvents = false;

                foreach (var message in messages)
                {
                    hasEvents = true;
                    message.Dispose();
                }

                // Checkpoint if we procesed 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 (hasEvents)
                {
                    await CheckpointAsync(context);
                }
            }
            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);
                }
            }
Example #3
0
            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);
                }
            }