sa_token_core/cleanup/
background.rs1use std::sync::Arc;
6use std::time::Duration;
7
8use tokio::sync::watch;
9use tokio::task::JoinHandle;
10use tokio::time;
11
12use crate::nonce::NonceManager;
13use crate::online::OnlineManager;
14
15#[derive(Debug, Clone)]
17pub struct CleanupConfig {
18 pub enabled: bool,
21 pub interval: Duration,
23 pub cleanup_nonce: bool,
25 pub cleanup_online: bool,
28}
29
30impl Default for CleanupConfig {
31 fn default() -> Self {
32 Self {
33 enabled: false,
34 interval: Duration::from_secs(300),
35 cleanup_nonce: true,
36 cleanup_online: true,
37 }
38 }
39}
40
41pub struct BackgroundCleanupTask {
44 stop: watch::Sender<bool>,
45 #[allow(dead_code)]
48 handle: Option<JoinHandle<()>>,
49}
50
51impl std::fmt::Debug for BackgroundCleanupTask {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 f.write_str("BackgroundCleanupTask { .. }")
54 }
55}
56
57impl BackgroundCleanupTask {
58 pub fn spawn(
60 config: CleanupConfig,
61 nonce: Option<Arc<NonceManager>>,
62 online: Option<Arc<OnlineManager>>,
63 ) -> Self {
64 let (stop, rx) = watch::channel(false);
65 if !config.enabled {
66 return Self { stop, handle: None };
67 }
68
69 let handle = tokio::spawn(async move {
70 let mut ticker = time::interval(config.interval);
71 ticker.set_missed_tick_behavior(time::MissedTickBehavior::Delay);
72 let mut rx = rx;
73 loop {
74 tokio::select! {
75 _ = ticker.tick() => {
76 if config.cleanup_nonce {
77 if let Some(n) = &nonce {
78 if let Err(e) = n.cleanup_expired().await {
79 tracing::warn!(error = %e, "nonce cleanup failed");
80 }
81 }
82 }
83 if config.cleanup_online {
84 if let Some(o) = &online {
85 match o.get_online_users().await {
86 Ok(users) => {
87 for uid in users {
88 if let Err(e) = o.get_user_sessions(&uid).await {
89 tracing::warn!(error = %e, login_id = %uid, "online prune failed");
90 }
91 }
92 }
93 Err(e) => tracing::warn!(error = %e, "online list failed during cleanup"),
94 }
95 }
96 }
97 }
98 _ = rx.changed() => {
99 if *rx.borrow() {
100 break;
101 }
102 }
103 }
104 }
105 });
106
107 Self {
108 stop,
109 handle: Some(handle),
110 }
111 }
112
113 pub fn shutdown(&self) {
115 let _ = self.stop.send(true);
116 }
117}
118
119impl Drop for BackgroundCleanupTask {
120 fn drop(&mut self) {
121 let _ = self.stop.send(true);
122 }
123}