Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions engine/artifacts/config-schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions engine/packages/config/src/config/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ pub struct Guard {
/// Enables the internal websocket health route for debug and latency testing. This is intended
/// for websocket ping/pong verification and should remain disabled in normal deployments.
pub enable_websocket_health_route: Option<bool>,
/// TTL for cached route lookups in milliseconds.
pub route_cache_ttl_ms: Option<u64>,
/// Timeout for route resolution in milliseconds.
pub route_timeout_ms: Option<u64>,
/// Timeout for waiting for an actor to become ready in milliseconds.
pub actor_ready_timeout_ms: Option<u64>,
/// Timeout sent with actor force-wake requests in milliseconds.
pub actor_force_wake_pending_timeout_ms: Option<i64>,
/// Enable & configure HTTPS
pub https: Option<Https>,
/// Max HTTP request body size in bytes (first line of defense).
Expand All @@ -37,6 +45,23 @@ impl Guard {
self.enable_websocket_health_route.unwrap_or(false)
}

pub fn route_cache_ttl(&self) -> std::time::Duration {
std::time::Duration::from_millis(self.route_cache_ttl_ms.unwrap_or(60 * 10 * 1000))
}

pub fn route_timeout(&self) -> std::time::Duration {
std::time::Duration::from_millis(self.route_timeout_ms.unwrap_or(15_000))
}

pub fn actor_ready_timeout(&self) -> std::time::Duration {
std::time::Duration::from_millis(self.actor_ready_timeout_ms.unwrap_or(10_000))
}

pub fn actor_force_wake_pending_timeout(&self) -> i64 {
self.actor_force_wake_pending_timeout_ms
.unwrap_or(60 * 1000)
}

pub fn http_max_request_body_size(&self) -> usize {
self.http_max_request_body_size.unwrap_or(20 * 1024 * 1024) // 20 MiB
}
Expand Down
16 changes: 9 additions & 7 deletions engine/packages/guard-core/src/proxy_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
use tracing::Instrument;
use url::Url;

use crate::RouteTarget;

Check warning on line 30 in engine/packages/guard-core/src/proxy_service.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

Diff in /home/runner/work/rivet/rivet/engine/packages/guard-core/src/proxy_service.rs
use crate::request_context::RequestContext;
use crate::response_body::ResponseBody;
use crate::route::{
CacheKeyFn, DEFAULT_ROUTE_TIMEOUT, ResolveRouteOutput, RouteCache, RoutingFn, RoutingOutput,
CacheKeyFn, ResolveRouteOutput, RouteCache, RoutingFn, RoutingOutput,
};
use crate::utils::{InFlightCounter, RateLimiter};
use crate::{
Expand Down Expand Up @@ -89,13 +89,14 @@
let client = Client::builder(TokioExecutor::new())
.pool_idle_timeout(Duration::from_secs(30))
.build(https_connector);
let route_cache_ttl = config.guard().route_cache_ttl();

Self {
config,
routing_fn,
cache_key_fn,
client,
route_cache: RouteCache::new(),
route_cache: RouteCache::new(route_cache_ttl),
rate_limiters: Cache::builder()
.max_capacity(10_000)
.time_to_live(PROXY_STATE_CACHE_TTL)
Expand Down Expand Up @@ -134,21 +135,22 @@
let res = if let Some(res) = cache_res {
res
} else {
// Not in cache, call routing function with a default timeout
// Default 15 seconds, routing functions should have their own internal timeouts that are shorter
// Not in cache, call routing function with a configured timeout.
// Routing functions should have their own internal timeouts that are shorter.
let route_timeout = self.config.guard().route_timeout();
tracing::debug!(
hostname = %req_ctx.hostname,
path = %req_ctx.path,
cache_hit = false,
timeout_seconds = DEFAULT_ROUTE_TIMEOUT.as_secs(),
timeout_seconds = route_timeout.as_secs(),
"Cache miss, calling routing function"
);

let routing_res = timeout(DEFAULT_ROUTE_TIMEOUT, (self.routing_fn)(req_ctx))
let routing_res = timeout(route_timeout, (self.routing_fn)(req_ctx))
.await
.map_err(|_| {
errors::RequestTimeout {
timeout_seconds: DEFAULT_ROUTE_TIMEOUT.as_secs(),
timeout_seconds: route_timeout.as_secs(),
}
.build()
})??;
Expand Down
7 changes: 2 additions & 5 deletions engine/packages/guard-core/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ use crate::custom_serve::CustomServeTrait;
use crate::metrics;
use crate::request_context::RequestContext;

const ROUTE_CACHE_TTL: Duration = Duration::from_secs(60 * 10); // 10 minutes
pub(crate) const DEFAULT_ROUTE_TIMEOUT: Duration = Duration::from_secs(15);

// Routing types
#[derive(Clone, Debug)]
pub struct RouteTarget {
Expand Down Expand Up @@ -51,11 +48,11 @@ pub(crate) struct RouteCache {
}

impl RouteCache {
pub(crate) fn new() -> Self {
pub(crate) fn new(ttl: Duration) -> Self {
Self {
cache: Cache::builder()
.max_capacity(10_000)
.time_to_live(ROUTE_CACHE_TTL)
.time_to_live(ttl)
.build(),
}
}
Expand Down
13 changes: 6 additions & 7 deletions engine/packages/guard/src/routing/pegboard_gateway/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ use crate::{
use cors::{CorsPreflight, set_non_preflight_cors};
use resolve_actor_query::resolve_query;

const ACTOR_FORCE_WAKE_PENDING_TIMEOUT: i64 = util::duration::seconds(60);
const ACTOR_READY_TIMEOUT: Duration = Duration::from_secs(10);

/// Time to wait before starting pool error checks
const RUNNER_POOL_ERROR_CHECK_DELAY: Duration = Duration::from_secs(1);
/// Interval between pool error checks
Expand Down Expand Up @@ -436,7 +433,7 @@ async fn handle_actor_v2(
}
}
// Ready timeout
_ = tokio::time::sleep(ACTOR_READY_TIMEOUT) => {
_ = tokio::time::sleep(ctx.config().guard().actor_ready_timeout()) => {
return Err(errors::ActorReadyTimeout { actor_id }.build());
}
}
Expand Down Expand Up @@ -480,7 +477,7 @@ async fn handle_actor_v1(

ctx.signal(pegboard::workflows::actor::Wake {
allocation_override: pegboard::workflows::actor::AllocationOverride::DontSleep {
pending_timeout: Some(ACTOR_FORCE_WAKE_PENDING_TIMEOUT),
pending_timeout: Some(ctx.config().guard().actor_force_wake_pending_timeout()),
},
})
.to_workflow_id(actor.workflow_id)
Expand Down Expand Up @@ -516,7 +513,9 @@ async fn handle_actor_v1(

let res = ctx.signal(pegboard::workflows::actor::Wake {
allocation_override: pegboard::workflows::actor::AllocationOverride::DontSleep {
pending_timeout: Some(ACTOR_FORCE_WAKE_PENDING_TIMEOUT),
pending_timeout: Some(
ctx.config().guard().actor_force_wake_pending_timeout(),
),
},
})
.to_workflow_id(actor.workflow_id)
Expand Down Expand Up @@ -565,7 +564,7 @@ async fn handle_actor_v1(
}
}
// Ready timeout
_ = tokio::time::sleep(ACTOR_READY_TIMEOUT) => {
_ = tokio::time::sleep(ctx.config().guard().actor_ready_timeout()) => {
return Err(errors::ActorReadyTimeout { actor_id }.build());
}
}
Expand Down
Loading
Loading