diff --git a/ext_calckey_model/src/note_model/mod.rs b/ext_calckey_model/src/note_model/mod.rs index 56e58ea..0c92e4d 100644 --- a/ext_calckey_model/src/note_model/mod.rs +++ b/ext_calckey_model/src/note_model/mod.rs @@ -3,8 +3,8 @@ pub mod data; use ext_calckey_model_migration::SelectStatement; use sea_orm::sea_query::{Asterisk, Expr, IntoIden, Query, SelectExpr, SimpleExpr}; use sea_orm::{ - Condition, EntityTrait, Iden, JoinType, QueryFilter, QueryOrder, QuerySelect, QueryTrait, - Select, + Condition, EntityTrait, Iden, IntoSimpleExpr, JoinType, QueryFilter, QueryOrder, QuerySelect, + QueryTrait, Select, }; use std::sync::Arc; @@ -247,6 +247,7 @@ impl NoteResolver { .add(join_columns_default( note::Relation::SelfRef2.with_alias(note_tbl, &reply_tbl), )) + .add(note_tbl.col(note::Column::IsQuote).not()) .add(visibility_filter); q.join_columns_on( JoinType::LeftJoin, @@ -255,17 +256,20 @@ impl NoteResolver { condition, ); + // A renote to a reply can only happen if it is a reply to a quote, and since it is very unlikely, + // we spare save much more time by avoiding joining quotes in a hot path and fetching in post-processing, + // hence the reduced renote depth self.attach_note( q, &reply_tbl, reply_depth - 1, - renote_depth, + renote_depth.saturating_sub(1), options, user_resolver, ); } - // Recursively attach renote/quote targets + // Recursively attach renote targets if renote_depth > 0 { let renote_tbl = note_tbl.join_str(RENOTE); let visibility_filter = options @@ -314,7 +318,7 @@ impl NoteResolver { &mut select, ¬e_tbl, options.with_reply_target.then_some(1).unwrap_or_default(), - options.with_renote_target.then_some(2).unwrap_or_default(), + options.with_renote_target.then_some(1).unwrap_or_default(), options, &self.user_resolver, ); diff --git a/src/model/processing/note.rs b/src/model/processing/note.rs index 02e349a..a65246a 100644 --- a/src/model/processing/note.rs +++ b/src/model/processing/note.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use crate::model::data::id::BaseId; use crate::model::data::note::{NoteAttachmentSource, NoteBaseSource, NoteDetailSource}; use crate::model::processing::emoji::EmojiModel; @@ -35,6 +33,7 @@ use magnetar_sdk::types::user::UserRelationship; use magnetar_sdk::types::{Id, MmXml}; use magnetar_sdk::{mmm, Optional, Packed, Required}; use serde::Deserialize; +use std::sync::Arc; use tokio::try_join; use super::drive::DriveModel; @@ -507,24 +506,29 @@ impl NoteModel { ))) } - fn pack_full_single<'a>( + fn pack_full_single<'b, 'a: 'b>( &'a self, ctx: &'a PackingContext, - note: &'a NoteData, - ) -> BoxFuture<'a, PackResult> { + note: &'b (dyn NoteShapedData<'a> + 'b), + ) -> BoxFuture<'b, PackResult> { async move { let drive_model = DriveModel; let reply_target = async { - match note.reply.as_ref() { - Some(r) if self.with_context => self.pack_full_single(ctx, r).await.map(Some), + match note.reply() { + Some(r) if self.with_context => { + self.pack_full_single(ctx, r.as_ref()).await.map(Some) + } _ => Ok(None), } }; let renote_target = async { - match note.renote.as_ref() { - Some(r) if self.with_context => self.pack_full_single(ctx, r).await.map(Some), + match (note.renote(), ¬e.note().renote_id, note.note().is_quote) { + (Some(r), _, _) if self.with_context => { + self.pack_full_single(ctx, r.as_ref()).await.map(Some) + } + (_, Some(renote_id), Some(true)) => self.fetch_single(ctx, renote_id).await, _ => Ok(None), } }; @@ -539,7 +543,7 @@ impl NoteModel { reply_target_pack, renote_target_pack, ) = try_join!( - self.pack_single_attachments(ctx, &drive_model, ¬e), + self.pack_single_attachments(ctx, &drive_model, note), reply_target, renote_target )?; @@ -602,7 +606,7 @@ impl NoteModel { return Ok(None); }; - Ok(Some(self.pack_full_single(ctx, ¬e).await?)) + Ok(Some(self.pack_full_single(ctx, &¬e).await?)) } pub async fn fetch_pins( @@ -620,7 +624,7 @@ impl NoteModel { time_range: None, limit: None, user_options: UserResolveOptions { - with_avatar: self.with_context, + with_avatar: false, // This is gonna be likely cached with_banner: false, with_profile: false, }, @@ -639,7 +643,9 @@ impl NoteModel { }) .await?; - let fut_iter = notes + let note_refs = notes.iter().collect::>(); + + let fut_iter = note_refs .iter() .map(|note| self.pack_full_single(ctx, note)) .collect::>();