diff --git a/examples/test-svc-acct/src/main.rs b/examples/test-svc-acct/src/main.rs index cf6b066..f9a9ee0 100644 --- a/examples/test-svc-acct/src/main.rs +++ b/examples/test-svc-acct/src/main.rs @@ -25,15 +25,12 @@ fn main() { println!("token is: {:?}", tok); Ok(()) }); - let mut sa2 = sa.clone(); - let all = fut - .then(move |_| { - sa2.token(["https://www.googleapis.com/auth/pubsub"].iter()) - .and_then(|tok| { - println!("cached token is {:?} and should be identical", tok); - Ok(()) - }) - }) - .then(|_| Ok(())); + let fut2 = sa + .token(["https://www.googleapis.com/auth/pubsub"].iter()) + .and_then(|tok| { + println!("cached token is {:?} and should be identical", tok); + Ok(()) + }); + let all = fut.join(fut2).then(|_| Ok(())); tokio::run(all) } diff --git a/src/service_account.rs b/src/service_account.rs index cabf075..435ff9a 100644 --- a/src/service_account.rs +++ b/src/service_account.rs @@ -333,43 +333,56 @@ where T: AsRef + Ord + 'b, I: Iterator, { - let (hash, scps) = hash_scopes(scopes); + let (hash, scps0) = hash_scopes(scopes); + let cache = self.cache.clone(); + let scps = scps0.clone(); - match self - .cache - .lock() - .unwrap() - .get(hash, &scps.iter().map(|s| s.as_str()).collect()) - { - Ok(Some(token)) => { - if !token.expired() { - return Box::new(future::ok(token)); + let cache_lookup = futures::lazy(move || { + match cache + .lock() + .unwrap() + .get(hash, &scps.iter().map(|s| s.as_str()).collect()) + { + Ok(Some(token)) => { + if !token.expired() { + return Ok(token); + } + return Err(Box::new(StringError::new("expired token in cache", None)) + as Box); + } + Err(e) => return Err(Box::new(e) as Box), + Ok(None) => { + return Err(Box::new(StringError::new("no token in cache", None)) + as Box) } } - Err(e) => return Box::new(future::err(Box::new(e) as Box)), - _ => {} - } + }); let cache = self.cache.clone(); - Box::new( - Self::request_token( - self.client.clone(), - self.sub.clone(), - self.key.clone(), - scps.iter().map(|s| s.to_string()).collect(), - ) - .then(move |r| match r { - Ok(token) => { - let _ = cache.lock().unwrap().set( - hash, - &scps.iter().map(|s| s.as_str()).collect(), - Some(token.clone()), - ); - Box::new(future::ok(token)) - } - Err(e) => Box::new(future::err(e)), - }), + let req_token = Self::request_token( + self.client.clone(), + self.sub.clone(), + self.key.clone(), + scps0.iter().map(|s| s.to_string()).collect(), ) + .then(move |r| match r { + Ok(token) => { + let _ = cache.lock().unwrap().set( + hash, + &scps0.iter().map(|s| s.as_str()).collect(), + Some(token.clone()), + ); + Box::new(future::ok(token)) + } + Err(e) => Box::new(future::err(e)), + }); + + Box::new(cache_lookup.then(|r| match r { + Ok(t) => Box::new(Ok(t).into_future()) + as Box> + Send>, + Err(_) => Box::new(req_token) + as Box> + Send>, + })) } /// Returns an empty ApplicationSecret as tokens for service accounts don't need to be