use crate::events::errors::EventProcessorError;
use crate::handle_indexing_results;
use nexus_common::db::queries::get::user_is_safe_to_delete;
use nexus_common::db::{execute_graph_operation, OperationOutcome};
use nexus_common::models::user::UserSearch;
use nexus_common::models::{
traits::Collection,
user::{UserCounts, UserDetails},
};
use nexus_common::types::DynError;
use pubky_app_specs::{PubkyAppUser, PubkyId};
use tracing::debug;
pub async fn sync_put(user: PubkyAppUser, user_id: PubkyId) -> Result<(), DynError> {
debug!("Indexing new user profile: {}", user_id);
let user_details = UserDetails::from_homeserver(user, &user_id).await?;
user_details
.put_to_graph()
.await
.map_err(|e| EventProcessorError::GraphQueryFailed {
message: format!("{e:?}"),
})?;
let indexing_results = tokio::join!(
async {
UserSearch::put_to_index(&[&user_details]).await?;
Ok::<(), DynError>(())
},
async {
if UserCounts::get_from_index(&user_id).await?.is_none() {
UserCounts::default().put_to_index(&user_id).await?;
}
Ok::<(), DynError>(())
},
async {
UserDetails::put_to_index(&[&user_details.id], vec![Some(user_details.clone())])
.await?;
Ok::<(), DynError>(())
}
);
handle_indexing_results!(indexing_results.0, indexing_results.1, indexing_results.2);
Ok(())
}
pub async fn del(user_id: PubkyId) -> Result<(), DynError> {
debug!("Deleting user profile: {}", user_id);
let query = user_is_safe_to_delete(&user_id);
match execute_graph_operation(query).await? {
OperationOutcome::CreatedOrDeleted => {
let indexing_results =
tokio::join!(UserDetails::delete(&user_id), UserCounts::delete(&user_id));
handle_indexing_results!(indexing_results.0, indexing_results.1)
}
OperationOutcome::Updated => {
let deleted_user = PubkyAppUser {
name: "[DELETED]".to_string(),
bio: None,
status: None,
links: None,
image: None,
};
sync_put(deleted_user, user_id).await?;
}
OperationOutcome::MissingDependency => return Err(EventProcessorError::SkipIndexing.into()),
}
Ok(())
}