/// <summary> /// Send a 'batch of <see cref="EventData"/> with the same partitionKey' to EventHub. All <see cref="EventData"/>'s with a partitionKey are guaranteed to land on the same partition. /// Multiple PartitionKey's will be mapped to one Partition. /// <para> /// There are 3 ways to send to EventHubs, to understand this particular type of send refer to the overload <see cref="SendAsync(EventData, string)"/>, /// which is the same type of send and is used to send single <see cref="EventData"/>. /// </para> /// Sending a batch of <see cref="EventData"/>'s is useful in the following cases: /// <para>i. Efficient send - sending a batch of <see cref="EventData"/> maximizes the overall throughput by optimally using the number of sessions created to EventHubs service.</para> /// <para>ii. Sending multiple events in One Transaction. This is the reason why all events sent in a batch needs to have same partitionKey (so that they are sent to one partition only).</para> /// </summary> /// <param name="eventDatas">the batch of events to send to EventHub</param> /// <param name="partitionKey">the partitionKey will be hashed to determine the partitionId to send the EventData to. On the Received message this can be accessed at <see cref="EventData.SystemPropertiesCollection.PartitionKey"/>.</param> /// <returns>A Task that completes when the send operation is done.</returns> /// <seealso cref="SendAsync(EventData)"/> /// <see cref="PartitionSender.SendAsync(EventData)"/> public async Task SendAsync(IEnumerable <EventData> eventDatas, string partitionKey) { // eventDatas null check is inside ValidateEvents int count = EventDataSender.ValidateEvents(eventDatas); EventHubsEventSource.Log.EventSendStart(this.ClientId, count, partitionKey); Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.ConnectionStringBuilder, partitionKey, eventDatas, count); Task sendTask = null; try { sendTask = this.InnerSender.SendAsync(eventDatas, partitionKey); await sendTask.ConfigureAwait(false); } catch (Exception exception) { EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString()); EventHubsDiagnosticSource.FailSendActivity(activity, this.ConnectionStringBuilder, partitionKey, eventDatas, exception); throw; } finally { EventHubsEventSource.Log.EventSendStop(this.ClientId); EventHubsDiagnosticSource.StopSendActivity(activity, this.ConnectionStringBuilder, partitionKey, eventDatas, sendTask); } }
public async Task SendAsync(IEnumerable <EventData> eventDatas, string partitionKey) { int count = ValidateEvents(eventDatas); var activePartitionRouting = String.IsNullOrEmpty(partitionKey) ? this.PartitionId : partitionKey; EventHubsEventSource.Log.EventSendStart(this.ClientId, count, partitionKey); Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, count); Task sendTask = null; try { var processedEvents = await this.ProcessEvents(eventDatas).ConfigureAwait(false); sendTask = this.OnSendAsync(processedEvents, partitionKey); await sendTask.ConfigureAwait(false); } catch (Exception exception) { EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString()); EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, exception); throw; } finally { EventHubsEventSource.Log.EventSendStop(this.ClientId); EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, sendTask); } }
/// <summary> /// Send <see cref="EventData"/> to a specific EventHub partition. The targeted partition is pre-determined when this PartitionSender was created. /// <para> /// There are 3 ways to send to EventHubs, to understand this particular type of send refer to the overload <see cref="SendAsync(EventData)"/>, which is the same type of send and is used to send single <see cref="EventData"/>. /// </para> /// Sending a batch of <see cref="EventData"/>'s is useful in the following cases: /// <para>i. Efficient send - sending a batch of <see cref="EventData"/> maximizes the overall throughput by optimally using the number of sessions created to EventHubs' service.</para> /// <para>ii. Sending multiple <see cref="EventData"/>'s in a Transaction. To acheive ACID properties, the Gateway Service will forward all <see cref="EventData"/>'s in the batch to a single EventHub partition.</para> /// </summary> /// <example> /// Sample code: /// <code> /// EventHubClient client = EventHubClient.Create("__connectionString__"); /// PartitionSender senderToPartitionOne = client.CreatePartitionSender("1"); /// /// while (true) /// { /// var events = new List<EventData>(); /// for (int count = 1; count < 11; count++) /// { /// var payload = new PayloadEvent(count); /// byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload)); /// var sendEvent = new EventData(payloadBytes); /// var applicationProperties = new Dictionary<string, string>(); /// applicationProperties["from"] = "csharpClient"; /// sendEvent.Properties = applicationProperties; /// events.Add(sendEvent); /// } /// /// await senderToPartitionOne.SendAsync(events); /// Console.WriteLine("Sent Batch... Size: {0}", events.Count); /// /// } /// </code> /// </example> /// <param name="eventDatas">batch of events to send to EventHub</param> /// <returns>a Task that completes when the send operation is done.</returns> /// <exception cref="MessageSizeExceededException">the total size of the <see cref="EventData"/> exceeds a pre-defined limit set by the service. Default is 256k bytes.</exception> /// <exception cref="EventHubsException">Event Hubs service encountered problems during the operation.</exception> public async Task SendAsync(IEnumerable <EventData> eventDatas) { Guard.ArgumentNotNull(nameof(eventDatas), eventDatas); if (eventDatas is EventDataBatch && !string.IsNullOrEmpty(((EventDataBatch)eventDatas).PartitionKey)) { throw Fx.Exception.InvalidOperation(Resources.PartitionSenderInvalidWithPartitionKeyOnBatch); } int count = EventDataSender.ValidateEvents(eventDatas); EventHubsEventSource.Log.EventSendStart(this.ClientId, count, null); Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDatas, count); Task sendTask = null; try { sendTask = this.InnerSender.SendAsync(eventDatas, null); await sendTask.ConfigureAwait(false); } catch (Exception exception) { EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString()); EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDatas, exception); throw; } finally { EventHubsEventSource.Log.EventSendStop(this.ClientId); EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDatas, sendTask); } }