feat: add better error handling for sync (#1572)

Hopefully this helps users get more descriptive errors, and give more
descriptive bug reports
This commit is contained in:
Ellie Huxtable 2024-01-15 12:57:28 +00:00 committed by GitHub
parent 69ec991118
commit ecce55b445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -143,6 +143,28 @@ pub fn ensure_version(response: &Response) -> Result<bool> {
Ok(true) Ok(true)
} }
async fn handle_resp_error(resp: Response) -> Result<Response> {
let status = resp.status();
if status == StatusCode::SERVICE_UNAVAILABLE {
bail!(
"Service unavailable: check https://status.atuin.sh (or get in touch with your host)"
);
}
if status.is_client_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("Could not fetch history, client error: {error}.")
} else if status.is_server_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("There was an error with the atuin sync service: {error}.\nIf the problem persists, contact the host")
} else if !status.is_success() {
bail!("There was an error with the atuin sync service: Status {status:?}.\nIf the problem persists, contact the host")
}
Ok(resp)
}
impl<'a> Client<'a> { impl<'a> Client<'a> {
pub fn new( pub fn new(
sync_addr: &'a str, sync_addr: &'a str,
@ -172,6 +194,7 @@ impl<'a> Client<'a> {
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let resp = handle_resp_error(resp).await?;
if !ensure_version(&resp)? { if !ensure_version(&resp)? {
bail!("could not sync due to version mismatch"); bail!("could not sync due to version mismatch");
@ -191,15 +214,12 @@ impl<'a> Client<'a> {
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let resp = handle_resp_error(resp).await?;
if !ensure_version(&resp)? { if !ensure_version(&resp)? {
bail!("could not sync due to version mismatch"); bail!("could not sync due to version mismatch");
} }
if resp.status() != StatusCode::OK {
bail!("failed to get status (are you logged in?)");
}
let status = resp.json::<StatusResponse>().await?; let status = resp.json::<StatusResponse>().await?;
Ok(status) Ok(status)
@ -228,27 +248,18 @@ impl<'a> Client<'a> {
); );
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let resp = handle_resp_error(resp).await?;
let status = resp.status();
if status.is_success() {
let history = resp.json::<SyncHistoryResponse>().await?; let history = resp.json::<SyncHistoryResponse>().await?;
Ok(history) Ok(history)
} else if status.is_client_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("Could not fetch history: {error}.")
} else if status.is_server_error() {
let error = resp.json::<ErrorResponse>().await?.reason;
bail!("There was an error with the atuin sync service: {error}.\nIf the problem persists, contact the host")
} else {
bail!("There was an error with the atuin sync service: Status {status:?}.\nIf the problem persists, contact the host")
}
} }
pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> { pub async fn post_history(&self, history: &[AddHistoryRequest]) -> Result<()> {
let url = format!("{}/history", self.sync_addr); let url = format!("{}/history", self.sync_addr);
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
self.client.post(url).json(history).send().await?; let resp = self.client.post(url).json(history).send().await?;
handle_resp_error(resp).await?;
Ok(()) Ok(())
} }
@ -257,7 +268,8 @@ impl<'a> Client<'a> {
let url = format!("{}/history", self.sync_addr); let url = format!("{}/history", self.sync_addr);
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
self.client let resp = self
.client
.delete(url) .delete(url)
.json(&DeleteHistoryRequest { .json(&DeleteHistoryRequest {
client_id: h.id.to_string(), client_id: h.id.to_string(),
@ -265,6 +277,8 @@ impl<'a> Client<'a> {
.send() .send()
.await?; .await?;
handle_resp_error(resp).await?;
Ok(()) Ok(())
} }
@ -273,14 +287,7 @@ impl<'a> Client<'a> {
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
let resp = self.client.post(url).json(records).send().await?; let resp = self.client.post(url).json(records).send().await?;
info!("posted records, got {}", resp.status()); handle_resp_error(resp).await?;
if !resp.status().is_success() {
error!(
"failed to post records to server; got: {:?}",
resp.text().await
);
}
Ok(()) Ok(())
} }
@ -307,6 +314,7 @@ impl<'a> Client<'a> {
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let resp = handle_resp_error(resp).await?;
let records = resp.json::<Vec<Record<EncryptedData>>>().await?; let records = resp.json::<Vec<Record<EncryptedData>>>().await?;
@ -318,6 +326,7 @@ impl<'a> Client<'a> {
let url = Url::parse(url.as_str())?; let url = Url::parse(url.as_str())?;
let resp = self.client.get(url).send().await?; let resp = self.client.get(url).send().await?;
let resp = handle_resp_error(resp).await?;
if !ensure_version(&resp)? { if !ensure_version(&resp)? {
bail!("could not sync records due to version mismatch"); bail!("could not sync records due to version mismatch");