diff --git a/consumer/src/database_writer/reference_extraction.rs b/consumer/src/database_writer/reference_extraction.rs index d0d8806e..b94c31cc 100644 --- a/consumer/src/database_writer/reference_extraction.rs +++ b/consumer/src/database_writer/reference_extraction.rs @@ -110,21 +110,23 @@ pub fn extract_references(record: &RecordTypes) -> RecordReferences { } // Like: extract author DID from liked post URI + // NOTE: Likes don't have subject_actor_id FK in DB, but we need it for notifications RecordTypes::AppBskyFeedLike(rec) => { - let mut dids = Vec::new(); if let Some(subject_did) = parakeet_db::at_uri_util::extract_did(&rec.subject.uri) { - dids.push(subject_did.to_string()); + RecordReferences::with_subject(subject_did.to_string()) + } else { + RecordReferences::empty() } - RecordReferences::with_additional(dids) } // Repost: extract author DID from reposted post URI + // NOTE: Reposts don't have subject_actor_id FK in DB, but we need it for notifications RecordTypes::AppBskyFeedRepost(rec) => { - let mut dids = Vec::new(); if let Some(subject_did) = parakeet_db::at_uri_util::extract_did(&rec.subject.uri) { - dids.push(subject_did.to_string()); + RecordReferences::with_subject(subject_did.to_string()) + } else { + RecordReferences::empty() } - RecordReferences::with_additional(dids) } // Post: extract DIDs from reply parents, quote embeds, and mentions @@ -244,8 +246,9 @@ mod tests { }); let refs = extract_references(&record); - assert_eq!(refs.subject_did, None); // Likes don't have subject_actor_id FK - assert_eq!(refs.additional_dids, vec!["did:plc:author"]); + // Likes use subject_did for notification creation (even though DB has no FK) + assert_eq!(refs.subject_did, Some("did:plc:author".to_string())); + assert_eq!(refs.additional_dids, Vec::::new()); } #[test] diff --git a/consumer/tests/mod_test.rs b/consumer/tests/mod_test.rs index e0560beb..7ee0ea29 100644 --- a/consumer/tests/mod_test.rs +++ b/consumer/tests/mod_test.rs @@ -18,7 +18,7 @@ async fn test_is_thread_muted() -> eyre::Result<()> { let tx = conn.transaction().await.wrap_err("Failed to start transaction")?; // Create recipient actor - consumer::db::actor::actor_upsert( + let recipient_id = consumer::db::actor::actor_upsert( &tx, "did:plc:recipient", Some(&ActorStatus::Active), @@ -30,10 +30,23 @@ async fn test_is_thread_muted() -> eyre::Result<()> { .await .unwrap(); + // Create root post author actor + let root_id = consumer::db::actor::actor_upsert( + &tx, + "did:plc:root", + Some(&ActorStatus::Active), + &ActorSyncState::Synced, + None, + None, + Utc::now(), + ) + .await + .unwrap(); + // Test with a thread root URI (this won't match anything, but tests SQL validity) - let thread_root_uri = "at://did:plc:root/app.bsky.feed.post/3m4fsspghex2n"; + let rkey_i64 = parakeet_db::models::tid_to_i64("3m4fsspghex2n")?; - let result = db::is_thread_muted(&tx, "did:plc:recipient", thread_root_uri).await; + let result = db::is_thread_muted(&tx, recipient_id as i32, root_id as i32, rkey_i64).await; assert!( result.is_ok(), @@ -47,24 +60,24 @@ async fn test_is_thread_muted() -> eyre::Result<()> { Ok(()) } -/// Test is_thread_muted with invalid URI format +/// Test is_thread_muted with non-existent thread #[tokio::test] async fn test_is_thread_muted_invalid_uri() -> eyre::Result<()> { let pool = test_pool(); let mut conn = pool.get().await.wrap_err("Failed to get connection")?; let tx = conn.transaction().await.wrap_err("Failed to start transaction")?; - // Test with invalid URI format (should return false, not error) - let result = db::is_thread_muted(&tx, "did:plc:recipient", "invalid-uri").await; + // Test with actor IDs and rkey that don't exist in thread_mutes (should return false) + let result = db::is_thread_muted(&tx, 1, 1, 1).await; assert!( result.is_ok(), - "is_thread_muted should handle invalid URI: {:?}", + "is_thread_muted should work: {:?}", result.err() ); let is_muted = result.unwrap(); - assert!(!is_muted, "Invalid URI should return false"); + assert!(!is_muted, "Non-existent thread should return false"); Ok(()) } diff --git a/consumer/tests/notification_test.rs b/consumer/tests/notification_test.rs index 5edeaed9..205ea406 100644 --- a/consumer/tests/notification_test.rs +++ b/consumer/tests/notification_test.rs @@ -31,18 +31,17 @@ async fn test_is_thread_muted_not_muted() -> eyre::Result<()> { .await .wrap_err("Failed to start transaction")?; - // Ensure actor exists - consumer::db::operations::feed::get_actor_id(&tx, "did:plc:user1") + // Ensure actors exist + let (user1_id, _, _) = consumer::db::operations::feed::get_actor_id(&tx, "did:plc:user1") .await .wrap_err("Failed to ensure actor")?; + let (other_id, _, _) = consumer::db::operations::feed::get_actor_id(&tx, "did:plc:other") + .await + .wrap_err("Failed to ensure other actor")?; // Check that thread is not muted (no rows in thread_mutes) (use valid TID format) - let result = db::is_thread_muted( - &tx, - "did:plc:user1", - "at://did:plc:other/app.bsky.feed.post/3l7mkz4lmk2ai", - ) - .await; + let rkey_i64 = parakeet_db::models::tid_to_i64("3l7mkz4lmk2ai")?; + let result = db::is_thread_muted(&tx, user1_id, other_id, rkey_i64).await; assert!( result.is_ok(), @@ -122,8 +121,7 @@ async fn test_is_thread_muted_muted() -> eyre::Result<()> { .wrap_err("Failed to insert thread mute")?; // Check that thread is muted - let thread_root_uri = "at://did:plc:rootpostauthor/app.bsky.feed.post/3l7mkz4lmk2aa"; - let result = db::is_thread_muted(&tx, "did:plc:user2", thread_root_uri).await; + let result = db::is_thread_muted(&tx, actor_id, rootpostauthor_id, rkey_i64).await; assert!( result.is_ok(), @@ -133,12 +131,13 @@ async fn test_is_thread_muted_muted() -> eyre::Result<()> { assert!(result.wrap_err("Operation failed")?, "Thread should be muted"); // Check that a different thread is not muted (use valid TID format) - let result2 = db::is_thread_muted( - &tx, - "did:plc:user2", - "at://did:plc:other/app.bsky.feed.post/3l7mkz4lmk2aj", - ) - .await; + // Ensure "other" actor exists + let (other_actor_id, _, _) = consumer::db::operations::feed::get_actor_id(&tx, "did:plc:other") + .await + .wrap_err("Failed to ensure other actor")?; + let other_rkey_i64 = parakeet_db::models::tid_to_i64("3l7mkz4lmk2aj")?; + + let result2 = db::is_thread_muted(&tx, actor_id, other_actor_id, other_rkey_i64).await; assert!(!result2.unwrap(), "Different thread should not be muted"); Ok(()) }