mirror of
https://github.com/telemt/telemt.git
synced 2026-10-31 12:52:19 +03:00
WEB Manager Session + Generation Fence tests
This commit is contained in:
@@ -62,15 +62,22 @@ struct ReinitCommitOutcome {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
struct DcFamilyGroup {
|
||||
dc: i32,
|
||||
family: IpFamily,
|
||||
/// One independently enforced hardswap writer-floor group.
|
||||
pub(in crate::transport::middle_proxy) struct DcFamilyGroup {
|
||||
/// Telegram DC owning the group.
|
||||
pub(in crate::transport::middle_proxy) dc: i32,
|
||||
/// Address family whose floor is evaluated independently.
|
||||
pub(in crate::transport::middle_proxy) family: IpFamily,
|
||||
}
|
||||
|
||||
struct HardswapCoverage {
|
||||
ratio: f32,
|
||||
missing_groups: Vec<DcFamilyGroup>,
|
||||
writer_deficit: usize,
|
||||
/// Complete floor-coverage result for one candidate hardswap generation.
|
||||
pub(in crate::transport::middle_proxy) struct HardswapCoverage {
|
||||
/// Fraction of configured DC-family groups that reached their full floor.
|
||||
pub(in crate::transport::middle_proxy) ratio: f32,
|
||||
/// Stable list of DC-family groups that remain below their floor.
|
||||
pub(in crate::transport::middle_proxy) missing_groups: Vec<DcFamilyGroup>,
|
||||
/// Total writer count still required across all missing groups.
|
||||
pub(in crate::transport::middle_proxy) writer_deficit: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -287,7 +287,7 @@ impl MePool {
|
||||
}
|
||||
|
||||
/// Evaluates full writer-floor coverage independently for every DC and address family.
|
||||
pub(super) fn hardswap_coverage(
|
||||
pub(in crate::transport::middle_proxy) fn hardswap_coverage(
|
||||
&self,
|
||||
desired_by_dc: &HashMap<i32, HashSet<SocketAddr>>,
|
||||
writer_addrs: &[(i32, SocketAddr)],
|
||||
|
||||
@@ -537,7 +537,12 @@ async fn generation_role_reconciliation_promotes_active_warm_and_drains_orphans(
|
||||
assert!(orphan_warm.draining.load(Ordering::Acquire));
|
||||
assert!(!orphan_warm.allow_drain_fallback.load(Ordering::Acquire));
|
||||
let snapshot = pool.api_hardswap_snapshot().await;
|
||||
let desired = pool.desired_dc_endpoints().await;
|
||||
let coverage = pool.hardswap_coverage(&desired, &[(1, endpoint)]);
|
||||
assert_eq!(snapshot.orphan_warm_writers_current, 0);
|
||||
assert_eq!(snapshot.pending_writer_deficit, 2);
|
||||
assert_eq!(snapshot.pending_missing_dc_groups, 1);
|
||||
assert_eq!(snapshot.pending_writer_deficit, coverage.writer_deficit);
|
||||
assert_eq!(
|
||||
snapshot.pending_missing_dc_groups,
|
||||
coverage.missing_groups.len()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::time::Instant;
|
||||
|
||||
use super::pool::{MePool, ReinitStatusSnapshot, WriterContour};
|
||||
use crate::config::{MeBindStaleMode, MeFloorMode, MeSocksKdfPolicy};
|
||||
use crate::network::IpFamily;
|
||||
use crate::transport::upstream::IpPreference;
|
||||
|
||||
// ME writer and DC coverage snapshots.
|
||||
|
||||
@@ -41,7 +41,7 @@ impl MePool {
|
||||
let pending_generation = reinit.pending_hardswap_generation;
|
||||
let pending = pending_generation != 0;
|
||||
let mut pending_writers_current = 0usize;
|
||||
let mut pending_by_group = HashMap::<(i32, IpFamily), usize>::new();
|
||||
let mut pending_writer_addrs = Vec::<(i32, SocketAddr)>::new();
|
||||
let mut orphan_warm_writers_current = 0usize;
|
||||
|
||||
for writer in writers.iter() {
|
||||
@@ -60,40 +60,18 @@ impl MePool {
|
||||
.is_some_and(|endpoints| endpoints.contains(&writer.addr))
|
||||
{
|
||||
pending_writers_current = pending_writers_current.saturating_add(1);
|
||||
let family = if writer.addr.is_ipv4() {
|
||||
IpFamily::V4
|
||||
} else {
|
||||
IpFamily::V6
|
||||
};
|
||||
*pending_by_group
|
||||
.entry((writer.writer_dc, family))
|
||||
.or_insert(0) += 1;
|
||||
pending_writer_addrs.push((writer.writer_dc, writer.addr));
|
||||
}
|
||||
}
|
||||
|
||||
let mut pending_writer_deficit = 0usize;
|
||||
let mut pending_missing_dc_groups = 0usize;
|
||||
if pending {
|
||||
for (dc, endpoints) in &desired_by_dc {
|
||||
for family in [IpFamily::V4, IpFamily::V6] {
|
||||
let endpoint_count = endpoints
|
||||
.iter()
|
||||
.filter(|endpoint| endpoint.is_ipv4() == (family == IpFamily::V4))
|
||||
.count();
|
||||
if endpoint_count == 0 {
|
||||
continue;
|
||||
}
|
||||
let alive = pending_by_group.get(&(*dc, family)).copied().unwrap_or(0);
|
||||
let required = self.required_writers_for_dc(endpoint_count);
|
||||
let deficit = required.saturating_sub(alive);
|
||||
pending_writer_deficit = pending_writer_deficit.saturating_add(deficit);
|
||||
if deficit > 0 {
|
||||
pending_missing_dc_groups =
|
||||
pending_missing_dc_groups.saturating_add(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let pending_coverage = pending
|
||||
.then(|| self.hardswap_coverage(&desired_by_dc, &pending_writer_addrs));
|
||||
let pending_writer_deficit = pending_coverage
|
||||
.as_ref()
|
||||
.map_or(0, |coverage| coverage.writer_deficit);
|
||||
let pending_missing_dc_groups = pending_coverage
|
||||
.as_ref()
|
||||
.map_or(0, |coverage| coverage.missing_groups.len());
|
||||
let (replacement_preparing_current, replacement_retiring_current) =
|
||||
self.registry.writer_replacement_counts();
|
||||
let pending_age_secs = pending.then(|| {
|
||||
|
||||
Reference in New Issue
Block a user