public ShardsCoordinator()
        {
            //load main stuff
            LogSetup.SetupLogger(-1);
            _log   = LogManager.GetCurrentClassLogger();
            _creds = new BotCredentials();

            _log.Info("Starting NadekoBot v" + StatsService.BotVersion);

            _key = _creds.RedisKey();

            var conf = ConfigurationOptions.Parse(_creds.RedisOptions);

            _redis = ConnectionMultiplexer.Connect(conf);

            var imgCache = new RedisImagesCache(_redis, _creds);   //reload images into redis

            if (!imgCache.AllKeysExist().GetAwaiter().GetResult()) // but only if the keys don't exist. If images exist, you have to reload them manually
            {
                imgCache.Reload().GetAwaiter().GetResult();
            }
            else
            {
                _log.Info("Images are already present in redis. Use .imagesreload to force update if needed.");
            }

            //setup initial shard statuses
            _defaultShardState = new ShardComMessage()
            {
                ConnectionState = Discord.ConnectionState.Disconnected,
                Guilds          = 0,
                Time            = DateTime.UtcNow
            };
            var db = _redis.GetDatabase();

            //clear previous statuses
            db.KeyDelete(_key + "_shardstats");

            _shardProcesses = new Process[_creds.TotalShards];

#if GLOBAL_NADEKO
            var shardIdsEnum = Enumerable.Range(1, 63)
                               .Concat(Enumerable.Range(65, _creds.TotalShards - 65))
                               .Shuffle()
                               .Prepend(64)
                               .Prepend(0);
#else
            var shardIdsEnum = Enumerable.Range(1, _creds.TotalShards - 1)
                               .Shuffle()
                               .Prepend(0);
#endif

            var shardIds = shardIdsEnum
                           .ToArray();
            for (var i = 0; i < shardIds.Length; i++)
            {
                var id = shardIds[i];
                //add it to the list of shards which should be started
#if DEBUG
                if (id > 0)
                {
                    _shardStartQueue.Enqueue(id);
                }
                else
                {
                    _shardProcesses[id] = Process.GetCurrentProcess();
                }
#else
                _shardStartQueue.Enqueue(id);
#endif
                //set the shard's initial state in redis cache
                var msg = _defaultShardState.Clone();
                msg.ShardId = id;
                //this is to avoid the shard coordinator thinking that
                //the shard is unresponsive while starting up
                var delay = 45;
#if GLOBAL_NADEKO
                delay = 180;
#endif
                msg.Time = DateTime.UtcNow + TimeSpan.FromSeconds(delay * (id + 1));
                db.ListRightPush(_key + "_shardstats",
                                 JsonConvert.SerializeObject(msg),
                                 flags: CommandFlags.FireAndForget);
            }

            _curProcessId = Process.GetCurrentProcess().Id;

            //subscribe to shardcoord events
            var sub = _redis.GetSubscriber();

            //send is called when shard status is updated. Every 7.5 seconds atm
            sub.Subscribe(_key + "_shardcoord_send",
                          OnDataReceived,
                          CommandFlags.FireAndForget);

            //called to stop the shard, although the shard will start again when it finds out it's dead
            sub.Subscribe(_key + "_shardcoord_stop",
                          OnStop,
                          CommandFlags.FireAndForget);

            //called kill the bot
            sub.Subscribe(_key + "_die",
                          (ch, x) => Environment.Exit(0),
                          CommandFlags.FireAndForget);
        }
Exemple #2
0
        public ShardsCoordinator()
        {
            //load main stuff
            LogSetup.SetupLogger(-1);
            _log   = LogManager.GetCurrentClassLogger();
            _creds = new BotCredentials();

            _log.Info("Starting NadekoBot v" + StatsService.BotVersion);

            _key   = _creds.RedisKey();
            _redis = ConnectionMultiplexer.Connect("127.0.0.1");

            new RedisImagesCache(_redis, _creds).Reload(); //reload images into redis

            //setup initial shard statuses
            _defaultShardState = new ShardComMessage()
            {
                ConnectionState = Discord.ConnectionState.Disconnected,
                Guilds          = 0,
                Time            = DateTime.UtcNow
            };
            var db = _redis.GetDatabase();

            //clear previous statuses
            db.KeyDelete(_key + "_shardstats");

            _shardProcesses = new Process[_creds.TotalShards];
            for (int i = 0; i < _creds.TotalShards; i++)
            {
                //add it to the list of shards which should be started
#if DEBUG
                if (i > 0)
                {
                    _shardStartQueue.Enqueue(i);
                }
                else
                {
                    _shardProcesses[i] = Process.GetCurrentProcess();
                }
#else
                _shardStartQueue.Enqueue(i);
#endif
                //set the shard's initial state in redis cache
                var msg = _defaultShardState.Clone();
                msg.ShardId = i;
                //this is to avoid the shard coordinator thinking that
                //the shard is unresponsive while startup up
                var delay = 45;
#if GLOBAL_NADEKO
                delay = 180;
#endif
                msg.Time = DateTime.UtcNow + TimeSpan.FromSeconds(delay * (i + 1));
                db.ListRightPush(_key + "_shardstats",
                                 JsonConvert.SerializeObject(msg),
                                 flags: CommandFlags.FireAndForget);
            }

            _curProcessId = Process.GetCurrentProcess().Id;

            //subscribe to shardcoord events
            var sub = _redis.GetSubscriber();

            //send is called when shard status is updated. Every 7.5 seconds atm
            sub.Subscribe(_key + "_shardcoord_send",
                          OnDataReceived,
                          CommandFlags.FireAndForget);

            //restart is called when shzard should be stopped and then started again
            sub.Subscribe(_key + "_shardcoord_restart",
                          OnRestart,
                          CommandFlags.FireAndForget);

            //called to kill the shard
            sub.Subscribe(_key + "_shardcoord_stop",
                          OnStop,
                          CommandFlags.FireAndForget);

            //called kill the bot
            sub.Subscribe(_key + "_die",
                          (ch, x) => Environment.Exit(0),
                          CommandFlags.FireAndForget);
        }