/// <summary>
        /// Initializes a new instance of the <see cref="ClusterMembers"/> class.
        /// </summary>
        /// <param name="clusterState">The cluster state.</param>
        /// <param name="terminateConnections">The terminate connections task.</param>
        public ClusterMembers(ClusterState clusterState, TerminateConnections terminateConnections)
        {
            HConsole.Configure(x => x.Configure <ClusterMembers>().SetPrefix("CLUST.MBRS"));

            _clusterState         = clusterState;
            _terminateConnections = terminateConnections;
            _loadBalancer         = clusterState.Options.LoadBalancer.Service ?? new RandomLoadBalancer();

            _logger = _clusterState.LoggerFactory.CreateLogger <ClusterMembers>();

            _members = new MemberTable();

            // members to connect
            if (clusterState.IsSmartRouting)
            {
                _memberConnectionQueue = new MemberConnectionQueue(clusterState.LoggerFactory);
            }
        }
        private volatile int _disposed; // disposed flag

        /// <summary>
        /// Initializes a new instance of the <see cref="Cluster"/> class.
        /// </summary>
        /// <param name="options">The cluster configuration.</param>
        /// <param name="serializationService">The serialization service.</param>
        /// <param name="loggerFactory">A logger factory.</param>
        public Cluster(IClusterOptions options, SerializationService serializationService, ILoggerFactory loggerFactory)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            if (serializationService == null)
            {
                throw new ArgumentNullException(nameof(serializationService));
            }
            if (loggerFactory is null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            var clientName = string.IsNullOrWhiteSpace(options.ClientName)
                ? options.ClientNamePrefix + ClusterIdSequence.GetNext()
                : options.ClientName;

            var clusterName = string.IsNullOrWhiteSpace(options.ClusterName) ? "dev" : options.ClusterName;

            State = new ClusterState(options, clusterName, clientName, new Partitioner(), loggerFactory);
            State.ShutdownRequested += () =>
            {
                // yes, we are starting a fire-and-forget task
                // but, DisposeAsync should never throw
                // yet we add a CfAwaitNoThrow() for more safety
                DisposeAsync().CfAwaitNoThrow();
            };

            // create components
            _terminateConnections = new TerminateConnections(loggerFactory);
            Members     = new ClusterMembers(State, _terminateConnections);
            Messaging   = new ClusterMessaging(State, Members);
            Events      = new ClusterEvents(State, Messaging, _terminateConnections, Members);
            Connections = new ClusterConnections(State, Members, serializationService);
            _heartbeat  = new Heartbeat(State, Messaging, options.Heartbeat, _terminateConnections);

            // wire components
            WireComponents();

            HConsole.Configure(x => x.Configure <Cluster>().SetIndent(2).SetPrefix("CLUSTER"));
        }
예제 #3
0
        public ClusterEvents(ClusterState clusterState, ClusterMessaging clusterMessaging, TerminateConnections terminateConnections, ClusterMembers clusterMembers)
        {
            _clusterState     = clusterState;
            _clusterMessaging = clusterMessaging;
            _clusterMembers   = clusterMembers;

            _logger               = _clusterState.LoggerFactory.CreateLogger <ClusterEvents>();
            _scheduler            = new DistributedEventScheduler(_clusterState.LoggerFactory);
            _terminateConnections = terminateConnections;

            _objectLifecycleEventSubscription = new ObjectLifecycleEventSubscription(_clusterState, this)
            {
                ObjectCreated   = args => _objectCreated.AwaitEach(args),
                ObjectDestroyed = args => _objectDestroyed.AwaitEach(args)
            };

            _partitionLostEventSubscription = new PartitionLostEventSubscription(_clusterState, this, clusterMembers)
            {
                PartitionLost = args => _partitionLost.AwaitEach(args)
            };
        }
예제 #4
0
        public Heartbeat(ClusterState clusterState, ClusterMessaging clusterMessaging, HeartbeatOptions options, TerminateConnections terminateConnections)
        {
            _clusterState         = clusterState ?? throw new ArgumentNullException(nameof(clusterState));
            _clusterMessaging     = clusterMessaging ?? throw new ArgumentNullException(nameof(clusterMessaging));
            _terminateConnections = terminateConnections;
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            _logger  = clusterState.LoggerFactory.CreateLogger <Heartbeat>(); // FIXME with client ID?
            _period  = TimeSpan.FromMilliseconds(options.PeriodMilliseconds);
            _timeout = TimeSpan.FromMilliseconds(options.TimeoutMilliseconds);

            if (options.PeriodMilliseconds < 0)
            {
                _logger.LogInformation("Heartbeat is disabled (period < 0)");
                return;
            }

            // sanity checks
            if (_timeout <= _period)
            {
                var timeout = TimeSpan.FromMilliseconds(2 * _period.TotalMilliseconds);
                _logger.LogWarning("Heartbeat timeout {Timeout}ms is <= period {Period}ms, falling back to a {Value}ms timeout.",
                                   _timeout, _period.TotalMilliseconds, timeout);
                _timeout = timeout;
            }

            _logger.LogInformation("Heartbeat with {Period}ms period and {Timeout}ms timeout",
                                   _period.ToString("hh\\:mm\\:ss", CultureInfo.InvariantCulture),
                                   _timeout.ToString("hh\\:mm\\:ss", CultureInfo.InvariantCulture));

            HConsole.Configure(x => x.Configure <Heartbeat>().SetPrefix("HEARTBEAT")); // FIXME with client ID?

            _cancel       = new CancellationTokenSource();
            _heartbeating = BeatAsync(_cancel.Token);
            _active       = 1;
        }