ソースを参照

Process docs-update Zulip trigger in the background.

Eric Huss 1 年間 前
コミット
14e9842552
1 ファイル変更57 行追加14 行削除
  1. 57 14
      src/zulip.rs

+ 57 - 14
src/zulip.rs

@@ -21,21 +21,50 @@ pub struct Request {
     token: String,
 }
 
-#[derive(Debug, serde::Deserialize)]
+#[derive(Clone, Debug, serde::Deserialize)]
 struct Message {
     sender_id: u64,
+    /// A unique ID for the set of users receiving the message (either a
+    /// stream or group of users). Useful primarily for hashing.
     #[allow(unused)]
     recipient_id: u64,
     sender_short_name: Option<String>,
     sender_full_name: String,
+    sender_email: String,
+    /// The ID of the stream.
+    ///
+    /// `None` if it is a private message.
     stream_id: Option<u64>,
-    // The topic of the incoming message. Not the stream name.
+    /// The topic of the incoming message. Not the stream name.
+    ///
+    /// Not currently set for private messages (though Zulip may change this in
+    /// the future if it adds topics to private messages).
     subject: Option<String>,
+    /// The type of the message: stream or private.
     #[allow(unused)]
     #[serde(rename = "type")]
     type_: String,
 }
 
+impl Message {
+    /// Creates a `Recipient` that will be addressed to the sender of this message.
+    fn sender_to_recipient(&self) -> Recipient<'_> {
+        match self.stream_id {
+            Some(id) => Recipient::Stream {
+                id,
+                topic: self
+                    .subject
+                    .as_ref()
+                    .expect("stream messages should have a topic"),
+            },
+            None => Recipient::Private {
+                id: self.sender_id,
+                email: &self.sender_email,
+            },
+        }
+    }
+}
+
 #[derive(serde::Serialize, serde::Deserialize)]
 struct Response {
     content: String,
@@ -158,7 +187,7 @@ fn handle_command<'a>(
                                 .await
                                 .map_err(|e| format_err!("Failed to await at this time: {e:?}"))
                             }
-                            Some("docs-update") => return trigger_docs_update().await,
+                            Some("docs-update") => return trigger_docs_update(message_data),
                             _ => {}
                         }
                     }
@@ -710,16 +739,30 @@ async fn post_waiter(
     Ok(None)
 }
 
-async fn trigger_docs_update() -> anyhow::Result<Option<String>> {
-    match docs_update().await {
-        Ok(None) => Ok(Some("No updates found.".to_string())),
-        Ok(Some(pr)) => Ok(Some(format!("Created docs update PR <{}>", pr.html_url))),
-        Err(e) => {
-            // Don't send errors to Zulip since they may contain sensitive data.
-            log::error!("Docs update via Zulip failed: {e:?}");
-            Err(format_err!(
-                "Docs update failed, please check the logs for more details."
-            ))
+fn trigger_docs_update(message: &Message) -> anyhow::Result<Option<String>> {
+    let message = message.clone();
+    // The default Zulip timeout of 10 seconds can be too short, so process in
+    // the background.
+    tokio::task::spawn(async move {
+        let response = match docs_update().await {
+            Ok(None) => "No updates found.".to_string(),
+            Ok(Some(pr)) => format!("Created docs update PR <{}>", pr.html_url),
+            Err(e) => {
+                // Don't send errors to Zulip since they may contain sensitive data.
+                log::error!("Docs update via Zulip failed: {e:?}");
+                "Docs update failed, please check the logs for more details.".to_string()
+            }
+        };
+        let recipient = message.sender_to_recipient();
+        let message = MessageApiRequest {
+            recipient,
+            content: &response,
+        };
+        if let Err(e) = message.send(&reqwest::Client::new()).await {
+            log::error!("failed to send Zulip response: {e:?}\nresponse was:\n{response}");
         }
-    }
+    });
+    Ok(Some(
+        "Docs update in progress, I'll let you know when I'm finished.".to_string(),
+    ))
 }