pull_requests_assignment_update.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. use std::collections::HashMap;
  2. use crate::db::notifications::record_username;
  3. use crate::github::retrieve_pull_requests;
  4. use crate::jobs::Job;
  5. use anyhow::Context as _;
  6. use async_trait::async_trait;
  7. use tokio_postgres::Client as DbClient;
  8. pub struct PullRequestAssignmentUpdate;
  9. #[async_trait]
  10. impl Job for PullRequestAssignmentUpdate {
  11. fn name(&self) -> &'static str {
  12. "pull_request_assignment_update"
  13. }
  14. async fn run(&self, ctx: &super::Context, _metadata: &serde_json::Value) -> anyhow::Result<()> {
  15. let db = ctx.db.get().await;
  16. let gh = &ctx.github;
  17. tracing::trace!("starting pull_request_assignment_update");
  18. let rust_repo = gh.repository("rust-lang/rust").await?;
  19. let prs = retrieve_pull_requests(&rust_repo, &gh).await?;
  20. // delete all PR assignments before populating
  21. init_table(&db).await?;
  22. // aggregate by user first
  23. let aggregated = prs.into_iter().fold(HashMap::new(), |mut acc, (user, pr)| {
  24. let (_, prs) = acc
  25. .entry(user.id.unwrap())
  26. .or_insert_with(|| (user, Vec::new()));
  27. prs.push(pr);
  28. acc
  29. });
  30. // populate the table
  31. for (_user_id, (assignee, prs)) in &aggregated {
  32. let assignee_id = assignee.id.expect("checked");
  33. let _ = record_username(&db, assignee_id, &assignee.login).await;
  34. create_team_member_workqueue(&db, assignee_id, &prs).await?;
  35. }
  36. Ok(())
  37. }
  38. }
  39. /// Truncate the review prefs table
  40. async fn init_table(db: &DbClient) -> anyhow::Result<u64> {
  41. let res = db
  42. .execute("UPDATE review_prefs SET assigned_prs='{}';", &[])
  43. .await?;
  44. Ok(res)
  45. }
  46. /// Create a team member work queue
  47. async fn create_team_member_workqueue(
  48. db: &DbClient,
  49. user_id: u64,
  50. prs: &Vec<i32>,
  51. ) -> anyhow::Result<u64, anyhow::Error> {
  52. let q = "
  53. INSERT INTO review_prefs (user_id, assigned_prs) VALUES ($1, $2)
  54. ON CONFLICT (user_id)
  55. DO UPDATE SET assigned_prs = $2
  56. WHERE review_prefs.user_id=$1";
  57. db.execute(q, &[&(user_id as i64), prs])
  58. .await
  59. .context("Insert DB error")
  60. }