use of net.kodehawa.mantarobot.core.shard.MantaroShard in project MantaroBot by Mantaro.
the class ShardWatcher method run.
@Override
public void run() {
LogUtils.shard("ShardWatcherThread started");
// Executes the restart queue handler. For the actual logic behind all this, check the next while(true) loop.
THREAD_POOL.execute(() -> {
while (true) {
MantaroShard shard = RESTART_QUEUE.poll();
if (shard == null) {
// poll the queue every 10 seconds
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
LogUtils.shard("Shard restarter task interrupted");
return;
}
// Continue to the next loop cycle if no shard is on the restart queue.
continue;
}
// Alert us, plz no panic
LogUtils.shard(String.format("(Resume request failed or errored) " + "Dead shard? Starting automatic shard restart on shard #%d due to it being inactive for longer than 30 seconds.", shard.getId()));
try {
// Reboot the shard.
shard.start(true);
} catch (Exception e) {
// If the shard wasn't able to restart by itself, alert us so we can reboot manually later.
LogUtils.shard(String.format("Shard %d was unable to be restarted: %s", shard.getId(), e));
}
try {
// Wait 5 seconds as a backoff.
Thread.sleep(5000);
} catch (InterruptedException e) {
LogUtils.shard("Shard restarter task interrupted");
return;
}
}
});
final int wait = MantaroData.config().get().shardWatcherWait;
while (true) {
try {
// Run every x ms (usually every 10 minutes unless changed)
Thread.sleep(wait);
MantaroEventManager.getLog().info("Checking shards...");
// Just in case...
if (shardedMantaro == null)
shardedMantaro = MantaroBot.getInstance().getShardedMantaro();
// Get and propagate the shard event.
// This event will propagate over all Mantaro-specific listeners, and see if the shards are responding accordingly.
ShardMonitorEvent sme = new ShardMonitorEvent(shardedMantaro.getTotalShards());
EventUtils.propagateEvent(sme);
// Start the procedure...
int[] dead = sme.getDeadShards();
// Oh well... we can try to recover them now!
if (dead.length != 0) {
MantaroEventManager.getLog().error("Dead shards found: {}", Arrays.toString(dead));
// restart on..." kinda message.
if (dead.length > 15) {
LogUtils.shard("Seems like Megumin struck our castle and we got a horribly high amount of dead shards (" + dead.length + ")\n" + "This could be just due to them reconnecting though, if nothing appears down there talking about how the shards are rebooting " + "you might aswell ignore this warning.");
}
// Under the hood this basically calls for a RESUME JDA instance and if it fails, it adds it to the restart queue to replace it with a completely new one.
for (int id : dead) {
try {
MantaroShard shard = MantaroBot.getInstance().getShard(id);
// But, if the shard has been inactive for too long, we're better off scrapping this session as the shard might be stuck on connecting.
if ((shard.getStatus() == JDA.Status.RECONNECT_QUEUED || shard.getStatus() == JDA.Status.ATTEMPTING_TO_RECONNECT || shard.getStatus() == JDA.Status.SHUTDOWN) && shard.getEventManager().getLastJDAEventTimeDiff() < 200000) {
LogUtils.shard(String.format("Skipping shard %d due to it being currently reconnecting to the websocket or was shutdown manually...", id));
continue;
}
LogUtils.shard(String.format("Found dead shard (#%d)... attempting RESUME request and waiting 20 seconds to validate.", id));
// Send the RESUME request.
((JDAImpl) (shard.getJDA())).getClient().close(4000);
RESUME_WAITER.schedule(() -> {
if (shard.getEventManager().getLastJDAEventTimeDiff() > 18000) {
RESTART_QUEUE.add(shard);
}
}, 20, TimeUnit.SECONDS);
} catch (Exception e) {
// Print the exception so we can look at it later...
e.printStackTrace();
// Force add into the queue
RESUME_WAITER.schedule(() -> RESTART_QUEUE.add(MantaroBot.getInstance().getShard(id)), 30, TimeUnit.SECONDS);
// Somehow we couldn't reboot the shard.
LogUtils.shard(String.format("Cannot restart shard %d. Try to do it manually.", id));
}
}
} else {
// yay
MantaroEventManager.getLog().info("No dead shards found");
long ping = MantaroBot.getInstance().getPing();
// We might have a few soft-dead shards on here... (or internet went to shit)
if (ping > 400) {
LogUtils.shard(String.format("No dead shards found, but average ping is high (%dms). Ping breakdown: %s", ping, Arrays.toString(MantaroBot.getInstance().getPings())));
}
}
} catch (InterruptedException e) {
// Just in case we stop this for any reason, we want to know that we interrupted this, just so we know we won't have a shard watcher running on the background.
log.error("ShardWatcher interrupted, stopping...");
LogUtils.shard("ShardWatcher interrupted, stopping...");
return;
}
}
}
use of net.kodehawa.mantarobot.core.shard.MantaroShard in project MantaroBot by Mantaro.
the class MantaroBot method startCheckingBirthdays.
public void startCheckingBirthdays() {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
// How much until tomorrow? That's the initial delay, then run it once a day.
ZoneId z = ZoneId.of("America/Chicago");
ZonedDateTime now = ZonedDateTime.now(z);
LocalDate tomorrow = now.toLocalDate().plusDays(1);
ZonedDateTime tomorrowStart = tomorrow.atStartOfDay(z);
Duration duration = Duration.between(now, tomorrowStart);
long millisecondsUntilTomorrow = duration.toMillis();
// It actually cut off the time from 50 minutes to 20 seconds.
for (MantaroShard shard : core.getShardedInstance().getShards()) {
shard.startBirthdayTask(millisecondsUntilTomorrow);
}
// Start the birthday cacher.
executorService.scheduleWithFixedDelay(birthdayCacher::cache, 22, 22, TimeUnit.HOURS);
}
Aggregations