};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
+use tracing::debug;
#[async_trait::async_trait(?Send)]
pub(crate) trait GetCommunity {
let object_value = serde_json::to_value(&self.object)?;
let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
- insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
+ let insert =
+ insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
+ if !insert {
+ debug!(
+ "Received duplicate activity in announce {}",
+ object_data.id.to_string()
+ );
+ return Ok(());
+ }
}
}
self.object.receive(context, request_counter).await
use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize};
use std::{fmt::Debug, io::Read};
-use tracing::info;
+use tracing::{debug, info};
use url::Url;
mod comment;
// Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen
// if we receive the same activity twice in very quick succession.
let object_value = serde_json::to_value(&activity)?;
- insert_activity(&activity_data.id, object_value, false, true, context.pool()).await?;
+ let insert =
+ insert_activity(&activity_data.id, object_value, false, true, context.pool()).await?;
+ if !insert {
+ debug!(
+ "Received duplicate activity {}",
+ activity_data.id.to_string()
+ );
+ return Ok(HttpResponse::BadRequest().finish());
+ }
info!("Receiving activity {}", activity_data.id.to_string());
activity
local: bool,
sensitive: bool,
pool: &DbPool,
-) -> Result<(), LemmyError> {
+) -> Result<bool, LemmyError> {
let ap_id = ap_id.to_owned().into();
- blocking(pool, move |conn| {
- Activity::insert(conn, ap_id, activity, local, sensitive)
- })
- .await??;
- Ok(())
+ Ok(
+ blocking(pool, move |conn| {
+ Activity::insert(conn, ap_id, activity, local, sensitive)
+ })
+ .await??,
+ )
}
use crate::{newtypes::DbUrl, source::activity::*, traits::Crud};
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+ dsl::*,
+ result::{DatabaseErrorKind, Error},
+ *,
+};
use serde_json::Value;
-use std::io::{Error as IoError, ErrorKind};
impl Crud for Activity {
type Form = ActivityForm;
}
impl Activity {
+ /// Returns true if the insert was successful
pub fn insert(
conn: &PgConnection,
ap_id: DbUrl,
data: Value,
local: bool,
sensitive: bool,
- ) -> Result<Activity, IoError> {
+ ) -> Result<bool, Error> {
let activity_form = ActivityForm {
ap_id,
data,
sensitive,
updated: None,
};
- let result = Activity::create(conn, &activity_form);
- match result {
- Ok(s) => Ok(s),
- Err(e) => Err(IoError::new(
- ErrorKind::Other,
- format!("Failed to insert activity into database: {}", e),
- )),
+ match Activity::create(conn, &activity_form) {
+ Ok(_) => Ok(true),
+ Err(e) => {
+ if let Error::DatabaseError(DatabaseErrorKind::UniqueViolation, _) = e {
+ return Ok(false);
+ }
+ Err(e)
+ }
}
}