///|
/// Zenoh-style session/fabric replay for W4B.
///|
pub(all) struct ZenohFabricSessionReport {
seed : Int
axis_id : Int
capabilities : ZenohMirrorCapabilities
fabric_capabilities : @sim.FabricCapabilities
session_trace : @trace.TraceLog
fabric_trace_event_count : Int
session_trace_event_count : Int
partition_count : Int
heal_count : Int
drop_count : Int
late_count : Int
reorder_count : Int
late_delivery_boundary_ns : Int64
liveness_boundary : String
live_interop_evidence : Bool
conformance : @protocol_ast.ConformanceReport
} derive(Debug)
///|
pub fn ZenohFabricSessionReport::passes(
self : ZenohFabricSessionReport,
) -> Bool {
self.conformance.passes() &&
self.conformance.checked_events == 8 &&
self.conformance.matched_steps == 8 &&
self.fabric_capabilities.unlocks_partition_faults() &&
self.partition_count == 1 &&
self.heal_count == 1 &&
self.drop_count == 1 &&
self.late_count == 1 &&
self.reorder_count == 1 &&
self.fabric_trace_event_count > 0 &&
self.session_trace_event_count > self.fabric_trace_event_count &&
self.late_delivery_boundary_ns > 0L &&
!self.live_interop_evidence &&
!self.capabilities.is_hard_realtime_evidence()
}
///|
pub fn zenoh_fabric_session_trace_fixture(
seed? : Int = 44,
axis_id? : Int = 1,
) -> @trace.TraceLog {
let profile_trace = zenoh_cia402_trace_fixture(axis_id~)
let fabric_run = @sim.run_fabric_partition_heal(seed~)
let log = @trace.TraceLog::new()
let mut event_id = 1
for index, event in profile_trace.events {
if index == 3 {
for fabric_event in fabric_run.trace.events {
append_session_envelope_event(log, fabric_event, event_id~, seed~)
event_id += 1
}
}
append_retimed_event(log, event, event_id~, seed~)
event_id += 1
}
log
}
///|
pub fn zenoh_fabric_session_observer_report(
seed? : Int = 44,
axis_id? : Int = 1,
) -> @protocol_ast.ConformanceReport {
zenoh_cia402_observer_backend(axis_id~).check_trace(
zenoh_fabric_session_trace_fixture(seed~, axis_id~),
)
}
///|
pub fn zenoh_fabric_session_report(
seed? : Int = 44,
axis_id? : Int = 1,
) -> ZenohFabricSessionReport {
let fabric_run = @sim.run_fabric_partition_heal(seed~)
let session_trace = zenoh_fabric_session_trace_fixture(seed~, axis_id~)
let conformance = zenoh_cia402_observer_backend(axis_id~).check_trace(
session_trace,
)
{
seed,
axis_id,
capabilities: ZenohMirrorCapabilities::local_non_live(),
fabric_capabilities: fabric_run.capabilities,
session_trace,
fabric_trace_event_count: fabric_run.trace.len(),
session_trace_event_count: session_trace.len(),
partition_count: fabric_run.partition_count,
heal_count: fabric_run.heal_count,
drop_count: fabric_run.drop_count,
late_count: fabric_run.late_count,
reorder_count: fabric_run.reorder_count,
late_delivery_boundary_ns: max_delivery_delay_ns(fabric_run.deliveries),
liveness_boundary: "local replay liveness after partition/heal; no zenoh runtime or transport interop",
live_interop_evidence: false,
conformance,
}
}
///|
fn append_retimed_event(
log : @trace.TraceLog,
event : @trace.TraceEvent,
event_id~ : Int,
seed~ : Int,
) -> Unit {
let time_ns = Int64::from_int(event_id) * 10L
log.append(
@trace.TraceEvent::make(
event_id~,
parent_id=event.parent_id,
vtime=@core.VTime::from_ns(time_ns),
clock_domain="sim",
raw_ns=time_ns,
node_id=event.node_id,
medium_id=event.medium_id,
channel_id=event.channel_id,
direction=event.direction,
payload_digest=event.payload_digest,
rng_step=event_id,
seed~,
backend=@core.SimNative,
label=event.label,
),
)
}
///|
fn append_session_envelope_event(
log : @trace.TraceLog,
event : @trace.TraceEvent,
event_id~ : Int,
seed~ : Int,
) -> Unit {
let direction = match event.label {
"fabric.partition" | "fabric.heal" => @trace.Meta
_ => @trace.Probe
}
let time_ns = Int64::from_int(event_id) * 10L
log.append(
@trace.TraceEvent::make(
event_id~,
parent_id=event.parent_id,
vtime=@core.VTime::from_ns(time_ns),
clock_domain="sim",
raw_ns=time_ns,
node_id="fabric",
medium_id="zenoh.fabric.session",
channel_id=event.channel_id,
direction~,
payload_digest=event.payload_digest,
rng_step=event_id,
seed~,
backend=@core.SimNative,
label="zenoh.session." + event.label,
),
)
}
///|
fn max_delivery_delay_ns(deliveries : Array[@sim.FabricDelivery]) -> Int64 {
let mut max_delay = 0L
for delivery in deliveries {
if delivery.delayed_by.ns() > max_delay {
max_delay = delivery.delayed_by.ns()
}
}
max_delay
}