Beispiel #1
0
        /// <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);
            }
        }
Beispiel #2
0
        /// <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&lt;EventData&gt;();
        ///     for (int count = 1; count &lt; 11; count++)
        ///     {
        ///         var payload = new PayloadEvent(count);
        ///         byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload));
        ///         var sendEvent = new EventData(payloadBytes);
        ///         var applicationProperties = new Dictionary&lt;string, string&gt;();
        ///         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);
            }
        }
        /// <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&lt;EventData&gt;();
        ///     for (int count = 1; count &lt; 11; count++)
        ///     {
        ///         var payload = new PayloadEvent(count);
        ///         byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload));
        ///         var sendEvent = new EventData(payloadBytes);
        ///         var applicationProperties = new Dictionary&lt;string, string&gt;();
        ///         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)
        {
            if (eventDatas == null)
            {
                throw Fx.Exception.ArgumentNull(nameof(eventDatas));
            }

            int count = EventDataSender.ValidateEvents(eventDatas, this.PartitionId, null);

            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);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Receive a batch of <see cref="EventData"/>'s from an EventHub partition by allowing wait time on each individual call.
        /// </summary>
        /// <returns>A Task that will yield a batch of <see cref="EventData"/> from the partition on which this receiver is created. Returns 'null' if no EventData is present.</returns>
        public async Task <IEnumerable <EventData> > ReceiveAsync(int maxMessageCount, TimeSpan waitTime)
        {
            EventHubsEventSource.Log.EventReceiveStart(this.ClientId);
            Activity activity = EventHubsDiagnosticSource.StartReceiveActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, this.ConsumerGroupName, this.EventPosition);

            Task <IList <EventData> > receiveTask = null;
            IList <EventData>         events      = null;
            int count = 0;

            try
            {
                receiveTask = this.OnReceiveAsync(maxMessageCount, waitTime);
                events      = await receiveTask.ConfigureAwait(false);

                count = events?.Count ?? 0;
                EventData lastEvent = events?[count - 1];
                if (lastEvent != null)
                {
                    // Store the current position in the stream of messages
                    this.EventPosition.Offset          = lastEvent.SystemProperties.Offset;
                    this.EventPosition.EnqueuedTimeUtc = lastEvent.SystemProperties.EnqueuedTimeUtc;
                    this.EventPosition.SequenceNumber  = lastEvent.SystemProperties.SequenceNumber;

                    // Update receiver runtime metrics?
                    if (this.ReceiverRuntimeMetricEnabled)
                    {
                        this.RuntimeInfo.LastSequenceNumber  = lastEvent.LastSequenceNumber;
                        this.RuntimeInfo.LastEnqueuedOffset  = lastEvent.LastEnqueuedOffset;
                        this.RuntimeInfo.LastEnqueuedTimeUtc = lastEvent.LastEnqueuedTime;
                        this.RuntimeInfo.RetrievalTime       = lastEvent.RetrievalTime;
                    }
                }

                return(events);
            }
            catch (Exception e)
            {
                EventHubsEventSource.Log.EventReceiveException(this.ClientId, e.ToString());
                EventHubsDiagnosticSource.FailReceiveActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, this.ConsumerGroupName, e);
                throw;
            }
            finally
            {
                EventHubsEventSource.Log.EventReceiveStop(this.ClientId, count);
                EventHubsDiagnosticSource.StopReceiveActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, this.ConsumerGroupName, events, receiveTask);
            }
        }
Beispiel #5
0
        /// <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&lt;EventData&gt;();
        ///     for (int count = 1; count &lt; 11; count++)
        ///     {
        ///         var payload = new PayloadEvent(count);
        ///         byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload));
        ///         var sendEvent = new EventData(payloadBytes);
        ///         var applicationProperties = new Dictionary&lt;string, string&gt;();
        ///         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);
            this.ThrowIfClosed();

            if (eventDatas is EventDataBatch && !string.IsNullOrEmpty(((EventDataBatch)eventDatas).PartitionKey))
            {
                throw Fx.Exception.InvalidOperation(Resources.PartitionSenderInvalidWithPartitionKeyOnBatch);
            }

            // Convert enumerator to a rescannable collection to avoid skipping events if underlying enumerator is not re-scannabled.
            var eventDataList = eventDatas?.ToList();

            int count = EventDataSender.ValidateEvents(eventDataList);

            EventHubsEventSource.Log.EventSendStart(this.ClientId, count, null);
            Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDataList, count);

            Task sendTask = null;

            try
            {
                sendTask = this.InnerSender.SendAsync(eventDataList, null);
                await sendTask.ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString());
                EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDataList, exception);
                throw;
            }
            finally
            {
                EventHubsEventSource.Log.EventSendStop(this.ClientId);
                EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, this.PartitionId, eventDataList, sendTask);
            }
        }