1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Discord Botがなぜか二重起動している件(ひとまずの解決編)

Posted at

はじめに

以前この記事でDiscord Botが二重起動しているという話をしました。

何かしらの無限ループを組み込んでいるBotが再起動した際に再び無限ループが実行されてしまっており、しかも元々あった無限ループが消えずに残ってしまっているため同時に複数の無限ループが発生してしまっていた、というのが問題でした。

先述の記事ではたまにDockerコンテナ自体を再起動するという解決策を取っていましたが、それは面倒です。

というわけで、今回は二重起動を根本的に解決する方法を調べたので、それを書き残しておこうと思います。

解決法

おそらく通信が不安定になったなどの理由で一旦Botがネットワークから切断され、再接続の際にon_ready関数によってスタートされるメインの無限ループが再度実行されてしまっていたことが二重起動の原因でした。

ここで、「元々あった無限ループが消えずに残っている」ことに注目します。無限ループを実行させるとき、すでに無限ループがあるかを確認し、あったら実行しない、ということをすればいいわけです。

この機能を実装するために、asyncio.create_taskを用います。

これにより、無限ループをコルーチンとしてスケジューリングすることができます。

スケジューリングが残っているかどうかで、無限ループがすでにあるか無いかを判断するわけです。

普通はこのメソッドをタスクの並行処理などに用いるようですが、今回は上記のような用い方をします。

サンプルプログラム

今回紹介した二重起動対策を組み込んだDiscord BotのメインPythonプログラムは以下の通りです。

import asyncio
import os
import discord
from discord.ext import commands

TOKEN = os.getenv("TOKEN")
DISCORD_CHANNEL_ID = int(os.environ.get("DISCORD_CHANNEL_ID"))
intent = discord.Intents.default()
intent.message_content = True
client = commands.Bot(command_prefix="-", intents=intent)
# すでに無限ループがあるかを示すグローバル変数
task = None


async def main():
    while True:
        # 処理


@client.event
async def on_ready():
    global task
    # スケジューリングがないなら以下を実行
    if task is None or task.done():
        print("Bot is ready!")
        # スケジューリングする
        task = asyncio.create_task(main())


client.run(TOKEN)

スケジューリングを組み込んだことにより、on_ready関数が再接続の際に再び実行されたとしても、main関数はコンテナ起動時の一回しか実行されないこととなります。

その他の設定ファイルはこの記事などを参考に設定してください。

おわりに

この方法を試すようになってから、一応Botが二重に起動してしまっているということはなくなりました。

非常に運用が楽になったので、もし無限ループを持つDiscord Botを運用している方がいらっしゃったら、この方法をぜひお試しください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?