From 2b39573eb1aef32fbb6a5afae7444375e97c26b6 Mon Sep 17 00:00:00 2001 From: Ampflower Date: Thu, 8 Dec 2022 18:36:47 -0600 Subject: [PATCH] Make #updatePresence use ScheduledThreadPool to try to avoid crashing. This tries to resolve the issue of presence updates not occurring as they should after about 6000 rounds, which sounds suspiciously like a stack overflow. (The-ProxyFox-Group/ProxyFox#21) --- .../main/kotlin/dev/proxyfox/bot/BotUtil.kt | 22 +++++++---- .../kotlin/dev/proxyfox/bot/SchedulerUtil.kt | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 modules/bot/src/main/kotlin/dev/proxyfox/bot/SchedulerUtil.kt diff --git a/modules/bot/src/main/kotlin/dev/proxyfox/bot/BotUtil.kt b/modules/bot/src/main/kotlin/dev/proxyfox/bot/BotUtil.kt index fe66a3e9..f8c6f755 100644 --- a/modules/bot/src/main/kotlin/dev/proxyfox/bot/BotUtil.kt +++ b/modules/bot/src/main/kotlin/dev/proxyfox/bot/BotUtil.kt @@ -49,20 +49,29 @@ import kotlinx.datetime.Clock import kotlinx.datetime.Instant import java.lang.Integer.min import java.time.OffsetDateTime +import java.util.concurrent.Executors import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.minutes const val UPLOAD_LIMIT = 1024 * 1024 * 8 +val scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()) + lateinit var scope: CoroutineScope lateinit var kord: Kord lateinit var http: HttpClient lateinit var startTime: Instant +private var count: Int = 0 var shardCount: Int = 0 -val errorChannelId = try { Snowflake(System.getenv("PROXYFOX_LOG")) } catch (_: Throwable) { null } +val errorChannelId = try { + Snowflake(System.getenv("PROXYFOX_LOG")) +} catch (_: Throwable) { + null +} var errorChannel: TextChannel? = null @OptIn(PrivilegedIntent::class) @@ -148,29 +157,28 @@ suspend fun login() { suspend fun updatePresence() { startTime = Clock.System.now() - var count = 0 - while (true) { - count++ - count %= 3 + scheduler.fixedRateAction(Duration.ZERO, 2.minutes) { + count = (count + 1) % 3 val append = when (count) { 0 -> { val servers = kord.guilds.count() "in $servers servers!" } + 1 -> { val systemCount = database.fetchTotalSystems() "$systemCount systems registered!" } + 2 -> { "uptime: ${(Clock.System.now() - startTime).inWholeHours} hours!" } - else -> throw IllegalStateException("Count is not 0, 1, or 2!") + else -> throw AssertionError("Count ($count) not in 0..2") } kord.editPresence { watching("for pf>help! $append") } - delay(120000) } } diff --git a/modules/bot/src/main/kotlin/dev/proxyfox/bot/SchedulerUtil.kt b/modules/bot/src/main/kotlin/dev/proxyfox/bot/SchedulerUtil.kt new file mode 100644 index 00000000..2003e502 --- /dev/null +++ b/modules/bot/src/main/kotlin/dev/proxyfox/bot/SchedulerUtil.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, The ProxyFox Group + * + * This Source Code is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package dev.proxyfox.bot + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import java.util.concurrent.ScheduledExecutorService +import java.util.concurrent.TimeUnit +import kotlin.time.Duration + +// Created 2022-08-12T16:06:42 + +/** + * Helper functions for [ScheduledExecutorService]. + * + * @author Ampflower + * @since 2.0.8 + **/ + +/** + * Wrapper around [ScheduledExecutorService.scheduleAtFixedRate] to provide a Kotlin Coroutine equivalent. + * + * @param initialDelay The initial delay. Will be treated as milliseconds. + * @param period The period in which future action runs will occur. Will be treated as milliseconds. + * @param action The action to execute within a coroutine scope. + * */ +fun ScheduledExecutorService.fixedRateAction(initialDelay: Duration, period: Duration, action: suspend CoroutineScope.() -> Unit) { + scheduleAtFixedRate({ + scope.launch(block = action) + }, initialDelay.inWholeMilliseconds, period.inWholeMilliseconds, TimeUnit.MILLISECONDS) +} \ No newline at end of file