#[async_trait::async_trait]
pub trait ProfileFetcher: Send + Sync {
async fn get_profile_metrics(&self) -> Result<ProfileMetrics, AnalyticsError>;
}
#[async_trait::async_trait]
pub trait EngagementFetcher: Send + Sync {
async fn get_tweet_metrics(&self, tweet_id: &str) -> Result<TweetMetrics, AnalyticsError>;
}
#[async_trait::async_trait]
pub trait AnalyticsStorage: Send + Sync {
async fn store_follower_snapshot(
&self,
followers: i64,
following: i64,
tweets: i64,
) -> Result<(), AnalyticsError>;
async fn get_yesterday_followers(&self) -> Result<Option<i64>, AnalyticsError>;
async fn get_replies_needing_measurement(&self) -> Result<Vec<String>, AnalyticsError>;
async fn get_tweets_needing_measurement(&self) -> Result<Vec<String>, AnalyticsError>;
async fn store_reply_performance(
&self,
reply_id: &str,
likes: i64,
replies: i64,
impressions: i64,
score: f64,
) -> Result<(), AnalyticsError>;
async fn store_tweet_performance(
&self,
tweet_id: &str,
likes: i64,
retweets: i64,
replies: i64,
impressions: i64,
score: f64,
) -> Result<(), AnalyticsError>;
async fn update_content_score(
&self,
topic: &str,
format: &str,
score: f64,
) -> Result<(), AnalyticsError>;
async fn log_action(
&self,
action_type: &str,
status: &str,
message: &str,
) -> Result<(), AnalyticsError>;
async fn run_forge_sync_if_enabled(&self) -> Result<Option<ForgeSyncResult>, AnalyticsError> {
Ok(None)
}
async fn run_aggregations(&self) -> Result<(), AnalyticsError> {
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct ProfileMetrics {
pub follower_count: i64,
pub following_count: i64,
pub tweet_count: i64,
}
#[derive(Debug, Clone)]
pub struct TweetMetrics {
pub likes: i64,
pub retweets: i64,
pub replies: i64,
pub impressions: i64,
}
#[derive(Debug)]
pub enum AnalyticsError {
ApiError(String),
StorageError(String),
Other(String),
}
impl std::fmt::Display for AnalyticsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ApiError(msg) => write!(f, "API error: {msg}"),
Self::StorageError(msg) => write!(f, "storage error: {msg}"),
Self::Other(msg) => write!(f, "{msg}"),
}
}
}
impl std::error::Error for AnalyticsError {}
#[derive(Debug, Default, Clone)]
pub struct ForgeSyncResult {
pub tweets_synced: usize,
pub threads_synced: usize,
}