[TSM.ID].[11031972] PXE : 19 Cangkang -> REAL Implementation (for/if/match/tests)
This commit is contained in:
@@ -1,76 +1,116 @@
|
||||
#![deny(warnings)]
|
||||
// [TSM.ID].[11031972] — All Rights Reserved. Proprietary & Confidential.
|
||||
use tracing::debug;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
||||
//! xcu-harmonic -- Cross-service Tempo Synchronization
|
||||
//! Distributed clock sync, heartbeat coordination, event ordering
|
||||
|
||||
/// THE HARMONIC MATRIX (Phase 38)
|
||||
/// Global Quantum Clock Synchronization (Precision Time Protocol / IEEE 1588)
|
||||
pub struct HarmonicClock;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
impl HarmonicClock {
|
||||
/// Mengambil stempel waktu absolut (Universal Time) hingga tingkat milidetik
|
||||
pub fn get_absolute_now() -> u64 {
|
||||
let start = SystemTime::now();
|
||||
let since_the_epoch = start.duration_since(UNIX_EPOCH).expect("Time went backwards");
|
||||
since_the_epoch.as_millis() as u64
|
||||
#[derive(Debug)]
|
||||
pub enum HarmonicError { ClockDrift(String), SyncFailed(String), NodeLost(String) }
|
||||
impl std::fmt::Display for HarmonicError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self { Self::ClockDrift(e) => write!(f, "Drift: {e}"), Self::SyncFailed(e) => write!(f, "Sync: {e}"), Self::NodeLost(e) => write!(f, "Lost: {e}") }
|
||||
}
|
||||
}
|
||||
impl std::error::Error for HarmonicError {}
|
||||
|
||||
/// Menghitung "Waktu Ledakan" (Detonation Time) absolut untuk sebuah ruangan.
|
||||
/// Waktu ledakan adalah: Waktu Saat Ini + Selisih Latensi Terburuk di Ruangan Tersebut.
|
||||
pub fn calculate_global_detonation_time(worst_rtt_ms: u64) -> u64 {
|
||||
let now = Self::get_absolute_now();
|
||||
// Berikan buffer ekstra (contoh: 50ms) di atas latensi terburuk untuk margin keamanan hardware
|
||||
let detonation_time = now + worst_rtt_ms + 50;
|
||||
|
||||
debug!("HARMONIC MATRIX: Paket dikunci. Akan diledakkan serentak secara global pada Timestamp: {}", detonation_time);
|
||||
detonation_time
|
||||
/// Hybrid Logical Clock (HLC) — combination of physical + logical time
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct HybridTimestamp { pub physical: u64, pub logical: u32, pub node_id: u16 }
|
||||
|
||||
impl HybridTimestamp {
|
||||
pub fn new(physical: u64, node_id: u16) -> Self { Self { physical, logical: 0, node_id } }
|
||||
/// Update on local event
|
||||
pub fn tick(&mut self, now: u64) {
|
||||
if now > self.physical { self.physical = now; self.logical = 0; }
|
||||
else { self.logical += 1; }
|
||||
}
|
||||
|
||||
/// SISI KLIEN / RECEIVER: Mengeksekusi paket
|
||||
/// Mengecek apakah sudah waktunya paket ini dikeluarkan ke Speaker
|
||||
pub fn is_time_to_detonate(detonation_time: u64) -> bool {
|
||||
let now = Self::get_absolute_now();
|
||||
now >= detonation_time
|
||||
/// Merge with received timestamp (Lamport-style)
|
||||
pub fn merge(&mut self, other: &HybridTimestamp, now: u64) {
|
||||
if now > self.physical && now > other.physical { self.physical = now; self.logical = 0; }
|
||||
else if self.physical == other.physical { self.logical = self.logical.max(other.logical) + 1; }
|
||||
else if other.physical > self.physical { self.physical = other.physical; self.logical = other.logical + 1; }
|
||||
else { self.logical += 1; }
|
||||
}
|
||||
pub fn to_bytes(&self) -> [u8; 14] {
|
||||
let mut buf = [0u8; 14];
|
||||
buf[..8].copy_from_slice(&self.physical.to_be_bytes());
|
||||
buf[8..12].copy_from_slice(&self.logical.to_be_bytes());
|
||||
buf[12..14].copy_from_slice(&self.node_id.to_be_bytes());
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
/// Struktur Pembungkus Paket Suara dengan Timestamp
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct HarmonicPacket {
|
||||
pub payload: Vec<u8>,
|
||||
pub detonation_timestamp: u64,
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HeartbeatRecord { pub node_id: String, pub timestamp: HybridTimestamp, pub drift_ms: i64, pub is_alive: bool }
|
||||
|
||||
pub struct Harmonic {
|
||||
clock: Arc<Mutex<HybridTimestamp>>,
|
||||
node_id: u16,
|
||||
heartbeats: Arc<Mutex<HashMap<String, HeartbeatRecord>>>,
|
||||
max_drift_ms: i64,
|
||||
}
|
||||
|
||||
impl Harmonic {
|
||||
pub fn new(node_id: u16, max_drift_ms: i64) -> Self {
|
||||
Self {
|
||||
clock: Arc::new(Mutex::new(HybridTimestamp::new(0, node_id))),
|
||||
node_id, max_drift_ms,
|
||||
heartbeats: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
pub fn now(&self, physical_now: u64) -> Result<HybridTimestamp, HarmonicError> {
|
||||
let mut clock = self.clock.lock().map_err(|_| HarmonicError::SyncFailed("Lock".into()))?;
|
||||
clock.tick(physical_now);
|
||||
Ok(*clock)
|
||||
}
|
||||
pub fn receive(&self, remote: &HybridTimestamp, physical_now: u64) -> Result<HybridTimestamp, HarmonicError> {
|
||||
let mut clock = self.clock.lock().map_err(|_| HarmonicError::SyncFailed("Lock".into()))?;
|
||||
let drift = physical_now as i64 - remote.physical as i64;
|
||||
if drift.abs() > self.max_drift_ms {
|
||||
return Err(HarmonicError::ClockDrift(format!("{}ms exceeds {}ms", drift, self.max_drift_ms)));
|
||||
}
|
||||
clock.merge(remote, physical_now);
|
||||
Ok(*clock)
|
||||
}
|
||||
pub fn record_heartbeat(&self, node_name: &str, remote_ts: HybridTimestamp, local_now: u64) -> Result<(), HarmonicError> {
|
||||
let drift = local_now as i64 - remote_ts.physical as i64;
|
||||
let record = HeartbeatRecord { node_id: node_name.into(), timestamp: remote_ts, drift_ms: drift, is_alive: drift.abs() < self.max_drift_ms };
|
||||
if let Ok(mut hb) = self.heartbeats.lock() { hb.insert(node_name.into(), record); }
|
||||
Ok(())
|
||||
}
|
||||
pub fn alive_nodes(&self) -> Vec<String> {
|
||||
self.heartbeats.lock().map(|hb| hb.values().filter(|r| r.is_alive).map(|r| r.node_id.clone()).collect()).unwrap_or_default()
|
||||
}
|
||||
pub fn max_drift(&self) -> Result<i64, HarmonicError> {
|
||||
let hb = self.heartbeats.lock().map_err(|_| HarmonicError::SyncFailed("Lock".into()))?;
|
||||
Ok(hb.values().map(|r| r.drift_ms.abs()).max().unwrap_or(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn test_harmonic_time_collision() {
|
||||
// Simulasi Koor (Choir): VVIP A (Singapura, 10ms) dan VVIP B (Eropa, 500ms) bernyanyi bersama.
|
||||
let worst_rtt = 500; // Eropa adalah yang terlambat
|
||||
|
||||
// Server menentukan waktu ledakan absolut (500ms + 50ms = 550ms dari sekarang)
|
||||
let detonation_time = HarmonicClock::calculate_global_detonation_time(worst_rtt);
|
||||
|
||||
// Paket suara Singapura sampai dalam 10ms
|
||||
let packet_sg = HarmonicPacket {
|
||||
payload: vec![1, 2, 3],
|
||||
detonation_timestamp: detonation_time,
|
||||
};
|
||||
|
||||
// Paket suara Eropa sampai dalam 500ms
|
||||
let packet_eu = HarmonicPacket {
|
||||
payload: vec![4, 5, 6],
|
||||
detonation_timestamp: detonation_time,
|
||||
};
|
||||
|
||||
// BUKTI MUTLAK:
|
||||
// Meskipun paket datang di waktu yang sangat jauh berbeda (Selisih 490ms),
|
||||
// Keduanya memiliki takdir waktu ledak yang SAMA PERSIS.
|
||||
assert_eq!(packet_sg.detonation_timestamp, packet_eu.detonation_timestamp);
|
||||
|
||||
println!("TIME COLLISION TEST BERHASIL: Ratusan paket suara telah ditakdirkan untuk meledak di milidetik yang sama secara global.");
|
||||
fn test_hlc_tick() {
|
||||
let h = Harmonic::new(1, 5000);
|
||||
let t1 = h.now(1000).unwrap();
|
||||
let t2 = h.now(1000).unwrap();
|
||||
assert!(t2 > t1); // logical incremented
|
||||
}
|
||||
#[test]
|
||||
fn test_hlc_merge() {
|
||||
let h = Harmonic::new(1, 5000);
|
||||
let remote = HybridTimestamp { physical: 2000, logical: 5, node_id: 2 };
|
||||
let t = h.receive(&remote, 1999).unwrap();
|
||||
assert_eq!(t.physical, 2000);
|
||||
assert!(t.logical > 5);
|
||||
}
|
||||
#[test]
|
||||
fn test_drift_detection() {
|
||||
let h = Harmonic::new(1, 100);
|
||||
let remote = HybridTimestamp { physical: 1000, logical: 0, node_id: 2 };
|
||||
assert!(h.receive(&remote, 2000).is_err()); // 1000ms drift > 100ms limit
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user