Skip to content

Commit 3a8bb56

Browse files
committed
Allow load limits to be configured from environment
... and fix a typo
1 parent 944a98d commit 3a8bb56

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

src/middleware/balance_capacity.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub(super) struct BalanceCapacity {
1818
handler: Option<Box<dyn Handler>>,
1919
capacity: usize,
2020
in_flight_requests: AtomicUsize,
21+
log_at_percentage: usize,
22+
throttle_at_percentage: usize,
23+
dl_only_at_percentage: usize,
2124
}
2225

2326
impl BalanceCapacity {
@@ -26,6 +29,9 @@ impl BalanceCapacity {
2629
handler: None,
2730
capacity,
2831
in_flight_requests: AtomicUsize::new(0),
32+
log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 20),
33+
throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
34+
dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
2935
}
3036
}
3137
}
@@ -43,8 +49,8 @@ impl Handler for BalanceCapacity {
4349
let handler = self.handler.as_ref().unwrap();
4450
let load = 100 * count / self.capacity;
4551

46-
// Begin logging request count at 20% capacity
47-
if load >= 20 {
52+
// Begin logging request count so early stages of load increase can be located
53+
if load >= self.log_at_percentage {
4854
super::log_request::add_custom_metadata(request, "in_flight_requests", count);
4955
}
5056

@@ -53,23 +59,24 @@ impl Handler for BalanceCapacity {
5359
return handler.call(request);
5460
}
5561

56-
// Reject read-only requests after reaching 70% load. Bots are likely to send only safe
62+
// Reject read-only requests as load nears capacity. Bots are likely to send only safe
5763
// requests and this helps prioritize requests that users may be reluctant to retry.
58-
if load >= 70 && request.method().is_safe() {
59-
return over_capcity_response();
64+
if load >= self.throttle_at_percentage && request.method().is_safe() {
65+
return over_capacity_response(request);
6066
}
6167

62-
// At 80% load, all non-download requests are rejected
63-
if load >= 80 {
64-
return over_capcity_response();
68+
// As load reaches capacity, all non-download requests are rejected
69+
if load >= self.dl_only_at_percentage {
70+
return over_capacity_response(request);
6571
}
6672

6773
handler.call(request)
6874
}
6975
}
7076

71-
fn over_capcity_response() -> AfterResult {
77+
fn over_capacity_response(request: &mut dyn RequestExt) -> AfterResult {
7278
// TODO: Generate an alert so we can investigate
79+
super::log_request::add_custom_metadata(request, "cause", "over capacity");
7380
let body = "Service temporarily unavailable";
7481
Response::builder()
7582
.status(StatusCode::SERVICE_UNAVAILABLE)
@@ -78,6 +85,14 @@ fn over_capcity_response() -> AfterResult {
7885
.map_err(box_error)
7986
}
8087

88+
fn read_env_percentage(name: &str, default: usize) -> usize {
89+
if let Ok(value) = std::env::var(name) {
90+
value.parse().unwrap_or(default)
91+
} else {
92+
default
93+
}
94+
}
95+
8196
// FIXME(JTG): I've copied the following from my `conduit-hyper` crate. Once we transition from
8297
// `civet`, we could pass the in_flight_request count from `condut-hyper` via a request extension.
8398

0 commit comments

Comments
 (0)