/// <summary> /// Handles the subscription of a new TopicPartition to this fetcher. /// Keeps track of the subscribed partitions in order to not fetch messages if the FlowControlState is Closed. /// </summary> /// <param name="topicPartition"></param> /// <returns></returns> public IDisposable Subscribe(TopicPartition topicPartition) { _topicPartitions.Add(topicPartition); EtwTrace.Log.FetcherPartitionSubscribed(_id, topicPartition.PartitionId); // cleanup var topicPartitionCleanup = Disposable.Create(() => _topicPartitions.Remove(topicPartition)); var receivedMessagesSubscriptionCleanup = ReceivedMessages. Where(rm => rm.Topic == topicPartition.Topic && rm.Partition == topicPartition.PartitionId) .Subscribe(topicPartition); var flowControlCleanup = topicPartition.FlowControl. // we need to wake up from waiting loop any time flow control hits low watermark and becomes enabled Where(enabled => enabled). Subscribe(_ => _wakeupSignal.OnNext(true)); var cleanup = new CompositeDisposable { topicPartitionCleanup, receivedMessagesSubscriptionCleanup, flowControlCleanup }; if (_log.IsDebugEnabled) { cleanup.Add(Disposable.Create(() => _log.Debug("Fetcher #{0} {1} topicPartition is unsubscribing", _id, topicPartition))); } _log.Debug("Fetcher #{0} added {1}", _id, topicPartition); return(cleanup); }
public IActionResult Index(EventHubModel model) { // Apply input history from cookie var cu = ControllerUtils.From(this); cu.PersistInput("ConnectionString", model, EventHubModel.Default.ConnectionString); cu.PersistInput("EventHubName", model, EventHubModel.Default.EventHubName); cu.PersistInput("ConsumerGroupName", model, EventHubModel.Default.ConsumerGroupName); cu.PersistInput("StorageConnectionString", model, EventHubModel.Default.StorageConnectionString); cu.PersistInput("StorageContainerName", model, EventHubModel.Default.StorageContainerName); var receiveTimeout = model.ListeningTime - TimeSpan.FromMilliseconds(200 * 2); if (model.ConsumerGroupName == EventHubModel.Default.ConsumerGroupName) { model.ConsumerGroupName = PartitionReceiver.DefaultConsumerGroupName; } try { var cs = new EventHubsConnectionStringBuilder(model.ConnectionString) { EntityPath = model.EventHubName, }; var ec = EventHubClient.CreateFromConnectionString(cs.ToString()); // WARNING : Max # of TCP socket because of each instance created by Http Request if (model.ReceiveRequested) { var eph = new EventProcessorHost( model.EventHubName, model.ConsumerGroupName, model.ConnectionString, model.StorageConnectionString, model.StorageContainerName); eph.RegisterEventProcessorFactoryAsync(this, new EventProcessorOptions { InvokeProcessorAfterReceiveTimeout = true, ReceiveTimeout = receiveTimeout, // It's necessary to set long time here. (1.6sec was not enough at 2020.7.30) } ).ConfigureAwait(false).GetAwaiter().GetResult(); Task.Delay(receiveTimeout + TimeSpan.FromMilliseconds(200)).ConfigureAwait(false).GetAwaiter().GetResult(); // wait message received eph.UnregisterEventProcessorAsync().ConfigureAwait(false).GetAwaiter().GetResult(); model.ActionMessage = ""; var err = ErrorMessages.ToString(); if (!string.IsNullOrEmpty(err)) { model.ActionMessage = $"{err}{Environment.NewLine}{Environment.NewLine}"; } model.ActionMessage += $"Received {ReceivedMessages.Count} messages.{Environment.NewLine}{Environment.NewLine}{string.Join(Environment.NewLine, ReceivedMessages.Where(a => a != null))}"; if (ReceivedMessages.Count > 5) { model.ActionMessage += $"{Environment.NewLine}...more"; } Task.Delay(TimeSpan.FromMilliseconds(200)).ConfigureAwait(false).GetAwaiter().GetResult(); // wait message received } else if (!model.SkipSend) { ec.SendAsync(new EventData(Encoding.UTF8.GetBytes(model.Message))).ConfigureAwait(false).GetAwaiter().GetResult(); model.ActionMessage = $"OK : Sent '{model.Message}' to {model.EventHubName}"; } // Collect Partition Information var isNetError = false; var runtimeInfo = ec.GetRuntimeInformationAsync().ConfigureAwait(false).GetAwaiter().GetResult(); foreach (var pid in runtimeInfo.PartitionIds) { if (isNetError == false) { try { var pi = ec.GetPartitionRuntimeInformationAsync(pid).ConfigureAwait(false).GetAwaiter().GetResult(); if (model.PartitionInfo == null) { model.PartitionInfo = new Dictionary <string, EventHubPartitionRuntimeInformation>(); } model.PartitionInfo[pid] = pi; } catch (SocketException ex) { throw ex; } } } } catch (Exception ex) { for (var exx = ex; exx != null; exx = ex.InnerException) { model.ActionMessage = $"ERROR : {exx.Message}{Environment.NewLine}"; } } model.ReceiveRequested = false; model.SkipSend = false; return(View(model)); }