mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 00:47:00 +01:00
fix(core,fuse): back failed uploads off properly and spread their retries
A reconnect made every failed op due at once, quota and access refusals included, and ops that failed together retried in the same second. The doubling also stopped at 128 s, short of the 300 s maximum. Reconnects now move up only unrefused ops, and the backoff reaches its maximum with a per-op spread of up to a fifth (B237).
This commit is contained in:
1 parent
8aca7836f9
commit
fcbb15cb4b
5 files changed
+110
-12
No files matched your search
@@ -1483,12 +1483,26 @@ impl Db {
|
||||
}
|
||||
|
||||
/// [`retry_op_now`](Self::retry_op_now) for every op that has failed at
|
||||
/// least once. Returns how many rows changed.
|
||||
/// least once, for the user's "Retry all". Returns how many rows changed.
|
||||
pub fn retry_failed_ops_now(&self, now: i64) -> Result<usize> {
|
||||
self.retry_ops_now(now, "")
|
||||
}
|
||||
|
||||
/// [`retry_failed_ops_now`](Self::retry_failed_ops_now) for the ops Drive
|
||||
/// did not refuse, for a reconnect. A link coming back changes nothing
|
||||
/// about a full quota or a missing permission, so those keep their backoff
|
||||
/// instead of all being sent again at once.
|
||||
pub fn retry_unrefused_ops_now(&self, now: i64) -> Result<usize> {
|
||||
self.retry_ops_now(now, "AND issue IS NULL")
|
||||
}
|
||||
|
||||
fn retry_ops_now(&self, now: i64, filter: &str) -> Result<usize> {
|
||||
let conn = self.conn.lock();
|
||||
let changed = conn.execute(
|
||||
"UPDATE pending_op SET next_attempt_at = ?1
|
||||
WHERE attempts > 0 AND next_attempt_at > ?1 AND next_attempt_at < ?2",
|
||||
&format!(
|
||||
"UPDATE pending_op SET next_attempt_at = ?1
|
||||
WHERE attempts > 0 AND next_attempt_at > ?1 AND next_attempt_at < ?2 {filter}"
|
||||
),
|
||||
params![now, PARK_UNTIL],
|
||||
)?;
|
||||
Ok(changed)
|
||||
|
||||
@@ -7531,6 +7531,32 @@ fn a_refused_change_names_its_node_by_local_id() {
|
||||
);
|
||||
}
|
||||
|
||||
/// A reconnect moves up the ops that failed for want of a link. One Drive
|
||||
/// refused, for quota or access, keeps its backoff: the link coming back
|
||||
/// changes nothing about it. "Retry all" still moves both.
|
||||
#[test]
|
||||
fn a_reconnect_leaves_refused_ops_to_their_backoff() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
let offline = queued_op(&db, "vol~a", 2, 90_000);
|
||||
let refused = queued_op(&db, "vol~b", 2, 90_000);
|
||||
db.set_op_issue(refused, Some("quota")).unwrap();
|
||||
|
||||
assert_eq!(db.retry_unrefused_ops_now(5_000).unwrap(), 1);
|
||||
let due = |id: i64| {
|
||||
db.pending_ops()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|op| op.id == id)
|
||||
.unwrap()
|
||||
.next_attempt_at
|
||||
};
|
||||
assert_eq!(due(offline), 5_000);
|
||||
assert_eq!(due(refused), 90_000);
|
||||
|
||||
assert_eq!(db.retry_failed_ops_now(5_000).unwrap(), 1);
|
||||
assert_eq!(due(refused), 5_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn retry_all_touches_only_ops_that_have_failed() {
|
||||
let db = Db::open_in_memory().unwrap();
|
||||
|
||||
Reference in new issue
Block a user