chamber_vault/
autolock_service.rs1use crate::autolock::{ActivityTracker, AutoLockConfig};
3use async_trait::async_trait;
4use std::sync::Arc;
5use tokio::sync::RwLock;
6use tokio::time::{Duration as TokioDuration, sleep};
7use tracing::{debug, info, warn};
8
9#[async_trait]
10pub trait AutoLockCallback: Send + Sync {
11 async fn on_auto_lock(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
12}
13
14pub struct AutoLockService {
15 pub activity_tracker: ActivityTracker,
16 callback: Arc<dyn AutoLockCallback>,
17 is_running: Arc<RwLock<bool>>,
18}
19
20impl AutoLockService {
21 pub fn new(config: AutoLockConfig, callback: Arc<dyn AutoLockCallback>) -> Self {
22 Self {
23 activity_tracker: ActivityTracker::new(config),
24 callback,
25 is_running: Arc::new(RwLock::new(false)),
26 }
27 }
28
29 pub async fn start(&self) -> tokio::task::JoinHandle<()> {
30 let activity_tracker = self.activity_tracker.clone();
31 let callback = Arc::clone(&self.callback);
32 let is_running = Arc::clone(&self.is_running);
33
34 *is_running.write().await = true;
35
36 tokio::spawn(async move {
37 let check_interval = TokioDuration::from_secs(activity_tracker.get_config().check_interval_seconds);
38
39 info!("Auto-lock service started");
40
41 while *is_running.read().await {
42 if activity_tracker.should_auto_lock().await {
43 info!("Auto-lock triggered due to inactivity");
44
45 match callback.on_auto_lock().await {
46 Ok(()) => {
47 debug!("Auto-lock callback executed successfully");
48 }
49 Err(e) => {
50 warn!("Auto-lock callback failed: {}", e);
51 }
52 }
53
54 activity_tracker.update_activity().await;
56 }
57
58 sleep(check_interval).await;
59 }
60
61 info!("Auto-lock service stopped");
62 })
63 }
64
65 pub async fn stop(&self) {
66 *self.is_running.write().await = false;
67 }
68
69 pub async fn update_activity(&self) {
70 self.activity_tracker.update_activity().await;
71 }
72
73 pub async fn get_time_until_lock(&self) -> Option<chrono::Duration> {
74 self.activity_tracker.time_until_lock().await
75 }
76
77 #[must_use]
78 pub const fn is_enabled(&self) -> bool {
79 self.activity_tracker.get_config().enabled
80 }
81}