Example #1
0
        public async Task UpdateAsync(float currentTimeMS)
        {
            if (currentTimeMS - _lastTimeStamp > _config.TimestampPeriodMS)
            {
                //Check to make sure there aren't two master servers
                var data = await _redisServer.GetValueAsync <MasterServerTimestamp>(RedisDBKeyTypes.MasterServerTimestamp);

                if (data != null)
                {
                    int receivedID = int.Parse(data.MasterServerID);


                    if (receivedID != Id)
                    {
                        throw new InvalidOperationException("Error: the ID associated with the current Master Server timestamp does not match this master server's Id. Are there two master servers running?");
                    }
                }
                else
                {
                    ConsoleManager.WriteLine("MasterServerTimestamp was null in redis db. Possible cause: MasterServer update was late.", ConsoleMessageType.Warning);
                    //If data is null, I'm assuming the master server was late in updating (which shouldn't happen in production, but was happening occasionally in debug.) Log just in case.
                }

                var msg = new MasterServerTimestamp()
                {
                    MasterServerID = Id.ToString()
                };

                await _redisServer.SetValueAsync(RedisDBKeyTypes.MasterServerTimestamp, msg, new TimeSpan(0, 0, 0, 0, _config.TimestampTimeoutMS));

                _lastTimeStamp = currentTimeMS;
            }

            HashSet <int> slaveIDsToRemove = new HashSet <int>();

            //Check for disconnected slaves
            foreach (var s in _slaveServers)
            {
                var heartbeat = await _redisServer.GetRawValueAsync(RedisDBKeyTypes.SlaveHeartbeat, s.Value.ID.ToString());

                if (heartbeat == null && TimeKeeper.MsSinceInitialization - _initTimeMs > _config.InitializationTimestampTimeoutMS && TimeKeeper.MsSinceInitialization - s.Value.InitializationTime > _config.SlaveInitializationGracePeriod)
                {
                    _redisServer.ClearHashValue(RedisDBKeyTypes.SlaveIDHashSet, s.Value.ID);



                    //ConsoleManager.WriteLine("Slave server timed out. Removing from slave list...", ConsoleMessageType.Warning);
                    slaveIDsToRemove.Add(s.Key);
                    _redisServer.PublishObjectAsync(ChannelTypes.MasterSlave, s.Value.ID, new NetworkMessageContainer(new MessageSlaveDisconnection(), MessageTypes.Redis_SlaveDisconnectionDetected));
                    _pendingRebalance       = true;//TODO: implement more graceful rebalance on slave disconnect, as of this writing the server basically just resets entirely
                    _rebalanceWaitStartTime = TimeKeeper.MsSinceInitialization;
                }
            }

            slaveIDsToRemove.ForEach(key => { RemoveSlave(key); });



            if (_pendingRebalance && TimeKeeper.MsSinceInitialization - _rebalanceWaitStartTime > _config.RebalanceDelayMS)
            {
                _rebalanceServers();
            }
        }