mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
fix(cli,core): wake the parked login-wait daemon on sign-in
The login backoff had no wake-up path. A unit started at boot sits in wait_for_session and reaches the ceiling within ~90s; the user then signs in and `enable --now` is a no-op on an already-active unit, so the daemon kept sleeping and the mount appeared up to a full interval late. - service::enable_start now runs `enable` + `restart` instead of `enable --now`, so the GUI login and the tray's Connect interrupt the sleep immediately and still start a unit that is down. - `pdfs login` restarts the unit when it is already active. It stays out of `enable` on purpose, so a headless setup driving `pdfs daemon` by hand is left alone. - Lower the backoff ceiling from 60s to 15s. It is still an 80% cut in keyring/D-Bus wakeups (28,800/day -> 5,760/day) and it bounds the worst-case latency for paths that never touch systemd. Also corrects the flat-3s-poll figure in the doc comment: 86400/3 is 28,800 checks a day, not 48,000.
This commit is contained in:
1 parent
637b512f6a
commit
45852082c0
2 files changed
+36
-14
No files matched your search
+25
-11
@@ -17,6 +17,7 @@ use pdfs_core::control::{
|
||||
RestoreItem as CtlRestoreItem, ShareEntryKind, SyncPhase, pending_summary,
|
||||
};
|
||||
use pdfs_core::db::Db;
|
||||
use pdfs_core::service;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
@@ -1309,6 +1310,15 @@ fn cmd_login(username: Option<String>) -> Result<()> {
|
||||
other => anyhow::Error::new(other).context("login failed"),
|
||||
})?;
|
||||
|
||||
// A daemon that is already up is parked in `wait_for_session`, sleeping
|
||||
// between keyring checks; restart it so the mount appears now instead of
|
||||
// whenever the next poll fires. Only when it is already active — `pdfs
|
||||
// login` deliberately does not enable the unit the way the GUI does, so a
|
||||
// headless user driving `pdfs daemon` by hand keeps that setup.
|
||||
if service::is_active() {
|
||||
service::restart();
|
||||
}
|
||||
|
||||
println!("Logged in as {username}. Session stored in the system keyring.");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1451,14 +1461,19 @@ fn cmd_mount(mountpoint: Option<PathBuf>) -> Result<()> {
|
||||
/// How long to wait before the next login check, after `attempts` checks have
|
||||
/// already come back [`pdfs_core::Error::NotLoggedIn`].
|
||||
///
|
||||
/// Doubles from 3s to a 60s ceiling. The interval is not just a sleep:
|
||||
/// Doubles from 3s to a 15s ceiling. The interval is not just a sleep:
|
||||
/// [`auth::load`] builds a fresh `keyring::Entry` on every call, so each check
|
||||
/// opens a new D-Bus connection to the Secret Service and negotiates an
|
||||
/// encrypted session over it. A flat 3s poll meant roughly 48,000 of those a
|
||||
/// day from a daemon that had nothing to do.
|
||||
/// encrypted session over it. A flat 3s poll meant 28,800 of those a day from a
|
||||
/// daemon that had nothing to do; the ceiling cuts that by 80%.
|
||||
///
|
||||
/// The ceiling stays low because the sleep is also the worst-case login →
|
||||
/// mount latency for anything that does *not* poke systemd: front-ends restart
|
||||
/// the unit on login (`service::enable_start`), which interrupts the sleep
|
||||
/// immediately, but a hand-run `pdfs daemon` has no such wake-up path.
|
||||
fn login_poll_delay(attempts: u32) -> std::time::Duration {
|
||||
const BASE_SECS: u64 = 3;
|
||||
const MAX_SECS: u64 = 60;
|
||||
const MAX_SECS: u64 = 15;
|
||||
|
||||
// `checked_shl` rather than `<<`: the daemon can sit unauthenticated for
|
||||
// weeks, and a shift past the width of the type is a panic, not a big number.
|
||||
@@ -2587,13 +2602,12 @@ mod login_wait_tests {
|
||||
assert_eq!(login_poll_delay(0), Duration::from_secs(3));
|
||||
assert_eq!(login_poll_delay(1), Duration::from_secs(6));
|
||||
assert_eq!(login_poll_delay(2), Duration::from_secs(12));
|
||||
assert_eq!(login_poll_delay(3), Duration::from_secs(24));
|
||||
assert_eq!(login_poll_delay(4), Duration::from_secs(48));
|
||||
assert_eq!(login_poll_delay(5), Duration::from_secs(60));
|
||||
assert_eq!(login_poll_delay(3), Duration::from_secs(15));
|
||||
assert_eq!(login_poll_delay(4), Duration::from_secs(15));
|
||||
// A daemon left unauthenticated for weeks reaches attempt counts well
|
||||
// past the width of the shift; that must cap, not panic.
|
||||
assert_eq!(login_poll_delay(64), Duration::from_secs(60));
|
||||
assert_eq!(login_poll_delay(u32::MAX), Duration::from_secs(60));
|
||||
assert_eq!(login_poll_delay(64), Duration::from_secs(15));
|
||||
assert_eq!(login_poll_delay(u32::MAX), Duration::from_secs(15));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2625,8 +2639,8 @@ mod login_wait_tests {
|
||||
// the way a flat 3s poll did.
|
||||
let total: Duration = slept.iter().sum();
|
||||
assert!(
|
||||
total >= Duration::from_secs(15 * 60),
|
||||
"20 checks should span at least 15 minutes, spanned {total:?}"
|
||||
total >= Duration::from_secs(4 * 60),
|
||||
"20 checks should span at least 4 minutes, spanned {total:?}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user