From a2fb42d242864a3db90634edd0209e782cb5eae7 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Mon, 26 Sep 2022 23:21:08 +0200 Subject: [PATCH] REST backend: abort at permanent errors --- src/backend/rest.rs | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/backend/rest.rs b/src/backend/rest.rs index 4ff8d3d..37cf8c8 100644 --- a/src/backend/rest.rs +++ b/src/backend/rest.rs @@ -2,14 +2,33 @@ use std::time::Duration; use anyhow::{bail, Result}; use async_trait::async_trait; -use backoff::{backoff::Backoff, ExponentialBackoff, ExponentialBackoffBuilder}; +use backoff::{backoff::Backoff, Error, ExponentialBackoff, ExponentialBackoffBuilder}; use bytes::Bytes; use log::*; -use reqwest::{Client, Url}; +use reqwest::{Client, Response, Url}; use serde::Deserialize; use super::{FileType, Id, ReadBackend, WriteBackend}; +// trait CheckError to add user-defined methoed check_error on Response +trait CheckError { + fn check_error(self) -> std::result::Result>; +} + +impl CheckError for Response { + // Check reqwest Response for error and treat errors as permanent or transient + fn check_error(self) -> std::result::Result> { + match self.error_for_status() { + Ok(t) => Ok(t), + Err(err) if err.status().unwrap().is_client_error() => Err(Error::Permanent(err)), + Err(err) => Err(Error::Transient { + err, + retry_after: None, + }), + } + } +} + #[derive(Clone)] struct MaybeBackoff(Option); @@ -32,7 +51,6 @@ pub struct RestBackend { backoff: MaybeBackoff, } -// TODO for backoff: Handle transient vs permanent errors! fn notify(err: reqwest::Error, duration: Duration) { warn!("Error {err} at {duration:?}, retrying"); } @@ -136,7 +154,7 @@ impl ReadBackend for RestBackend { .header("Accept", "application/vnd.x.restic.rest.v2") .send() .await? - .error_for_status()? + .check_error()? .json::>() .await?; Ok(list.into_iter().map(|i| (i.name, i.size)).collect()) @@ -155,7 +173,7 @@ impl ReadBackend for RestBackend { .get(self.url(tpe, id)) .send() .await? - .error_for_status()? + .check_error()? .bytes() .await? .into_iter() @@ -185,7 +203,7 @@ impl ReadBackend for RestBackend { .header("Range", header_value.clone()) .send() .await? - .error_for_status()? + .check_error()? .bytes() .await? .into_iter() @@ -207,7 +225,7 @@ impl WriteBackend for RestBackend { .post(self.url.join("?create=true").unwrap()) .send() .await? - .error_for_status()?; + .check_error()?; Ok(()) }, notify, @@ -232,7 +250,7 @@ impl WriteBackend for RestBackend { .unwrap() .send() .await? - .error_for_status()?; + .check_error()?; Ok(()) }, notify, @@ -249,7 +267,7 @@ impl WriteBackend for RestBackend { .delete(self.url(tpe, id)) .send() .await? - .error_for_status()?; + .check_error()?; Ok(()) }, notify,