From aa6383c1cfdaf0d6a7338f696f061283590ebbf7 Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 17 Feb 2023 18:16:13 +0100 Subject: [PATCH] Fix instances taking too long to stop --- CHANGELOG.md | 1 + src/bot/instance.rs | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df9c471..178c4c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Procedure when bumping the version number: ### Fixed - `!uptime` minute count - Instance reconnecting after encountering a 404 (it now stops and logs an error) +- Instance taking too long to stop when stopped during reconnect delay ## v0.3.0 - 2023-02-11 diff --git a/src/bot/instance.rs b/src/bot/instance.rs index 668cc2c..52d5d02 100644 --- a/src/bot/instance.rs +++ b/src/bot/instance.rs @@ -2,6 +2,7 @@ //! //! See [`Instance`] for more details. +use std::convert::Infallible; use std::fmt; use std::str::FromStr; use std::sync::{Arc, Mutex}; @@ -276,6 +277,9 @@ enum RunError { pub struct Instance { config: InstanceConfig, request_tx: mpsc::UnboundedSender, + // In theory, request_tx should be sufficient as canary, but I'm not sure + // exactly how to check it during the reconnect timeout. + _canary_tx: oneshot::Sender, } impl Instance { @@ -306,9 +310,22 @@ impl Instance { F: Fn(Event) + Send + Sync + 'static, { idebug!(config, "Created with config {config:?}"); + let (request_tx, request_rx) = mpsc::unbounded_channel(); - tokio::spawn(Self::run::(config.clone(), on_event, request_rx)); - Self { config, request_tx } + let (canary_tx, canary_rx) = oneshot::channel(); + + tokio::spawn(Self::run::( + config.clone(), + on_event, + request_rx, + canary_rx, + )); + + Self { + config, + request_tx, + _canary_tx: canary_tx, + } } pub fn config(&self) -> &InstanceConfig { @@ -342,13 +359,26 @@ impl Instance { async fn run( config: InstanceConfig, on_event: F, + request_rx: mpsc::UnboundedReceiver, + canary_rx: oneshot::Receiver, + ) { + select! { + _ = Self::stay_connected(&config, &on_event, request_rx) => (), + _ = canary_rx => { idebug!(config, "Instance dropped"); }, + } + on_event(Event::Stopped(config)) + } + + async fn stay_connected( + config: &InstanceConfig, + on_event: &F, mut request_rx: mpsc::UnboundedReceiver, ) { loop { idebug!(config, "Connecting..."); on_event(Event::Connecting(config.clone())); - let result = Self::run_once::(&config, &on_event, &mut request_rx).await; + let result = Self::run_once::(config, on_event, &mut request_rx).await; on_event(Event::Disconnected(config.clone())); let connected = match result { @@ -386,8 +416,6 @@ impl Instance { tokio::time::sleep(config.server.reconnect_delay).await; } } - - on_event(Event::Stopped(config)) } fn get_cookies(config: &InstanceConfig) -> HeaderValue {