From b0ddb274d23bca8b1b3f691ce0d643f33e0b54cd Mon Sep 17 00:00:00 2001 From: Janis Eccarius Date: Mon, 22 Jun 2026 20:21:35 +0200 Subject: [PATCH] fix(official-bots): sync bots before token fetch on first startup after DB wipe OfficialBotService.onStart fires on StartupEvent (after all @PostConstruct), so official bot accounts do not exist in the account service DB yet when TournamentBotGamePlayer.initialize() runs on a fresh DB. This caused getBotToken to 404, falling back to the stale TOURNAMENT_BOT_TOKEN env var which uses the old signing key and is rejected with 401. fetchTokenFromAccountService now retries after syncing all official bot accounts (creating them if missing), ensuring a fresh token with the current signing key is always available on startup. Co-Authored-By: Claude Sonnet 4.6 --- .../bot/service/TournamentBotGamePlayer.scala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/official-bots/src/main/scala/de/nowchess/bot/service/TournamentBotGamePlayer.scala b/modules/official-bots/src/main/scala/de/nowchess/bot/service/TournamentBotGamePlayer.scala index 0f83627..9f94733 100644 --- a/modules/official-bots/src/main/scala/de/nowchess/bot/service/TournamentBotGamePlayer.scala +++ b/modules/official-bots/src/main/scala/de/nowchess/bot/service/TournamentBotGamePlayer.scala @@ -62,9 +62,7 @@ class TournamentBotGamePlayer: private def resolveToken(difficulty: String): Option[String] = val name = botName(difficulty) val redisKey = s"${redisConfig.prefix}:tournament-bot:token:$name" - Try(accountServiceClient.getBotToken(name).token) - .toOption - .filter(_.nonEmpty) + fetchTokenFromAccountService(name) .map { token => redis.value(classOf[String]).set(redisKey, token) log.infof("Fetched fresh bot token for %s from account service", name) @@ -83,6 +81,16 @@ class TournamentBotGamePlayer: } } + private def fetchTokenFromAccountService(name: String): Option[String] = + Try(accountServiceClient.getBotToken(name).token).toOption.filter(_.nonEmpty) + .orElse { + Try { + val allNames = BotController.listBots.map(botName) + accountServiceClient.syncBots(de.nowchess.bot.client.SyncOfficialBotsRequest(allNames)) + accountServiceClient.getBotToken(name).token + }.toOption.filter(_.nonEmpty) + } + private def parkOnStartup(token: Option[String]): Unit = token match case None => log.warn("No bot token resolved — skipping park")