From 49f310e8a18159ec2feef5d0fabdf6fd9731a4c0 Mon Sep 17 00:00:00 2001 From: Mark Drobnak Date: Mon, 13 Jul 2020 09:39:38 -0400 Subject: [PATCH] Make FCM request timeout a config option --- autoendpoint/src/server/routers/fcm/client.rs | 18 ++++++++++++------ autoendpoint/src/server/routers/fcm/router.rs | 2 +- .../src/server/routers/fcm/settings.rs | 4 ++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/autoendpoint/src/server/routers/fcm/client.rs b/autoendpoint/src/server/routers/fcm/client.rs index f90010782..569006c7e 100644 --- a/autoendpoint/src/server/routers/fcm/client.rs +++ b/autoendpoint/src/server/routers/fcm/client.rs @@ -1,5 +1,6 @@ use crate::server::routers::fcm::error::FcmError; use crate::server::routers::fcm::settings::FcmCredential; +use crate::server::FcmSettings; use reqwest::StatusCode; use serde::Deserialize; use std::collections::HashMap; @@ -8,14 +9,13 @@ use url::Url; use yup_oauth2::authenticator::DefaultAuthenticator; use yup_oauth2::ServiceAccountAuthenticator; -/// The timeout for FCM requests, in seconds -const TIMEOUT: Duration = Duration::from_secs(3); const OAUTH_SCOPES: &[&str] = &["https://www.googleapis.com/auth/firebase.messaging"]; /// Holds application-specific Firebase data and authentication. This client /// handles sending notifications to Firebase. pub struct FcmClient { endpoint: Url, + timeout: Duration, auth: DefaultAuthenticator, http: reqwest::Client, } @@ -23,7 +23,7 @@ pub struct FcmClient { impl FcmClient { /// Create an `FcmClient` using the provided credential pub async fn new( - fcm_url: Url, + settings: &FcmSettings, credential: FcmCredential, http: reqwest::Client, ) -> std::io::Result { @@ -33,12 +33,14 @@ impl FcmClient { .await?; Ok(FcmClient { - endpoint: fcm_url + endpoint: settings + .fcm_url .join(&format!( "v1/projects/{}/messages:send", credential.project_id )) .expect("Project ID is not URL-safe"), + timeout: Duration::from_secs(settings.timeout as u64), auth, http, }) @@ -70,7 +72,7 @@ impl FcmClient { .header("Authorization", format!("Bearer {}", access_token.as_str())) .header("Content-Type", "application/json; UTF-8") .body(message.to_string()) - .timeout(TIMEOUT) + .timeout(self.timeout) .send() .await .map_err(|e| { @@ -119,6 +121,7 @@ pub mod tests { use crate::server::routers::fcm::client::FcmClient; use crate::server::routers::fcm::error::FcmError; use crate::server::routers::fcm::settings::FcmCredential; + use crate::server::FcmSettings; use std::collections::HashMap; use std::io::Write; use std::path::PathBuf; @@ -175,7 +178,10 @@ pub mod tests { /// Make a FcmClient from the service auth data async fn make_client(auth_file: PathBuf) -> FcmClient { FcmClient::new( - Url::parse(&mockito::server_url()).unwrap(), + &FcmSettings { + fcm_url: Url::parse(&mockito::server_url()).unwrap(), + ..Default::default() + }, FcmCredential { auth_file, project_id: PROJECT_ID.to_string(), diff --git a/autoendpoint/src/server/routers/fcm/router.rs b/autoendpoint/src/server/routers/fcm/router.rs index 54c768a9e..525fec1df 100644 --- a/autoendpoint/src/server/routers/fcm/router.rs +++ b/autoendpoint/src/server/routers/fcm/router.rs @@ -56,7 +56,7 @@ impl FcmRouter { for (profile, credential) in credentials { clients.insert( profile, - FcmClient::new(settings.fcm_url.clone(), credential, http.clone()).await?, + FcmClient::new(&settings, credential, http.clone()).await?, ); } diff --git a/autoendpoint/src/server/routers/fcm/settings.rs b/autoendpoint/src/server/routers/fcm/settings.rs index c1057baa1..60b3b31b2 100644 --- a/autoendpoint/src/server/routers/fcm/settings.rs +++ b/autoendpoint/src/server/routers/fcm/settings.rs @@ -7,6 +7,7 @@ use url::Url; #[serde(default)] #[serde(deny_unknown_fields)] pub struct FcmSettings { + /// The minimum TTL to use for FCM notifications pub ttl: usize, /// A JSON dict of `FcmCredential`s. This must be a `String` because /// environment variables cannot encode a `HashMap` @@ -15,6 +16,8 @@ pub struct FcmSettings { pub max_data: usize, /// The base URL to use for FCM requests pub fcm_url: Url, + /// The number of seconds to wait for FCM requests to complete + pub timeout: usize, } /// Credential information for each application @@ -31,6 +34,7 @@ impl Default for FcmSettings { credentials: "{}".to_string(), max_data: 4096, fcm_url: Url::parse("https://fcm.googleapis.com").unwrap(), + timeout: 3, } } }