mirror of
https://github.com/telemt/telemt.git
synced 2026-10-21 08:14:24 +03:00
556affc63a
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
422 lines
16 KiB
Rust
422 lines
16 KiB
Rust
use super::*;
|
|
|
|
impl MePool {
|
|
/// Creates the immutable byte semaphore assigned to one ME writer generation.
|
|
pub(crate) fn new_writer_byte_budget(&self) -> Arc<Semaphore> {
|
|
Arc::new(Semaphore::new(
|
|
self.writer_lifecycle.writer_byte_budget_permits,
|
|
))
|
|
}
|
|
|
|
pub fn current_generation(&self) -> u64 {
|
|
self.reinit.active_generation.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub fn set_runtime_ready(&self, ready: bool) {
|
|
self.runtime_ready.store(ready, Ordering::Relaxed);
|
|
}
|
|
|
|
pub fn is_runtime_ready(&self) -> bool {
|
|
self.runtime_ready.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub(in crate::transport::middle_proxy) fn now_epoch_millis() -> u64 {
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_millis() as u64
|
|
}
|
|
|
|
pub(in crate::transport::middle_proxy) fn notify_writer_epoch(&self) {
|
|
self.writer_epoch.send_modify(|epoch| {
|
|
*epoch = epoch.wrapping_add(1);
|
|
});
|
|
}
|
|
|
|
pub(in crate::transport::middle_proxy) fn set_family_runtime_state(
|
|
&self,
|
|
family: IpFamily,
|
|
state: MeFamilyRuntimeState,
|
|
state_since_epoch_secs: u64,
|
|
suppressed_until_epoch_secs: u64,
|
|
fail_streak: u32,
|
|
recover_success_streak: u32,
|
|
) {
|
|
let snapshot = Arc::new(FamilyHealthSnapshot::new(
|
|
state,
|
|
state_since_epoch_secs,
|
|
suppressed_until_epoch_secs,
|
|
fail_streak,
|
|
recover_success_streak,
|
|
));
|
|
match family {
|
|
IpFamily::V4 => self.health_runtime.family_health_v4.store(snapshot),
|
|
IpFamily::V6 => self.health_runtime.family_health_v6.store(snapshot),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn family_runtime_state(&self, family: IpFamily) -> MeFamilyRuntimeState {
|
|
match family {
|
|
IpFamily::V4 => self.health_runtime.family_health_v4.load().state,
|
|
IpFamily::V6 => self.health_runtime.family_health_v6.load().state,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn family_runtime_state_since_epoch_secs(&self, family: IpFamily) -> u64 {
|
|
match family {
|
|
IpFamily::V4 => {
|
|
self.health_runtime
|
|
.family_health_v4
|
|
.load()
|
|
.state_since_epoch_secs
|
|
}
|
|
IpFamily::V6 => {
|
|
self.health_runtime
|
|
.family_health_v6
|
|
.load()
|
|
.state_since_epoch_secs
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn family_suppressed_until_epoch_secs(&self, family: IpFamily) -> u64 {
|
|
match family {
|
|
IpFamily::V4 => {
|
|
self.health_runtime
|
|
.family_health_v4
|
|
.load()
|
|
.suppressed_until_epoch_secs
|
|
}
|
|
IpFamily::V6 => {
|
|
self.health_runtime
|
|
.family_health_v6
|
|
.load()
|
|
.suppressed_until_epoch_secs
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn family_fail_streak(&self, family: IpFamily) -> u32 {
|
|
match family {
|
|
IpFamily::V4 => self.health_runtime.family_health_v4.load().fail_streak,
|
|
IpFamily::V6 => self.health_runtime.family_health_v6.load().fail_streak,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn family_recover_success_streak(&self, family: IpFamily) -> u32 {
|
|
match family {
|
|
IpFamily::V4 => {
|
|
self.health_runtime
|
|
.family_health_v4
|
|
.load()
|
|
.recover_success_streak
|
|
}
|
|
IpFamily::V6 => {
|
|
self.health_runtime
|
|
.family_health_v6
|
|
.load()
|
|
.recover_success_streak
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn is_family_temporarily_suppressed(
|
|
&self,
|
|
family: IpFamily,
|
|
now_epoch_secs: u64,
|
|
) -> bool {
|
|
self.family_suppressed_until_epoch_secs(family) > now_epoch_secs
|
|
}
|
|
|
|
pub(in crate::transport::middle_proxy) fn family_enabled_for_drain_coverage(
|
|
&self,
|
|
family: IpFamily,
|
|
now_epoch_secs: u64,
|
|
) -> bool {
|
|
let configured = match family {
|
|
IpFamily::V4 => self.decision.ipv4_me,
|
|
IpFamily::V6 => self.decision.ipv6_me,
|
|
};
|
|
configured && !self.is_family_temporarily_suppressed(family, now_epoch_secs)
|
|
}
|
|
|
|
pub(in crate::transport::middle_proxy) fn set_last_drain_gate(
|
|
&self,
|
|
route_quorum_ok: bool,
|
|
redundancy_ok: bool,
|
|
block_reason: MeDrainGateReason,
|
|
updated_at_epoch_secs: u64,
|
|
) {
|
|
self.drain_runtime
|
|
.me_last_drain_gate_route_quorum_ok
|
|
.store(route_quorum_ok, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_last_drain_gate_redundancy_ok
|
|
.store(redundancy_ok, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_last_drain_gate_block_reason
|
|
.store(block_reason as u8, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_last_drain_gate_updated_at_epoch_secs
|
|
.store(updated_at_epoch_secs, Ordering::Relaxed);
|
|
}
|
|
|
|
pub(crate) fn last_drain_gate_route_quorum_ok(&self) -> bool {
|
|
self.drain_runtime
|
|
.me_last_drain_gate_route_quorum_ok
|
|
.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub(crate) fn last_drain_gate_redundancy_ok(&self) -> bool {
|
|
self.drain_runtime
|
|
.me_last_drain_gate_redundancy_ok
|
|
.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub(crate) fn last_drain_gate_block_reason(&self) -> MeDrainGateReason {
|
|
MeDrainGateReason::from_u8(
|
|
self.drain_runtime
|
|
.me_last_drain_gate_block_reason
|
|
.load(Ordering::Relaxed),
|
|
)
|
|
}
|
|
|
|
pub(crate) fn last_drain_gate_updated_at_epoch_secs(&self) -> u64 {
|
|
self.drain_runtime
|
|
.me_last_drain_gate_updated_at_epoch_secs
|
|
.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub fn update_runtime_reinit_policy(
|
|
&self,
|
|
hardswap: bool,
|
|
drain_ttl_secs: u64,
|
|
instadrain: bool,
|
|
pool_drain_threshold: u64,
|
|
pool_drain_soft_evict_enabled: bool,
|
|
pool_drain_soft_evict_grace_secs: u64,
|
|
pool_drain_soft_evict_per_writer: u8,
|
|
pool_drain_soft_evict_budget_per_core: u16,
|
|
pool_drain_soft_evict_cooldown_ms: u64,
|
|
force_close_secs: u64,
|
|
min_fresh_ratio: f32,
|
|
hardswap_warmup_delay_min_ms: u64,
|
|
hardswap_warmup_delay_max_ms: u64,
|
|
hardswap_warmup_extra_passes: u8,
|
|
hardswap_warmup_pass_backoff_base_ms: u64,
|
|
bind_stale_mode: MeBindStaleMode,
|
|
bind_stale_ttl_secs: u64,
|
|
secret_atomic_snapshot: bool,
|
|
deterministic_writer_sort: bool,
|
|
writer_pick_mode: MeWriterPickMode,
|
|
writer_pick_sample_size: u8,
|
|
single_endpoint_shadow_writers: u8,
|
|
single_endpoint_outage_mode_enabled: bool,
|
|
single_endpoint_outage_disable_quarantine: bool,
|
|
single_endpoint_outage_backoff_min_ms: u64,
|
|
single_endpoint_outage_backoff_max_ms: u64,
|
|
single_endpoint_shadow_rotate_every_secs: u64,
|
|
floor_mode: MeFloorMode,
|
|
adaptive_floor_idle_secs: u64,
|
|
adaptive_floor_min_writers_single_endpoint: u8,
|
|
adaptive_floor_min_writers_multi_endpoint: u8,
|
|
adaptive_floor_recover_grace_secs: u64,
|
|
adaptive_floor_writers_per_core_total: u16,
|
|
adaptive_floor_cpu_cores_override: u16,
|
|
adaptive_floor_max_extra_writers_single_per_core: u16,
|
|
adaptive_floor_max_extra_writers_multi_per_core: u16,
|
|
adaptive_floor_max_active_writers_per_core: u16,
|
|
adaptive_floor_max_warm_writers_per_core: u16,
|
|
adaptive_floor_max_active_writers_global: u32,
|
|
adaptive_floor_max_warm_writers_global: u32,
|
|
me_health_interval_ms_unhealthy: u64,
|
|
me_health_interval_ms_healthy: u64,
|
|
me_warn_rate_limit_ms: u64,
|
|
) {
|
|
self.reinit.hardswap.store(hardswap, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_pool_drain_ttl_secs
|
|
.store(drain_ttl_secs, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_instadrain
|
|
.store(instadrain, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_pool_drain_threshold
|
|
.store(pool_drain_threshold, Ordering::Relaxed);
|
|
// Runtime soft-evict knobs are updated lock-free to keep control-plane
|
|
// writes non-blocking; readers observe a short eventual-consistency
|
|
// window by design.
|
|
self.drain_runtime
|
|
.me_pool_drain_soft_evict_enabled
|
|
.store(pool_drain_soft_evict_enabled, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_pool_drain_soft_evict_grace_secs
|
|
.store(pool_drain_soft_evict_grace_secs, Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_pool_drain_soft_evict_per_writer
|
|
.store(pool_drain_soft_evict_per_writer.max(1), Ordering::Relaxed);
|
|
self.drain_runtime
|
|
.me_pool_drain_soft_evict_budget_per_core
|
|
.store(
|
|
pool_drain_soft_evict_budget_per_core.max(1) as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.drain_runtime
|
|
.me_pool_drain_soft_evict_cooldown_ms
|
|
.store(pool_drain_soft_evict_cooldown_ms.max(1), Ordering::Relaxed);
|
|
self.drain_runtime.me_pool_force_close_secs.store(
|
|
Self::normalize_force_close_secs(force_close_secs),
|
|
Ordering::Relaxed,
|
|
);
|
|
self.drain_runtime
|
|
.me_pool_min_fresh_ratio_permille
|
|
.store(Self::ratio_to_permille(min_fresh_ratio), Ordering::Relaxed);
|
|
self.reinit
|
|
.me_hardswap_warmup_delay_min_ms
|
|
.store(hardswap_warmup_delay_min_ms, Ordering::Relaxed);
|
|
self.reinit
|
|
.me_hardswap_warmup_delay_max_ms
|
|
.store(hardswap_warmup_delay_max_ms, Ordering::Relaxed);
|
|
self.reinit
|
|
.me_hardswap_warmup_extra_passes
|
|
.store(hardswap_warmup_extra_passes as u32, Ordering::Relaxed);
|
|
self.reinit
|
|
.me_hardswap_warmup_pass_backoff_base_ms
|
|
.store(hardswap_warmup_pass_backoff_base_ms, Ordering::Relaxed);
|
|
self.binding_policy
|
|
.me_bind_stale_mode
|
|
.store(bind_stale_mode.as_u8(), Ordering::Relaxed);
|
|
self.binding_policy
|
|
.me_bind_stale_ttl_secs
|
|
.store(bind_stale_ttl_secs, Ordering::Relaxed);
|
|
self.writer_selection_policy
|
|
.secret_atomic_snapshot
|
|
.store(secret_atomic_snapshot, Ordering::Relaxed);
|
|
self.writer_selection_policy
|
|
.me_deterministic_writer_sort
|
|
.store(deterministic_writer_sort, Ordering::Relaxed);
|
|
let previous_writer_pick_mode = self.writer_pick_mode();
|
|
self.writer_selection_policy
|
|
.me_writer_pick_mode
|
|
.store(writer_pick_mode.as_u8(), Ordering::Relaxed);
|
|
self.writer_selection_policy
|
|
.me_writer_pick_sample_size
|
|
.store(writer_pick_sample_size.clamp(2, 4), Ordering::Relaxed);
|
|
if previous_writer_pick_mode != writer_pick_mode {
|
|
self.stats.increment_me_writer_pick_mode_switch_total();
|
|
}
|
|
let mut coordinator = self.reinit.coordinator.lock();
|
|
let previous_floor_policy = self.floor_policy_values();
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_shadow_writers
|
|
.store(single_endpoint_shadow_writers, Ordering::Relaxed);
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_outage_mode_enabled
|
|
.store(single_endpoint_outage_mode_enabled, Ordering::Relaxed);
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_outage_disable_quarantine
|
|
.store(single_endpoint_outage_disable_quarantine, Ordering::Relaxed);
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_outage_backoff_min_ms
|
|
.store(single_endpoint_outage_backoff_min_ms, Ordering::Relaxed);
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_outage_backoff_max_ms
|
|
.store(single_endpoint_outage_backoff_max_ms, Ordering::Relaxed);
|
|
self.single_endpoint_runtime
|
|
.me_single_endpoint_shadow_rotate_every_secs
|
|
.store(single_endpoint_shadow_rotate_every_secs, Ordering::Relaxed);
|
|
let previous_floor_mode = self.floor_mode();
|
|
self.floor_runtime
|
|
.me_floor_mode
|
|
.store(floor_mode.as_u8(), Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_idle_secs
|
|
.store(adaptive_floor_idle_secs, Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_min_writers_single_endpoint
|
|
.store(
|
|
adaptive_floor_min_writers_single_endpoint,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_min_writers_multi_endpoint
|
|
.store(adaptive_floor_min_writers_multi_endpoint, Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_recover_grace_secs
|
|
.store(adaptive_floor_recover_grace_secs, Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_writers_per_core_total
|
|
.store(
|
|
adaptive_floor_writers_per_core_total as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_cpu_cores_override
|
|
.store(adaptive_floor_cpu_cores_override as u32, Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_extra_writers_single_per_core
|
|
.store(
|
|
adaptive_floor_max_extra_writers_single_per_core as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_extra_writers_multi_per_core
|
|
.store(
|
|
adaptive_floor_max_extra_writers_multi_per_core as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_active_writers_per_core
|
|
.store(
|
|
adaptive_floor_max_active_writers_per_core as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_warm_writers_per_core
|
|
.store(
|
|
adaptive_floor_max_warm_writers_per_core as u32,
|
|
Ordering::Relaxed,
|
|
);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_active_writers_global
|
|
.store(adaptive_floor_max_active_writers_global, Ordering::Relaxed);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_max_warm_writers_global
|
|
.store(adaptive_floor_max_warm_writers_global, Ordering::Relaxed);
|
|
if previous_floor_policy != self.floor_policy_values() {
|
|
coordinator.floor_policy_revision = coordinator.floor_policy_revision.wrapping_add(1);
|
|
// Cached caps belong to the old policy until a new health plan is accepted.
|
|
self.floor_runtime
|
|
.me_adaptive_floor_active_cap_effective
|
|
.store(0, Ordering::Release);
|
|
self.floor_runtime
|
|
.me_adaptive_floor_warm_cap_effective
|
|
.store(0, Ordering::Release);
|
|
}
|
|
drop(coordinator);
|
|
self.health_runtime
|
|
.me_health_interval_ms_unhealthy
|
|
.store(me_health_interval_ms_unhealthy.max(1), Ordering::Relaxed);
|
|
self.health_runtime
|
|
.me_health_interval_ms_healthy
|
|
.store(me_health_interval_ms_healthy.max(1), Ordering::Relaxed);
|
|
self.health_runtime
|
|
.me_warn_rate_limit_ms
|
|
.store(me_warn_rate_limit_ms.max(1), Ordering::Relaxed);
|
|
if previous_floor_mode != floor_mode {
|
|
self.stats.increment_me_floor_mode_switch_total();
|
|
match (previous_floor_mode, floor_mode) {
|
|
(MeFloorMode::Static, MeFloorMode::Adaptive) => {
|
|
self.stats
|
|
.increment_me_floor_mode_switch_static_to_adaptive_total();
|
|
}
|
|
(MeFloorMode::Adaptive, MeFloorMode::Static) => {
|
|
self.stats
|
|
.increment_me_floor_mode_switch_adaptive_to_static_total();
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|