public Cluster(Configuration configuration, ILogger logger, NodeFactory nodeFactory, ProducerFactory producerFactory, ConsumerFactory consumerFactory, IStatistics statistics = null) { _configuration = configuration; _seeds = configuration.Seeds; _seedsGetter = configuration.SeedsGetter; Logger = logger; Statistics = statistics ?? new Statistics(); _timeoutScheduler = new TimeoutScheduler(configuration.ClientRequestTimeoutMs / 2); _pools = InitPools(Statistics, configuration, logger); // Producer init ProduceRouter = producerFactory != null?producerFactory() : new ProduceRouter(this, configuration, _pools.MessageBuffersPool); ProduceRouter.MessageExpired += (t, m) => { Statistics.UpdateExpired(); UpdateExited(1); }; ProduceRouter.MessagesAcknowledged += (t, c) => { Statistics.UpdateSuccessfulSent(c); UpdateExited(c); SignalSeenTopic(t); }; ProduceRouter.MessageDiscarded += (t, m) => { Statistics.UpdateDiscarded(); UpdateExited(1); }; RoutingTableChange += ProduceRouter.ChangeRoutingTable; ProduceRouter.BrokerTimeoutError += Statistics.UpdateBrokerTimeoutError; ProduceRouter.MessageReEnqueued += Statistics.UpdateMessageRetry; ProduceRouter.MessagePostponed += Statistics.UpdateMessagePostponed; // Consumer init ConsumeRouter = consumerFactory != null?consumerFactory() : new ConsumeRouter(this, configuration); ConsumeRouter.MessageReceived += UpdateConsumerMessageStatistics; if (ConsumeRouter is ConsumeRouter) { (ConsumeRouter as ConsumeRouter).InternalError += ex => Logger.LogError("An unexpected error occured in the consumer: " + ex); } RoutingTableChange += ConsumeRouter.ChangeRoutingTable; // Node factory var clientId = Encoding.UTF8.GetBytes(configuration.ClientId); var serializer = new Node.Serialization(configuration.SerializationConfig, configuration.Compatibility, _pools.RequestsBuffersPool, clientId, configuration.RequiredAcks, configuration.RequestTimeoutMs, configuration.CompressionCodec, configuration.FetchMinBytes, configuration.FetchMaxWaitTime, configuration.FetchMaxBytes); _nodeFactory = nodeFactory ?? ((h, p) => new Node(string.Format("[{0}:{1}]", h, p), () => new Connection(h, p, ep => new RealSocket(ep), _pools.SocketBuffersPool, _pools.RequestsBuffersPool, configuration.SendBufferSize, configuration.ReceiveBufferSize), serializer, configuration, _timeoutScheduler, _resolution)); _nodeFactory = DecorateFactory(_nodeFactory); // Inner actor _agent = new ActionBlock <ClusterMessage>(r => ProcessMessage(r), new ExecutionDataflowBlockOptions { TaskScheduler = configuration.TaskScheduler }); // Bootstrap BuildNodesFromSeeds(); if (_nodes.Count == 0) { var message = _seedsGetter != null ? "Invalid seeds Getter" : "Invalid seeds: " + _seeds; throw new ArgumentException(message); } }