-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Add helper functions to ApiKeyFactory struct #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5d2dcdb
d3f95e3
2252249
f6c7a65
689429e
0e06eb2
e94c813
6bdd328
8987283
8d99785
aa17d9a
74f8ab1
98eac71
07c343d
1822e69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
use std::fmt::Debug; | ||
use std::sync::Arc; | ||
use std::{future::Future, pin::Pin}; | ||
use tokio::sync::OnceCell; | ||
|
||
pub type ApiKeyResolverFn = | ||
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = String> + Send>> + Send + Sync>; | ||
|
||
#[derive(Clone)] | ||
pub enum ApiKeyFactory { | ||
Static(String), | ||
Dynamic { | ||
resolver_fn: ApiKeyResolverFn, | ||
api_key: Arc<OnceCell<String>>, | ||
}, | ||
} | ||
|
||
impl ApiKeyFactory { | ||
/// Create a new `ApiKeyFactory` with a static API key. | ||
pub fn new(api_key: &str) -> Self { | ||
Self::Static(api_key.to_string()) | ||
} | ||
|
||
/// Create a new `ApiKeyFactory` with a dynamic API key resolver function. | ||
pub fn new_from_resolver(resolver_fn: ApiKeyResolverFn) -> Self { | ||
Self::Dynamic { | ||
resolver_fn, | ||
api_key: Arc::new(OnceCell::new()), | ||
} | ||
} | ||
|
||
pub async fn get_api_key(&self) -> &str { | ||
match self { | ||
Self::Static(api_key) => api_key, | ||
Self::Dynamic { | ||
resolver_fn, | ||
api_key, | ||
} => { | ||
api_key | ||
.get_or_init(|| async { (resolver_fn)().await }) | ||
.await | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl Debug for ApiKeyFactory { | ||
duncanista marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "ApiKeyFactory") | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
pub mod tests { | ||
use super::*; | ||
|
||
#[tokio::test] | ||
async fn test_new() { | ||
let api_key_factory = ApiKeyFactory::new("mock-api-key"); | ||
assert_eq!(api_key_factory.get_api_key().await, "mock-api-key"); | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_new_from_resolver() { | ||
let api_key_factory = Arc::new(ApiKeyFactory::new_from_resolver(Arc::new(move || { | ||
let api_key = "mock-api-key".to_string(); | ||
Box::pin(async move { api_key }) | ||
}))); | ||
assert_eq!(api_key_factory.get_api_key().await, "mock-api-key"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,21 +2,17 @@ | |||||
// SPDX-License-Identifier: Apache-2.0 | ||||||
|
||||||
use crate::aggregator::Aggregator; | ||||||
use crate::api_key::ApiKeyFactory; | ||||||
use crate::datadog::{DdApi, MetricsIntakeUrlPrefix, RetryStrategy}; | ||||||
use reqwest::{Response, StatusCode}; | ||||||
use std::future::Future; | ||||||
use std::pin::Pin; | ||||||
use std::sync::{Arc, Mutex}; | ||||||
use std::time::Duration; | ||||||
use tracing::{debug, error}; | ||||||
|
||||||
pub type ApiKeyFactory = | ||||||
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = String> + Send>> + Send + Sync>; | ||||||
|
||||||
#[derive(Clone)] | ||||||
pub struct Flusher { | ||||||
// Accept a future so the API key resolution is deferred until the flush happens | ||||||
api_key_factory: ApiKeyFactory, | ||||||
// Allow accepting a future so the API key resolution is deferred until the flush happens | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Update this comment to reflect that
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
api_key_factory: Arc<ApiKeyFactory>, | ||||||
metrics_intake_url_prefix: MetricsIntakeUrlPrefix, | ||||||
https_proxy: Option<String>, | ||||||
timeout: Duration, | ||||||
|
@@ -26,7 +22,7 @@ pub struct Flusher { | |||||
} | ||||||
|
||||||
pub struct FlusherConfig { | ||||||
pub api_key_factory: ApiKeyFactory, | ||||||
pub api_key_factory: Arc<ApiKeyFactory>, | ||||||
pub aggregator: Arc<Mutex<Aggregator>>, | ||||||
pub metrics_intake_url_prefix: MetricsIntakeUrlPrefix, | ||||||
pub https_proxy: Option<String>, | ||||||
|
@@ -38,7 +34,7 @@ pub struct FlusherConfig { | |||||
impl Flusher { | ||||||
pub fn new(config: FlusherConfig) -> Self { | ||||||
Flusher { | ||||||
api_key_factory: config.api_key_factory, | ||||||
api_key_factory: Arc::clone(&config.api_key_factory), | ||||||
metrics_intake_url_prefix: config.metrics_intake_url_prefix, | ||||||
https_proxy: config.https_proxy, | ||||||
timeout: config.timeout, | ||||||
|
@@ -50,9 +46,9 @@ impl Flusher { | |||||
|
||||||
async fn get_dd_api(&mut self) -> &DdApi { | ||||||
if self.dd_api.is_none() { | ||||||
let api_key = (self.api_key_factory)().await; | ||||||
let api_key = self.api_key_factory.get_api_key().await; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Since Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
self.dd_api = Some(DdApi::new( | ||||||
api_key, | ||||||
api_key.to_string(), | ||||||
self.metrics_intake_url_prefix.clone(), | ||||||
self.https_proxy.clone(), | ||||||
self.timeout, | ||||||
|
@@ -63,7 +59,7 @@ impl Flusher { | |||||
#[allow(clippy::expect_used)] | ||||||
self.dd_api | ||||||
.as_ref() | ||||||
.expect("dd_api should be initialized by this point") | ||||||
.expect("dd_api should have been initialized") | ||||||
} | ||||||
|
||||||
/// Flush metrics from the aggregator | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe some docs on what is considered a resolver