Ignore NotFound errors when receiving activities (fixes #2240)

This commit is contained in:
Felix Ableitner 2024-09-25 13:21:20 +02:00
parent f6a24e133a
commit 99cdf742d4
4 changed files with 34 additions and 12 deletions

1
Cargo.lock generated
View file

@ -2795,6 +2795,7 @@ dependencies = [
name = "lemmy_utils"
version = "0.19.6-beta.7"
dependencies = [
"activitypub_federation",
"actix-web",
"anyhow",
"cfg-if",

View file

@ -17,7 +17,7 @@ use lemmy_db_schema::{
source::{activity::SentActivity, community::Community},
CommunityVisibility,
};
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
use lemmy_utils::error::{LemmyError, LemmyErrorType, LemmyResult};
use serde::{Deserialize, Serialize};
use std::{ops::Deref, time::Duration};
use tokio::time::timeout;
@ -43,9 +43,16 @@ pub async fn shared_inbox(
// avoid taking a long time to process an incoming activity when a required data fetch times out.
// In this case our own instance would timeout and be marked as dead by the sender. Better to
// consider the activity broken and move on.
timeout(INCOMING_ACTIVITY_TIMEOUT, receive_fut)
.await
.map_err(|_| LemmyErrorType::InboxTimeout)?
let res = timeout(INCOMING_ACTIVITY_TIMEOUT, receive_fut).await;
match res {
// Ignore NotFound error, usually means that the sending actor was deleted and sent a delete
// activity: https://github.com/LemmyNet/lemmy/issues/2240
Ok(Err(LemmyError {error_type: LemmyErrorType::NotFound, ..})) => Ok(HttpResponse::Ok().finish()),
// Top-level error means we hit the send timeout
Err(_) => Err(LemmyErrorType::InboxTimeout.into()),
Ok(other) => other,
}
}
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub

View file

@ -47,6 +47,7 @@ full = [
"dep:uuid",
"dep:itertools",
"dep:markdown-it",
"dep:activitypub_federation"
]
[dependencies]
@ -80,6 +81,7 @@ lettre = { version = "0.11.8", default-features = false, features = [
markdown-it = { version = "0.6.1", optional = true }
ts-rs = { workspace = true, optional = true }
enum-map = { workspace = true, optional = true }
activitypub_federation = { workspace = true, optional = true }
cfg-if = "1"
clearurls = { version = "0.0.4", features = ["linkify"] }

View file

@ -198,10 +198,14 @@ cfg_if! {
{
fn from(t: T) -> Self {
let cause = t.into();
let error_type = match cause.downcast_ref::<diesel::result::Error>() {
Some(&diesel::NotFound) => LemmyErrorType::NotFound,
_ => LemmyErrorType::Unknown(format!("{}", &cause))
};
let error_type = if let Some(&diesel::NotFound) = cause.downcast_ref::<diesel::result::Error>() {
LemmyErrorType::NotFound
} else if let Some(activitypub_federation::error::Error::NotFound) = cause.downcast_ref::<activitypub_federation::error::Error>() {
LemmyErrorType::NotFound
}
else {
LemmyErrorType::Unknown(format!("{}", &cause))
};
LemmyError {
error_type,
inner: cause,
@ -231,11 +235,15 @@ cfg_if! {
impl actix_web::error::ResponseError for LemmyError {
fn status_code(&self) -> actix_web::http::StatusCode {
if self.error_type == LemmyErrorType::IncorrectLogin {
return actix_web::http::StatusCode::UNAUTHORIZED;
actix_web::http::StatusCode::UNAUTHORIZED
}
match self.inner.downcast_ref::<diesel::result::Error>() {
Some(diesel::result::Error::NotFound) => actix_web::http::StatusCode::NOT_FOUND,
_ => actix_web::http::StatusCode::BAD_REQUEST,
else if let Some(&diesel::NotFound) = self.inner.downcast_ref::<diesel::result::Error>() {
actix_web::http::StatusCode::NOT_FOUND
} else if let Some(activitypub_federation::error::Error::NotFound) = self.inner.downcast_ref::<activitypub_federation::error::Error>() {
actix_web::http::StatusCode::NOT_FOUND
}
else {
actix_web::http::StatusCode::BAD_REQUEST
}
}
@ -320,6 +328,10 @@ cfg_if! {
assert_eq!(LemmyErrorType::NotFound, not_found_error.error_type);
assert_eq!(404, not_found_error.status_code());
let apub_not_found_error = LemmyError::from(activitypub_federation::error::Error::NotFound);
assert_eq!(LemmyErrorType::NotFound, apub_not_found_error.error_type);
assert_eq!(404, apub_not_found_error.status_code());
let other_error = LemmyError::from(diesel::result::Error::NotInTransaction);
assert!(matches!(other_error.error_type, LemmyErrorType::Unknown{..}));
assert_eq!(400, other_error.status_code());