Mattermost ボットを作成しています。Websocket 接続がランダムな時間 (1 分、8 分、2 時間など) 後に ping タイムアウト (PingTimeoutChannel) を受信すると、応答が停止します。最も重要なサーバーは v.5.13、API v.4 です。
ボットは、新しい Client4 を作成して Mattermost API に接続します。次に、ユーザーとしてログインし、受け取った認証トークンを使用して Websocket クライアントを作成します。すべてのチャネルでリッスンを開始し、彼 (@botname) に向けられたメッセージであるイベントを受信すると、自動的に応答します (model.post を作成します)。
Mattermost のサンプル ボットと同様に、単純なユーザー名/パスワード認証を使用してログインすることにしました。ただし、タイムアウトの問題を解決できると思ったので、個人アクセストークン認証 (ここのように) に書き換えてみました。ただし、この解決策はもう機能しません。その方法でログインしようとすると、「無効または期限切れのセッション エラーです。もう一度ログインしてください」というメッセージが表示されます。
そこで、私はこの考えを捨てて、タイムアウトが発生する場所を探し始めました。サーバーのpingは問題ありませんが、websocketはそうではありません。再接続するところまで、さまざまな方法を試しました (新しい Mattermost API と Websocket クライアントを再度作成することによって)。ボットはまだ応答しません。アイデアが尽きた。
Websocket 接続 (スキップされたエラー処理):
if config.BotCfg.Port == "443" {
protocol = "https"
secure = true
}
config.ConnectionCfg.Client = model.NewAPIv4Client(fmt.Sprintf("%s://%s:%s", protocol, config.BotCfg.Server, config.BotCfg.Port))
user,resp := config.ConnectionCfg.Client.Login(config.BotCfg.BotName, config.BotCfg.Password)
setBotTeam()
if limit.Users == nil {
limit.SetUsersList()
}
ws := "ws"
if secure {
ws = "wss"
}
if Websocket != nil {
Websocket.Close()
}
websocket, err := model.NewWebSocketClient4(fmt.Sprintf("%s://%s:%s", ws, config.BotCfg.Server, config.BotCfg.Port), config.ConnectionCfg.Client.AuthToken)
リスニング機能:
for {
select {
case <-connection.Websocket.PingTimeoutChannel:
logs.WriteToFile("Websocket ping timeout. Connecting again.")
log.Println("Websocket ping timeout. Connecting again.")
mux.Lock()
connection.Connect()
mux.Unlock()
case event := <-connection.Websocket.EventChannel:
mux.Lock()
if event != nil {
if event.IsValid() && isMessage(event.Event){
handleEvent(event)
}
}
mux.Unlock()
}
}
}()
// block to the go function
select {}
ボットが継続的に実行されることを期待しています。この問題を解決する方法について何か提案があれば、本当に感謝します!
編集: Ceriseが示唆したように、SIGQUIT を exit 関数に追加し、レース検出器を実行しました。ケース イベント := [...] から if を 1 つ削除して、データ競合の問題を修正しました。Race Detector は問題を報告しなくなりましたが、ボットはしばらくすると応答を停止します。
初めて PingTimeout が発生すると、アプリを再起動するまでピアが応答を停止することがわかりました。Websocket の再接続は役に立ちません。ただし、この問題を解決する方法が実際にはわからないか、解決策が存在することさえありません。