private async Task CheckpointAsync(EventData checkpointEvent, EventProcessorHostPartition context)
            {
                bool checkpointed = false;

                if (_batchCheckpointFrequency == 1)
                {
                    await context.CheckpointAsync(checkpointEvent).ConfigureAwait(false);

                    checkpointed = true;
                }
                else
                {
                    // only checkpoint every N batches
                    if (++_batchCounter >= _batchCheckpointFrequency)
                    {
                        _batchCounter = 0;
                        await context.CheckpointAsync(checkpointEvent).ConfigureAwait(false);

                        checkpointed = true;
                    }
                }
                if (checkpointed)
                {
                    _logger.LogDebug(GetOperationDetails(context, "CheckpointAsync"));
                }
            }
            public Task ProcessErrorAsync(EventProcessorHostPartition context, Exception error)
            {
                string errorDetails = $"Processing error (Partition Id: '{context.PartitionId}', Owner: '{context.Owner}', EventHubPath: '{context.EventHubPath}').";

                Utility.LogException(error, errorDetails, _logger);

                return(Task.CompletedTask);
            }
            public Task CloseAsync(EventProcessorHostPartition context, ProcessingStoppedReason reason)
            {
                // signal cancellation for any in progress executions
                _cts.Cancel();

                _logger.LogDebug(GetOperationDetails(context, $"CloseAsync, {reason.ToString()}"));
                return(Task.CompletedTask);
            }
Пример #4
0
            private static string GetOperationDetails(EventProcessorHostPartition context, string operation)
            {
                StringWriter sw = new StringWriter();

                using (JsonTextWriter writer = new JsonTextWriter(sw)
                {
                    Formatting = Formatting.None
                })
                {
                    writer.WriteStartObject();
                    WritePropertyIfNotNull(writer, "operation", operation);
                    writer.WritePropertyName("partitionContext");
                    writer.WriteStartObject();
                    WritePropertyIfNotNull(writer, "partitionId", context.PartitionId);
                    WritePropertyIfNotNull(writer, "owner", context.Owner);
                    WritePropertyIfNotNull(writer, "eventHubPath", context.EventHubPath);
                    writer.WriteEndObject();

                    // Log partition checkpoint info
                    if (context.Checkpoint != null)
                    {
                        // leave the property name as lease for backcompat with T1
                        writer.WritePropertyName("lease");
                        writer.WriteStartObject();
                        WritePropertyIfNotNull(writer, "offset", context.Checkpoint.Value.Offset.ToString(CultureInfo.InvariantCulture));
                        WritePropertyIfNotNull(writer, "sequenceNumber", context.Checkpoint.Value.SequenceNumber.ToString(CultureInfo.InvariantCulture));
                        writer.WriteEndObject();
                    }

                    // Log RuntimeInformation if EnableReceiverRuntimeMetric is enabled
                    if (context.LastEnqueuedEventProperties != null)
                    {
                        writer.WritePropertyName("runtimeInformation");
                        writer.WriteStartObject();
                        WritePropertyIfNotNull(writer, "lastEnqueuedOffset", context.LastEnqueuedEventProperties.Offset?.ToString(CultureInfo.InvariantCulture));
                        WritePropertyIfNotNull(writer, "lastSequenceNumber", context.LastEnqueuedEventProperties.SequenceNumber?.ToString(CultureInfo.InvariantCulture));
                        WritePropertyIfNotNull(writer, "lastEnqueuedTimeUtc", context.LastEnqueuedEventProperties.EnqueuedTime?.ToString("o", CultureInfo.InvariantCulture));
                        writer.WriteEndObject();
                    }
                    writer.WriteEndObject();
                }
                return(sw.ToString());
            }
            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 Task OpenAsync(EventProcessorHostPartition context)
 {
     _logger.LogDebug(GetOperationDetails(context, "OpenAsync"));
     return(Task.CompletedTask);
 }
Пример #7
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);
                }
            }