Skip to content

Commit c243033

Browse files
committed
simplify env parsing
1 parent 603e8e5 commit c243033

File tree

2 files changed

+29
-35
lines changed

2 files changed

+29
-35
lines changed

src/main.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ use std::{
2525
convert::Infallible,
2626
env,
2727
error::Error,
28-
net::{IpAddr, SocketAddr},
28+
net::{Ipv4Addr, SocketAddr},
2929
pin::pin,
3030
str::FromStr,
3131
sync::Arc,
32+
time::Duration,
3233
};
3334
use tokio::{net::TcpListener, task::JoinSet};
34-
use tracing::{debug, error, info, trace, warn};
35+
use tracing::{debug, error, info, trace};
3536
use twilight_http_ratelimiting::{
3637
InMemoryRatelimiter, Method, Path, RatelimitHeaders, Ratelimiter,
3738
};
@@ -50,11 +51,7 @@ use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
5051
#[cfg(feature = "metrics")]
5152
use metrics_util::MetricKindMask;
5253
#[cfg(feature = "metrics")]
53-
use std::{
54-
borrow::Cow,
55-
sync::LazyLock,
56-
time::{Duration, Instant},
57-
};
54+
use std::{borrow::Cow, sync::LazyLock, time::Instant};
5855

5956
#[cfg(feature = "metrics")]
6057
static METRIC_KEY: LazyLock<Cow<str>> = LazyLock::new(|| {
@@ -65,9 +62,8 @@ static METRIC_KEY: LazyLock<Cow<str>> = LazyLock::new(|| {
6562
async fn main() -> Result<(), Box<dyn Error>> {
6663
tracing_subscriber::fmt::init();
6764

68-
let host_raw = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".into());
69-
let host = IpAddr::from_str(&host_raw)?;
70-
let port = env::var("PORT").unwrap_or_else(|_| "80".into()).parse()?;
65+
let host = parse_env("HOST")?.unwrap_or(Ipv4Addr::UNSPECIFIED);
66+
let port = parse_env("PORT")?.unwrap_or(80);
7167

7268
let https_connector = {
7369
let mut http_connector = TokioHickoryResolver::default().into_http_connector();
@@ -78,15 +74,19 @@ async fn main() -> Result<(), Box<dyn Error>> {
7874
.https_only()
7975
.enable_http1();
8076

81-
if env::var("DISABLE_HTTP2").is_ok() {
77+
if env::var_os("DISABLE_HTTP2").is_some() {
8278
builder.wrap_connector(http_connector)
8379
} else {
8480
builder.enable_http2().wrap_connector(http_connector)
8581
}
8682
};
8783

8884
let client: Client<_, Incoming> = Client::builder(TokioExecutor::new()).build(https_connector);
89-
let ratelimiter_map = Arc::new(RatelimiterMap::new(env::var("DISCORD_TOKEN")?));
85+
let ratelimiter_map = Arc::new(RatelimiterMap::new(
86+
env::var("DISCORD_TOKEN")?,
87+
Duration::from_secs(parse_env("CLIENT_DECAY_TIMEOUT")?.unwrap_or(3600)),
88+
parse_env("CLIENT_CACHE_MAX_SIZE")?,
89+
));
9090

9191
let address = SocketAddr::from((host, port));
9292

@@ -95,7 +95,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
9595

9696
#[cfg(feature = "metrics")]
9797
{
98-
let timeout = parse_env("METRIC_TIMEOUT").unwrap_or(300);
98+
let timeout = parse_env("METRIC_TIMEOUT")?.unwrap_or(300);
9999
let recorder = PrometheusBuilder::new()
100100
.idle_timeout(
101101
MetricKindMask::COUNTER | MetricKindMask::HISTOGRAM,
@@ -452,19 +452,17 @@ fn handle_metrics(handle: Arc<PrometheusHandle>) -> Response<BoxBody<Bytes, hype
452452
.unwrap()
453453
}
454454

455-
pub fn parse_env<T: FromStr>(key: &str) -> Option<T> {
456-
env::var_os(key).and_then(|value| match value.into_string() {
457-
Ok(s) => {
458-
if let Ok(t) = s.parse() {
459-
Some(t)
460-
} else {
461-
warn!("Unable to parse {}, proceeding with defaults", key);
462-
None
463-
}
464-
}
465-
Err(s) => {
466-
warn!("{} is not UTF-8: {:?}", key, s);
467-
None
468-
}
469-
})
455+
fn parse_env<T>(key: &str) -> Result<Option<T>, Box<dyn Error>>
456+
where
457+
T: FromStr,
458+
<T as FromStr>::Err: Error + 'static,
459+
{
460+
match env::var(key) {
461+
Ok(s) => match s.parse() {
462+
Ok(v) => Ok(Some(v)),
463+
Err(e) => Err(e.into()),
464+
},
465+
Err(env::VarError::NotPresent) => Ok(None),
466+
Err(e @ env::VarError::NotUnicode(_)) => Err(e.into()),
467+
}
470468
}

src/ratelimiter_map.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ use crate::expiring_lru::{Builder, ExpiringLru};
22
use tokio::time::Duration;
33
use twilight_http_ratelimiting::InMemoryRatelimiter;
44

5-
use crate::parse_env;
6-
75
pub struct RatelimiterMap {
86
default: InMemoryRatelimiter,
97
default_token: String,
108
inner: ExpiringLru<String, InMemoryRatelimiter>,
119
}
1210

1311
impl RatelimiterMap {
14-
pub fn new(mut default_token: String) -> Self {
12+
pub fn new(mut default_token: String, timeout: Duration, max_size: Option<usize>) -> Self {
1513
let is_bot = default_token.starts_with("Bot ");
1614
let is_bearer = default_token.starts_with("Bearer ");
1715

@@ -21,11 +19,9 @@ impl RatelimiterMap {
2119
default_token.insert_str(0, "Bot ");
2220
}
2321

24-
let expiration = Duration::from_secs(parse_env("CLIENT_DECAY_TIMEOUT").unwrap_or(3600));
25-
26-
let mut builder = Builder::new().expiration(expiration);
22+
let mut builder = Builder::new().expiration(timeout);
2723

28-
if let Some(max_size) = parse_env("CLIENT_CACHE_MAX_SIZE") {
24+
if let Some(max_size) = max_size {
2925
builder = builder.max_size(max_size);
3026
}
3127

0 commit comments

Comments
 (0)