use std::{sync::Arc, time::Duration}; use clap::Parser; use moments_core::{EventSource, run_poller}; use moments_data::{ PgStore, github::{GithubConfig, GithubSource}, github_search::{GithubSearchConfig, GithubSearchSource}, }; use reqwest::Client; use tracing::info; #[derive(Parser, Debug)] #[command(version, about = "moments ingestion worker")] struct Args { #[arg(long, env = "DATABASE_URL")] database_url: String, #[arg(long, env = "GITHUB_USER", default_value = "grenade")] github_user: String, /// Optional GitHub token. Higher rate limit and access to private events. #[arg(long, env = "GITHUB_TOKEN")] github_token: Option, /// Seconds between Events-API polls (live feed, last 90 days). #[arg(long, env = "POLL_INTERVAL_SECS", default_value = "600")] interval_secs: u64, /// Seconds between Search-API polls (historical issue/PR backfill). /// Defaults to 24h — this is a backfill, not a live feed. #[arg(long, env = "SEARCH_POLL_INTERVAL_SECS", default_value = "86400")] search_interval_secs: u64, } #[tokio::main] async fn main() -> anyhow::Result<()> { init_tracing(); let args = Args::parse(); let store = Arc::new(PgStore::connect(&args.database_url).await?); store.migrate().await?; let http = Client::builder() .timeout(Duration::from_secs(30)) .build()?; let github = Arc::new(GithubSource::new( http.clone(), store.clone(), store.clone(), GithubConfig { user: args.github_user.clone(), token: args.github_token.clone(), per_page: 100, }, )) as Arc; let github_search = Arc::new(GithubSearchSource::new( http.clone(), store.clone(), store.clone(), GithubSearchConfig { user: args.github_user.clone(), token: args.github_token.clone(), ..Default::default() }, )) as Arc; info!( github_user = args.github_user, interval_secs = args.interval_secs, search_interval_secs = args.search_interval_secs, "worker started" ); let interval = Duration::from_secs(args.interval_secs); let search_interval = Duration::from_secs(args.search_interval_secs); let github_task = tokio::spawn(async move { run_poller(github, interval).await }); let github_search_task = tokio::spawn(async move { run_poller(github_search, search_interval).await }); tokio::signal::ctrl_c().await?; info!("shutdown signal received"); github_task.abort(); github_search_task.abort(); Ok(()) } fn init_tracing() { use tracing_subscriber::{EnvFilter, fmt}; let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); let json = std::env::var("JOURNAL_STREAM").is_ok(); if json { fmt().with_env_filter(filter).json().init(); } else { fmt().with_env_filter(filter).init(); } }