mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-03 16:41:26 +01:00
fix(core,android,app): say why a crawl failed, not only which URL
A transport failure's text is reqwest's "error sending request for url (…)", and the cause sits further down its source chain. Error::describe appends the causes and drops the URL, so the reason fits on a share row.
This commit is contained in:
1 parent
4f130d1d6e
commit
85bc975f5f
3 files changed
+55
-3
No files matched your search
@@ -2637,11 +2637,11 @@ impl AndroidEngine {
|
||||
if let Err(error) = self
|
||||
.catalog
|
||||
.lock()
|
||||
.record_crawl_failure(&id, &error.to_string())
|
||||
.record_crawl_failure(&id, &error.describe())
|
||||
{
|
||||
log::warn!("record a failed crawl: {error}");
|
||||
}
|
||||
return Err(BridgeError::from_display(error));
|
||||
return Err(BridgeError::from_display(error.describe()));
|
||||
}
|
||||
};
|
||||
let rows = build_rows(&id, &nodes);
|
||||
|
||||
@@ -1494,7 +1494,7 @@ impl Engine {
|
||||
if let Err(error) = self
|
||||
.catalog
|
||||
.lock()
|
||||
.record_crawl_failure(&share_id, &error.to_string())
|
||||
.record_crawl_failure(&share_id, &error.describe())
|
||||
{
|
||||
tracing::warn!(%error, "record a failed crawl");
|
||||
}
|
||||
|
||||
@@ -54,6 +54,36 @@ pub enum Error {
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// The message, followed by every cause its own text leaves out.
|
||||
///
|
||||
/// A dropped connection reads as reqwest's "error sending request for url
|
||||
/// (…)" and nothing else: why — a reset, a DNS failure, a certificate — is
|
||||
/// further down the source chain. That is the part a viewer reporting a
|
||||
/// failed crawl needs, so the URL, which only says which folder, is left
|
||||
/// out to keep it on screen.
|
||||
pub fn describe(&self) -> String {
|
||||
let mut text = match self {
|
||||
Self::Drive(proton_sdk::error::ProtonError::Transport(error)) => {
|
||||
let url = error.url().map(|url| format!(" for url ({url})"));
|
||||
let own = self.to_string();
|
||||
url.map_or_else(|| own.clone(), |url| own.replace(&url, ""))
|
||||
}
|
||||
_ => self.to_string(),
|
||||
};
|
||||
let mut seen = self.to_string();
|
||||
let mut source = std::error::Error::source(self);
|
||||
while let Some(cause) = source {
|
||||
let line = cause.to_string();
|
||||
if !seen.contains(&line) {
|
||||
text.push_str(": ");
|
||||
text.push_str(&line);
|
||||
seen.push_str(&line);
|
||||
}
|
||||
source = cause.source();
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
/// Whether this is the account's session having ended: the refresh token
|
||||
/// was revoked or expired, or the token lacks a scope only a password
|
||||
/// sign-in grants. Nothing but signing in again fixes it.
|
||||
@@ -76,3 +106,25 @@ impl From<keyring::Error> for Error {
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("connection closed before message completed")]
|
||||
struct Closed;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("client error (SendRequest)")]
|
||||
struct SendRequest(#[source] Closed);
|
||||
|
||||
#[test]
|
||||
fn a_failure_is_described_with_the_causes_its_own_text_leaves_out() {
|
||||
let error = Error::Io(std::io::Error::other(SendRequest(Closed)));
|
||||
assert_eq!(
|
||||
error.describe(),
|
||||
"io: client error (SendRequest): connection closed before message completed"
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user