/// <summary> /// Seeds the Event Hub partition with enough events to satisfy the read operations the test scenario /// is expected to perform. /// </summary> /// /// <param name="producer">The producer to use for publishing events; ownership is assumed to be retained by the caller.</param> /// /// <remarks> /// This method makes heavy use of class state, including the /// test environment and command line options. /// </remarks> /// private async Task SeedEventsToBeReadAsync(EventHubProducerClient producer) { // Calculate the number of events needed to satisfy the number of events per iteration // and then buffer it to allow for the warm-up. var eventCount = Options.BatchSize * Options.Iterations * 3; var eventBody = EventGenerator.CreateRandomBody(Options.BodySize); var batchOptions = new CreateBatchOptions { PartitionId = PartitionId }; foreach (var eventData in EventGenerator.CreateEventsFromBody(eventCount, eventBody)) { using var batch = await producer.CreateBatchAsync(batchOptions).ConfigureAwait(false); // Fill the batch with as many events that will fit. while (batch.TryAdd(EventGenerator.CreateEventFromBody(eventBody))) { } // If there were no events in the batch, then a single event was generated that is too large to // ever send. In this context, it will be detected on the first TryAdd call, since events are // sharing a common body. if (batch.Count == 0) { throw new InvalidOperationException("There was an event too large to fit into a batch."); } await producer.SendAsync(batch).ConfigureAwait(false); } }
/// <summary> /// Executes the performance test scenario asynchronously. /// </summary> /// /// <param name="cancellationToken">The token used to signal when cancellation is requested.</param> /// public async override Task <int> RunBatchAsync(CancellationToken cancellationToken) { using var batch = await s_producer.CreateBatchAsync(_batchOptions, cancellationToken).ConfigureAwait(false); // Fill the batch with events using the same body. This will result in a batch of events of equal size. // The events will only differ by the id property that is assigned to them. foreach (var eventData in EventGenerator.CreateEventsFromBody(Options.BatchSize, s_eventBody)) { if (!batch.TryAdd(eventData)) { throw new InvalidOperationException("It was not possible to fit the requested number of events in a single batch."); } } try { await s_producer.SendAsync(batch, cancellationToken).ConfigureAwait(false); return(Options.BatchSize); } catch (EventHubsException ex) when(cancellationToken.IsCancellationRequested && ex.IsTransient) { // If SendAsync() is canceled during a retry loop, the most recent exception is thrown. // If the exception is transient, it should be wrapped in an OperationCanceledException // which is ignored by the performance framework. throw new OperationCanceledException("EventHubsException thrown during cancellation", ex); } }
/// <summary> /// Executes the performance test scenario asynchronously. /// </summary> /// /// <param name="cancellationToken">The token used to signal when cancellation is requested.</param> /// public async override Task RunAsync(CancellationToken cancellationToken) { // Generate a set of events using the same body. This will result in publishing a set of events // of equal size. The events will only differ by the id property that is assigned to them. await s_producer.SendAsync( EventGenerator.CreateEventsFromBody(Options.Count, s_eventBody), s_sendOptions, cancellationToken ).ConfigureAwait(false); }
/// <summary> /// Executes the performance test scenario asynchronously. /// </summary> /// /// <param name="cancellationToken">The token used to signal when cancellation is requested.</param> /// public async override Task RunAsync(CancellationToken cancellationToken) { using var batch = s_client.CreateBatch(); // Fill the batch with events using the same body. This will result in a batch of events of equal size. // The events will only differ by the id property that is assigned to them. foreach (var eventData in EventGenerator.CreateEventsFromBody(Options.Count, s_eventBody)) { if (!batch.TryAdd(eventData)) { throw new InvalidOperationException("It was not possible to fit the requested number of events in a single batch."); } } await s_client.SendAsync(batch).ConfigureAwait(false); }
/// <summary> /// Executes the performance test scenario asynchronously. /// </summary> /// /// <param name="cancellationToken">The token used to signal when cancellation is requested.</param> /// public async override Task RunAsync(CancellationToken cancellationToken) { // Generate a set of events using the same body. This will result in publishing a set of events // of equal size. The events will only differ by the id property that is assigned to them. var events = EventGenerator.CreateEventsFromBody(Options.Count, s_eventBody); try { await s_client.SendAsync(events).ConfigureAwait(false); } finally { foreach (var eventData in events) { eventData.Dispose(); } } }
/// <summary> /// Enqueues events into the buffer to be published. /// </summary> /// /// <param name="testOptions">The set of options governing test execution.</param> /// private async Task EnqueueEvents(CancellationToken cancellationToken) { var eventBody = EventGenerator.CreateRandomBody(Options.BodySize); try { while (!cancellationToken.IsCancellationRequested) { var enqueueOptions = CreateEnqueueOptions(); // Generate events using the same body. This will result in publishing a set of events // of equal size. The events will only differ by the id property that is assigned to them. if (Options.BatchSize > 1) { await _producer.EnqueueEventsAsync(EventGenerator.CreateEventsFromBody(Options.BatchSize, eventBody), enqueueOptions, cancellationToken).ConfigureAwait(false); } else { await _producer.EnqueueEventAsync(EventGenerator.CreateEventFromBody(eventBody), enqueueOptions, cancellationToken).ConfigureAwait(false); } } } catch (OperationCanceledException) { // Expected } catch (EventHubsException ex) when((cancellationToken.IsCancellationRequested) && (ex.IsTransient)) { // If the enqueue is canceled during a retry loop, the most recent exception is thrown. // If the exception is transient, it should be ignored. } catch (Exception ex) { ErrorRaised(ex); } }
/// <summary> /// Executes the performance test scenario asynchronously. /// </summary> /// /// <param name="cancellationToken">The token used to signal when cancellation is requested.</param> /// public async override Task <int> RunBatchAsync(CancellationToken cancellationToken) { try { // Generate a set of events using the same body. This will result in publishing a set of events // of equal size. The events will only differ by the id property that is assigned to them. await s_producer.SendAsync( EventGenerator.CreateEventsFromBody(Options.BatchSize, s_eventBody), _sendOptions, cancellationToken ).ConfigureAwait(false); return(Options.BatchSize); } catch (EventHubsException ex) when(cancellationToken.IsCancellationRequested && ex.IsTransient) { // If SendAsync() is canceled during a retry loop, the most recent exception is thrown. // If the exception is transient, it should be wrapped in an OperationCancelledException // which is ignored by the performance framework. throw new OperationCanceledException("EventHubsException thrown during cancellation", ex); } }