settings dialog works now and reloads the session properly

This commit is contained in:
Igor Katson 2023-12-06 23:18:06 +00:00
parent e4543e1ba2
commit 9cbe16b387
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
13 changed files with 123 additions and 49 deletions

View file

@ -107,7 +107,9 @@ mod tests {
init_logging();
let info_hash = Id20::from_str("cab507494d02ebb1178b38f2e9d7be299c86b862").unwrap();
let dht = DhtBuilder::new().await.unwrap();
let (dht, run_dht) = DhtBuilder::new().await.unwrap();
tokio::spawn(run_dht);
let peer_rx = dht.get_peers(info_hash, None).unwrap();
let peer_id = generate_peer_id();
match read_metainfo_from_peer_receiver(peer_id, info_hash, Vec::new(), peer_rx, None).await

View file

@ -150,6 +150,23 @@ struct SerializedSessionDatabase {
torrents: HashMap<usize, SerializedTorrent>,
}
fn spawn_with_cancel_token(
mut cancel_rx: tokio::sync::watch::Receiver<()>,
name: &str,
span: tracing::Span,
fut: impl std::future::Future<Output = anyhow::Result<()>> + Send + 'static,
) {
spawn(name, span, async move {
tokio::select! {
r = fut => r,
_ = cancel_rx.changed() => {
debug!("task canceled");
Ok(())
}
}
});
}
pub struct Session {
peer_id: Id20,
dht: Option<Dht>,
@ -385,6 +402,8 @@ impl Session {
) -> anyhow::Result<Arc<Self>> {
let peer_id = opts.peer_id.unwrap_or_else(generate_peer_id);
let (cancel_tx, cancel_rx) = tokio::sync::watch::channel(());
let (tcp_listener, tcp_listen_port) = if let Some(port_range) = opts.listen_port_range {
let (l, p) = create_tcp_listener(port_range)
.await
@ -399,12 +418,26 @@ impl Session {
None
} else {
let dht = if opts.disable_dht_persistence {
DhtBuilder::with_config(DhtConfig::default()).await
let (dht, run_worker) = DhtBuilder::with_config(DhtConfig::default())
.await
.context("error initializing DHT")?;
spawn_with_cancel_token(cancel_rx.clone(), "dht", error_span!("dht"), run_worker);
dht
} else {
let pdht_config = opts.dht_config.take().unwrap_or_default();
PersistentDht::create(Some(pdht_config)).await
}
.context("error initializing DHT")?;
let (dht, run_worker, run_persistence) = PersistentDht::create(Some(pdht_config))
.await
.context("error initializing persistent DHT")?;
spawn_with_cancel_token(cancel_rx.clone(), "dht", error_span!("dht"), run_worker);
spawn_with_cancel_token(
cancel_rx.clone(),
"dht_persistence",
error_span!("dht_persistence"),
run_persistence,
);
dht
};
Some(dht)
};
let peer_opts = opts.peer_opts.unwrap_or_default();
@ -414,8 +447,6 @@ impl Session {
};
let spawner = BlockingSpawner::default();
let (cancel_tx, cancel_rx) = tokio::sync::watch::channel(());
let session = Arc::new(Self {
persistence_filename,
peer_id,
@ -618,22 +649,26 @@ impl Session {
span: tracing::Span,
fut: impl std::future::Future<Output = anyhow::Result<()>> + Send + 'static,
) {
let mut cancel_rx = self.cancel_rx.clone();
spawn(name, span, async move {
tokio::select! {
r = fut => r,
_ = cancel_rx.changed() => {
debug!("task canceled");
Ok(())
}
}
});
spawn_with_cancel_token(self.cancel_rx.clone(), name, span, fut);
}
/// Stop the session and all managed tasks.
// TODO: this probably doesn't kill everything properly.
pub async fn stop(&self) {
let torrents = self
.db
.read()
.torrents
.values()
.cloned()
.collect::<Vec<_>>();
for torrent in torrents {
if let Err(e) = torrent.pause() {
debug!("error pausing torrent: {e:#}");
}
}
let _ = self.cancel_tx.send(());
// this sucks, but hopefully will be enough
tokio::time::sleep(Duration::from_secs(1)).await;
}
async fn populate_from_stored(self: &Arc<Self>) -> anyhow::Result<()> {