use async_trait::async_trait; use tokio::sync::mpsc::{self, Receiver, Sender}; mod gql; mod list_repos; mod print; mod repo_participants; mod util; #[async_trait] pub trait Producer { /// What columns names are produced. fn column_names(&self) -> Vec; /// Executes the producer and sends columns off to the given "tx" endpoint /// of a channel. async fn producer_task(self, tx: Sender>) -> anyhow::Result<()>; } #[async_trait] pub trait Consumer { async fn consume( self, rx: &mut Receiver>, column_names: Vec, ) -> anyhow::Result<()>; } pub use gql::Graphql; pub use list_repos::ListReposForOrg; pub use print::Print; pub use repo_participants::RepoParticipants; pub use util::all_repos; /// Spawns a task running a producer and returns the column names /// that it will produce along with /// a receiver for the actual columns. pub fn run_producer( producer: impl Producer + Send + 'static, ) -> (Vec, Receiver>) { let (tx, rx) = mpsc::channel::>(400); let column_names = producer.column_names(); tokio::spawn(async move { if let Err(e) = producer.producer_task(tx).await { println!("Encountered an error while collecting data: {}", e); }; }); (column_names, rx) }