Преглед на файлове

Move team-data API access to separate module

This also adds retries (up to three total requests) if we timeout on connection.
It's possible we should be less restrictive and always retry, but the hope is
that timeouts are sufficient. This may not cover (for example) a "connection
reset by peer" error though, even if fundamentally that's also a timeout, just
of a different kind.
Mark Rousskov преди 5 години
родител
ревизия
12a2b3cb58
променени са 4 файла, в които са добавени 43 реда и са изтрити 25 реда
  1. 3 15
      src/github.rs
  2. 1 0
      src/lib.rs
  3. 37 0
      src/team_data.rs
  4. 2 10
      src/zulip.rs

+ 3 - 15
src/github.rs

@@ -56,11 +56,7 @@ impl User {
     }
 
     pub async fn is_team_member<'a>(&'a self, client: &'a GithubClient) -> anyhow::Result<bool> {
-        let url = format!("{}/teams.json", rust_team_data::v1::BASE_URL);
-        let permission: rust_team_data::v1::Teams = client
-            .json(client.raw().get(&url))
-            .await
-            .context("could not get team data")?;
+        let permission = crate::team_data::teams(client).await?;
         let map = permission.teams;
         let is_triager = map
             .get("wg-triage")
@@ -70,11 +66,7 @@ impl User {
 
     // Returns the ID of the given user, if the user is in the `all` team.
     pub async fn get_id<'a>(&'a self, client: &'a GithubClient) -> anyhow::Result<Option<usize>> {
-        let url = format!("{}/teams.json", rust_team_data::v1::BASE_URL);
-        let permission: rust_team_data::v1::Teams = client
-            .json(client.raw().get(&url))
-            .await
-            .context("could not get team data")?;
+        let permission = crate::team_data::teams(client).await?;
         let map = permission.teams;
         Ok(map["all"]
             .members
@@ -88,11 +80,7 @@ pub async fn get_team(
     client: &GithubClient,
     team: &str,
 ) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
-    let url = format!("{}/teams.json", rust_team_data::v1::BASE_URL);
-    let permission: rust_team_data::v1::Teams = client
-        .json(client.raw().get(&url))
-        .await
-        .context("could not get team data")?;
+    let permission = crate::team_data::teams(client).await?;
     let mut map = permission.teams;
     Ok(map.swap_remove(team))
 }

+ 1 - 0
src/lib.rs

@@ -13,6 +13,7 @@ pub mod interactions;
 pub mod notification_listing;
 pub mod payload;
 pub mod team;
+mod team_data;
 pub mod zulip;
 
 #[derive(Debug)]

+ 37 - 0
src/team_data.rs

@@ -0,0 +1,37 @@
+use crate::github::GithubClient;
+use anyhow::Context as _;
+use rust_team_data::v1::{Teams, ZulipMapping, BASE_URL};
+use serde::de::DeserializeOwned;
+
+async fn by_url<T: DeserializeOwned>(client: &GithubClient, path: &str) -> anyhow::Result<T> {
+    let url = format!("{}{}", BASE_URL, path);
+    for _ in 0i32..3 {
+        let map: Result<T, _> = client.json(client.raw().get(&url)).await;
+        match map {
+            Ok(v) => return Ok(v),
+            Err(e) => {
+                if e.downcast_ref::<reqwest::Error>()
+                    .map_or(false, |e| e.is_timeout())
+                {
+                    continue;
+                } else {
+                    return Err(e);
+                }
+            }
+        }
+    }
+
+    Err(anyhow::anyhow!("Failed to retrieve {} in 3 requests", url))
+}
+
+pub async fn zulip_map(client: &GithubClient) -> anyhow::Result<ZulipMapping> {
+    by_url(client, "/zulip-map.json")
+        .await
+        .context("team-api: zulip-map.json")
+}
+
+pub async fn teams(client: &GithubClient) -> anyhow::Result<Teams> {
+    by_url(client, "/teams.json")
+        .await
+        .context("team-api: teams.json")
+}

+ 2 - 10
src/zulip.rs

@@ -31,20 +31,12 @@ struct Response<'a> {
 }
 
 pub async fn to_github_id(client: &GithubClient, zulip_id: usize) -> anyhow::Result<Option<i64>> {
-    let url = format!("{}/zulip-map.json", rust_team_data::v1::BASE_URL);
-    let map: rust_team_data::v1::ZulipMapping = client
-        .json(client.raw().get(&url))
-        .await
-        .context("could not get team data")?;
+    let map = crate::team_data::zulip_map(client).await?;
     Ok(map.users.get(&zulip_id).map(|v| *v as i64))
 }
 
 pub async fn to_zulip_id(client: &GithubClient, github_id: i64) -> anyhow::Result<Option<usize>> {
-    let url = format!("{}/zulip-map.json", rust_team_data::v1::BASE_URL);
-    let map: rust_team_data::v1::ZulipMapping = client
-        .json(client.raw().get(&url))
-        .await
-        .context("could not get team data")?;
+    let map = crate::team_data::zulip_map(client).await?;
     Ok(map
         .users
         .iter()