mirror of
https://github.com/telemt/telemt.git
synced 2026-11-05 23:32:00 +03:00
Decoy Fasttrack Drafts
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
@@ -15,7 +15,7 @@ use super::model::ApiFailure;
|
||||
use crate::config::ProxyConfig;
|
||||
use crate::config::hot_reload::classify_config_changes;
|
||||
use crate::maestro::reload::{ReloadAccepted, ReloadRequest, ReloadSubmitError};
|
||||
use crate::maestro::runtime_build::{deferred_process_fields, resolve_reload_config};
|
||||
use crate::maestro::runtime_build::resolve_reload_config;
|
||||
use serde::Serialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
@@ -206,8 +206,7 @@ async fn prepare_patch_to_path(
|
||||
let revision = compute_snapshot_revision(&candidate);
|
||||
let new_cfg = candidate.config;
|
||||
let class = classify_config_changes(&old_cfg, &new_cfg);
|
||||
let deferred_process_fields =
|
||||
deferred_process_fields(&old_cfg, &new_cfg).map_err(ApiFailure::bad_request)?;
|
||||
let resolved = resolve_reload_config(&old_cfg, &new_cfg).map_err(ApiFailure::bad_request)?;
|
||||
|
||||
Ok(PreparedConfigPatch {
|
||||
owner_path,
|
||||
@@ -216,9 +215,9 @@ async fn prepare_patch_to_path(
|
||||
response: PatchConfigResponse {
|
||||
revision,
|
||||
restart_required: class.restart_required,
|
||||
runtime_reload_required: class.restart_required,
|
||||
process_restart_required: !deferred_process_fields.is_empty(),
|
||||
deferred_process_fields,
|
||||
runtime_reload_required: resolved.runtime_changed,
|
||||
process_restart_required: !resolved.deferred_process_fields.is_empty(),
|
||||
deferred_process_fields: resolved.deferred_process_fields,
|
||||
changed: class.changed,
|
||||
reload: None,
|
||||
},
|
||||
|
||||
@@ -131,6 +131,24 @@ async fn patch_web_debug_is_hot_and_limits_are_process_deferred() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn patch_web_decoy_fasttrack_requires_only_process_restart() {
|
||||
let (path, _directory) = temp_config("[web]\nenabled = false\n");
|
||||
let patch: Json = serde_json::json!({
|
||||
"web": {"decoy_fasttrack_mode": "shadow"}
|
||||
});
|
||||
|
||||
let response = apply_patch_to_path(&path, &patch, None).await.unwrap();
|
||||
|
||||
assert!(response.restart_required);
|
||||
assert!(!response.runtime_reload_required);
|
||||
assert!(response.process_restart_required);
|
||||
assert_eq!(
|
||||
response.deferred_process_fields,
|
||||
vec!["web.decoy_fasttrack_mode".to_string()]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_web_patch_does_not_modify_the_source() {
|
||||
let (path, _directory) = temp_config("[web]\nenabled = false\n");
|
||||
|
||||
@@ -20,8 +20,8 @@ mod request;
|
||||
// Ingress, capacity, and decoy telemetry remain separate availability planes.
|
||||
mod observability;
|
||||
use observability::{
|
||||
WebCapacityStatus, WebCarrierNegotiationStatus, WebDecoyUpstreamStatus, WebIngressStatus,
|
||||
WebLifecycleCountersStatus,
|
||||
WebCapacityStatus, WebCarrierNegotiationStatus, WebDecoyFastTrackStatus,
|
||||
WebDecoyUpstreamStatus, WebIngressStatus, WebLifecycleCountersStatus,
|
||||
};
|
||||
use request::{
|
||||
CloseRequest, DrainRequest, RuntimeInstanceRequest, parse_session_query, parse_session_ref,
|
||||
@@ -280,6 +280,7 @@ struct WebStatusData {
|
||||
ingress: WebIngressStatus,
|
||||
capacity: WebCapacityStatus,
|
||||
decoy_upstream: WebDecoyUpstreamStatus,
|
||||
decoy_fasttrack: WebDecoyFastTrackStatus,
|
||||
carrier_negotiation: WebCarrierNegotiationStatus,
|
||||
lifecycle_counters: WebLifecycleCountersStatus,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -315,6 +316,7 @@ impl WebStatusData {
|
||||
let ingress = WebIngressStatus::new(&publication, runtime.is_some());
|
||||
let capacity = WebCapacityStatus::new(&publication, runtime, config);
|
||||
let decoy_upstream = WebDecoyUpstreamStatus::new(&publication);
|
||||
let decoy_fasttrack = WebDecoyFastTrackStatus::new(&publication, config);
|
||||
let carrier_negotiation = WebCarrierNegotiationStatus::new(&publication);
|
||||
let lifecycle_counters = WebLifecycleCountersStatus::new(&publication, config);
|
||||
Self {
|
||||
@@ -332,6 +334,7 @@ impl WebStatusData {
|
||||
ingress,
|
||||
capacity,
|
||||
decoy_upstream,
|
||||
decoy_fasttrack,
|
||||
carrier_negotiation,
|
||||
lifecycle_counters,
|
||||
operator_lifecycle,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::config::{ProxyConfig, WebHttpConnectionCapacityAction};
|
||||
use crate::config::{ProxyConfig, WebDecoyFastTrackMode, WebHttpConnectionCapacityAction};
|
||||
use crate::web::control::{WebRuntimeLifecycle, WebRuntimePublication};
|
||||
use crate::web::manager::{WebCapacityResourceStatus, WebCapacitySnapshot, WebProcessRuntime};
|
||||
use crate::web::telemetry::{
|
||||
WebBridgeRecoveryCounter, WebCarrierFailureCounter, WebCarrierLearningCounter,
|
||||
WebCarrierSelectionCounter, WebSessionCloseCounter, WebSessionLifecycleObservationCounter,
|
||||
WebCarrierSelectionCounter, WebDecoyFastTrackCounter, WebSessionCloseCounter,
|
||||
WebSessionLifecycleObservationCounter,
|
||||
};
|
||||
use crate::web::telemetry::{WebOutcomeCounter, WebRejectionCounter};
|
||||
|
||||
@@ -121,6 +122,27 @@ impl WebDecoyUpstreamStatus {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fixed-cardinality process-lifetime decoy capability-routing counters.
|
||||
#[derive(Serialize)]
|
||||
pub(super) struct WebDecoyFastTrackStatus {
|
||||
mode: WebDecoyFastTrackMode,
|
||||
requests: Vec<WebDecoyFastTrackCounter>,
|
||||
shadow_mismatches_total: u64,
|
||||
}
|
||||
|
||||
impl WebDecoyFastTrackStatus {
|
||||
/// Builds effective policy and counters without requiring the runtime manager.
|
||||
pub(super) fn new(publication: &WebRuntimePublication, config: &ProxyConfig) -> Self {
|
||||
Self {
|
||||
mode: config.web.decoy_fasttrack_mode,
|
||||
requests: publication.telemetry.decoy_fasttrack_counters(),
|
||||
shadow_mismatches_total: publication
|
||||
.telemetry
|
||||
.decoy_fasttrack_shadow_mismatches(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fixed-cardinality process-lifetime carrier negotiation counters.
|
||||
#[derive(Serialize)]
|
||||
pub(super) struct WebCarrierNegotiationStatus {
|
||||
@@ -187,6 +209,11 @@ mod tests {
|
||||
serde_json::to_value(super::WebCapacityStatus::new(&publication, None, &config))
|
||||
.unwrap();
|
||||
let decoy = serde_json::to_value(super::WebDecoyUpstreamStatus::new(&publication)).unwrap();
|
||||
let fasttrack = serde_json::to_value(super::WebDecoyFastTrackStatus::new(
|
||||
&publication,
|
||||
&config,
|
||||
))
|
||||
.unwrap();
|
||||
let carrier =
|
||||
serde_json::to_value(super::WebCarrierNegotiationStatus::new(&publication)).unwrap();
|
||||
let lifecycle = serde_json::to_value(super::WebLifecycleCountersStatus::new(
|
||||
@@ -210,6 +237,12 @@ mod tests {
|
||||
decoy["outcomes"].as_array().unwrap().len(),
|
||||
crate::web::telemetry::WebDecoyUpstreamOutcome::ALL.len()
|
||||
);
|
||||
assert_eq!(fasttrack["mode"], "off");
|
||||
assert_eq!(
|
||||
fasttrack["requests"].as_array().unwrap().len(),
|
||||
crate::web::telemetry::WebDecoyFastTrackDisposition::ALL.len()
|
||||
);
|
||||
assert_eq!(fasttrack["shadow_mismatches_total"], 0);
|
||||
assert_eq!(capacity["partial"][0], "runtime");
|
||||
assert_eq!(
|
||||
carrier["selections"].as_array().unwrap().len(),
|
||||
|
||||
Reference in New Issue
Block a user