Skip to content

Commit 07da44c

Browse files
committed
chore(guard): configure local timeout knobs
1 parent 7256a9c commit 07da44c

6 files changed

Lines changed: 216 additions & 37 deletions

File tree

engine/artifacts/config-schema.json

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/packages/config/src/config/guard.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ pub struct Guard {
1414
/// Enables the internal websocket health route for debug and latency testing. This is intended
1515
/// for websocket ping/pong verification and should remain disabled in normal deployments.
1616
pub enable_websocket_health_route: Option<bool>,
17+
/// TTL for cached route lookups in milliseconds.
18+
pub route_cache_ttl_ms: Option<u64>,
19+
/// Timeout for route resolution in milliseconds.
20+
pub route_timeout_ms: Option<u64>,
21+
/// Timeout for waiting for an actor to become ready in milliseconds.
22+
pub actor_ready_timeout_ms: Option<u64>,
23+
/// Timeout sent with actor force-wake requests in milliseconds.
24+
pub actor_force_wake_pending_timeout_ms: Option<i64>,
1725
/// Enable & configure HTTPS
1826
pub https: Option<Https>,
1927
/// Max HTTP request body size in bytes (first line of defense).
@@ -37,6 +45,23 @@ impl Guard {
3745
self.enable_websocket_health_route.unwrap_or(false)
3846
}
3947

48+
pub fn route_cache_ttl(&self) -> std::time::Duration {
49+
std::time::Duration::from_millis(self.route_cache_ttl_ms.unwrap_or(60 * 10 * 1000))
50+
}
51+
52+
pub fn route_timeout(&self) -> std::time::Duration {
53+
std::time::Duration::from_millis(self.route_timeout_ms.unwrap_or(15_000))
54+
}
55+
56+
pub fn actor_ready_timeout(&self) -> std::time::Duration {
57+
std::time::Duration::from_millis(self.actor_ready_timeout_ms.unwrap_or(10_000))
58+
}
59+
60+
pub fn actor_force_wake_pending_timeout(&self) -> i64 {
61+
self.actor_force_wake_pending_timeout_ms
62+
.unwrap_or(60 * 1000)
63+
}
64+
4065
pub fn http_max_request_body_size(&self) -> usize {
4166
self.http_max_request_body_size.unwrap_or(20 * 1024 * 1024) // 20 MiB
4267
}

engine/packages/guard-core/src/proxy_service.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::RouteTarget;
3131
use crate::request_context::RequestContext;
3232
use crate::response_body::ResponseBody;
3333
use crate::route::{
34-
CacheKeyFn, DEFAULT_ROUTE_TIMEOUT, ResolveRouteOutput, RouteCache, RoutingFn, RoutingOutput,
34+
CacheKeyFn, ResolveRouteOutput, RouteCache, RoutingFn, RoutingOutput,
3535
};
3636
use crate::utils::{InFlightCounter, RateLimiter};
3737
use crate::{
@@ -89,13 +89,14 @@ impl ProxyState {
8989
let client = Client::builder(TokioExecutor::new())
9090
.pool_idle_timeout(Duration::from_secs(30))
9191
.build(https_connector);
92+
let route_cache_ttl = config.guard().route_cache_ttl();
9293

9394
Self {
9495
config,
9596
routing_fn,
9697
cache_key_fn,
9798
client,
98-
route_cache: RouteCache::new(),
99+
route_cache: RouteCache::new(route_cache_ttl),
99100
rate_limiters: Cache::builder()
100101
.max_capacity(10_000)
101102
.time_to_live(PROXY_STATE_CACHE_TTL)
@@ -134,21 +135,22 @@ impl ProxyState {
134135
let res = if let Some(res) = cache_res {
135136
res
136137
} else {
137-
// Not in cache, call routing function with a default timeout
138-
// Default 15 seconds, routing functions should have their own internal timeouts that are shorter
138+
// Not in cache, call routing function with a configured timeout.
139+
// Routing functions should have their own internal timeouts that are shorter.
140+
let route_timeout = self.config.guard().route_timeout();
139141
tracing::debug!(
140142
hostname = %req_ctx.hostname,
141143
path = %req_ctx.path,
142144
cache_hit = false,
143-
timeout_seconds = DEFAULT_ROUTE_TIMEOUT.as_secs(),
145+
timeout_seconds = route_timeout.as_secs(),
144146
"Cache miss, calling routing function"
145147
);
146148

147-
let routing_res = timeout(DEFAULT_ROUTE_TIMEOUT, (self.routing_fn)(req_ctx))
149+
let routing_res = timeout(route_timeout, (self.routing_fn)(req_ctx))
148150
.await
149151
.map_err(|_| {
150152
errors::RequestTimeout {
151-
timeout_seconds: DEFAULT_ROUTE_TIMEOUT.as_secs(),
153+
timeout_seconds: route_timeout.as_secs(),
152154
}
153155
.build()
154156
})??;

engine/packages/guard-core/src/route.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ use crate::custom_serve::CustomServeTrait;
77
use crate::metrics;
88
use crate::request_context::RequestContext;
99

10-
const ROUTE_CACHE_TTL: Duration = Duration::from_secs(60 * 10); // 10 minutes
11-
pub(crate) const DEFAULT_ROUTE_TIMEOUT: Duration = Duration::from_secs(15);
12-
1310
// Routing types
1411
#[derive(Clone, Debug)]
1512
pub struct RouteTarget {
@@ -51,11 +48,11 @@ pub(crate) struct RouteCache {
5148
}
5249

5350
impl RouteCache {
54-
pub(crate) fn new() -> Self {
51+
pub(crate) fn new(ttl: Duration) -> Self {
5552
Self {
5653
cache: Cache::builder()
5754
.max_capacity(10_000)
58-
.time_to_live(ROUTE_CACHE_TTL)
55+
.time_to_live(ttl)
5956
.build(),
6057
}
6158
}

engine/packages/guard/src/routing/pegboard_gateway/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ use crate::{
2323
use cors::{CorsPreflight, set_non_preflight_cors};
2424
use resolve_actor_query::resolve_query;
2525

26-
const ACTOR_FORCE_WAKE_PENDING_TIMEOUT: i64 = util::duration::seconds(60);
27-
const ACTOR_READY_TIMEOUT: Duration = Duration::from_secs(10);
28-
2926
/// Time to wait before starting pool error checks
3027
const RUNNER_POOL_ERROR_CHECK_DELAY: Duration = Duration::from_secs(1);
3128
/// Interval between pool error checks
@@ -436,7 +433,7 @@ async fn handle_actor_v2(
436433
}
437434
}
438435
// Ready timeout
439-
_ = tokio::time::sleep(ACTOR_READY_TIMEOUT) => {
436+
_ = tokio::time::sleep(ctx.config().guard().actor_ready_timeout()) => {
440437
return Err(errors::ActorReadyTimeout { actor_id }.build());
441438
}
442439
}
@@ -480,7 +477,7 @@ async fn handle_actor_v1(
480477

481478
ctx.signal(pegboard::workflows::actor::Wake {
482479
allocation_override: pegboard::workflows::actor::AllocationOverride::DontSleep {
483-
pending_timeout: Some(ACTOR_FORCE_WAKE_PENDING_TIMEOUT),
480+
pending_timeout: Some(ctx.config().guard().actor_force_wake_pending_timeout()),
484481
},
485482
})
486483
.to_workflow_id(actor.workflow_id)
@@ -516,7 +513,9 @@ async fn handle_actor_v1(
516513

517514
let res = ctx.signal(pegboard::workflows::actor::Wake {
518515
allocation_override: pegboard::workflows::actor::AllocationOverride::DontSleep {
519-
pending_timeout: Some(ACTOR_FORCE_WAKE_PENDING_TIMEOUT),
516+
pending_timeout: Some(
517+
ctx.config().guard().actor_force_wake_pending_timeout(),
518+
),
520519
},
521520
})
522521
.to_workflow_id(actor.workflow_id)
@@ -565,7 +564,7 @@ async fn handle_actor_v1(
565564
}
566565
}
567566
// Ready timeout
568-
_ = tokio::time::sleep(ACTOR_READY_TIMEOUT) => {
567+
_ = tokio::time::sleep(ctx.config().guard().actor_ready_timeout()) => {
569568
return Err(errors::ActorReadyTimeout { actor_id }.build());
570569
}
571570
}

0 commit comments

Comments
 (0)