blob: d5416856cdb45160c8518d3428231b2f1eb94db0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
//! Channel tasks of the arti-relay.
//!
//! The tasks are:
//! * [`ChannelHouseKeepingTask`] which is in charge of regularly going over existing channels
//! to clean up expiring ones and prune duplicates. At the start, it will run in
//! [`ChannelHouseKeepingTask::START_TICK_TIME`] seconds and then the channel expiry function
//! tells it how much time to sleep.
use anyhow::Context;
use std::{
sync::{Arc, Weak},
time::Duration,
};
use tracing::debug;
use tor_chanmgr::ChanMgr;
use tor_rtcompat::Runtime;
/// Channel housekeeping standalone background task.
pub(crate) struct ChannelHouseKeepingTask<R: Runtime> {
/// Weak reference to the ChanMgr. If it disappears, task stops.
mgr: Weak<ChanMgr<R>>,
}
impl<R: Runtime> ChannelHouseKeepingTask<R> {
/// Starting tick time is to run in 3 minutes. The ChanMgr expire channels uses a default of
/// 180 seconds and so we simply align with that for the first run. After that, the channel
/// subsystems will tell us how long to wait if any channels.
const START_TICK_TIME: Duration = Duration::from_secs(180);
/// Constructor.
pub(crate) fn new(mgr: &Arc<ChanMgr<R>>) -> Self {
Self {
mgr: Arc::downgrade(mgr),
}
}
/// Run the background task.
#[allow(clippy::unused_async)] // TODO(relay)
async fn run(&mut self) -> anyhow::Result<Duration> {
let mgr = Weak::upgrade(&self.mgr).context("Channel manager is gone")?;
// Expire any channels that are possibly closing.
let next_expiry = mgr.expire_channels();
// TODO: Another action is to prune duplicate channels like C-tor does in
// channel_update_bad_for_new_circs().
Ok(next_expiry)
}
/// Start the task.
pub(crate) async fn start(&mut self) -> anyhow::Result<void::Void> {
let mut next_tick_in = Self::START_TICK_TIME;
debug!("Channel housekeeping task starting.");
loop {
// Sleep until next tick.
tokio::time::sleep(next_tick_in).await;
// Run this task. The returned value is the next tick.
next_tick_in = self
.run()
.await
.context("Shutting down channel housekeeping task")?;
}
}
}
|