use nemo_flow::api::runtime::current_scope_stack;
use nemo_flow::api::scope::ScopeType;
use uuid::Uuid;
pub const LATENCY_SENSITIVITY_POINTER: &str = "/nemo_flow_adaptive/latency_sensitivity";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SharedParentScopeIdentity {
pub root_uuid: Uuid,
pub shared_parent_uuid: Uuid,
}
pub fn extract_scope_path() -> Vec<String> {
let stack_handle = current_scope_stack();
let stack = match stack_handle.read() {
Ok(s) => s,
Err(_) => return vec![],
};
stack
.scopes()
.iter()
.skip(1) .filter(|s| matches!(s.scope_type, ScopeType::Agent | ScopeType::Function))
.map(|s| s.name.clone())
.collect()
}
pub fn read_manual_latency_sensitivity() -> Option<u32> {
let stack_handle = current_scope_stack();
let stack = match stack_handle.read() {
Ok(s) => s,
Err(_) => return None,
};
let mut max_val: Option<u32> = None;
for scope in stack.scopes() {
if let Some(ref meta) = scope.metadata
&& let Some(val) = meta
.pointer(LATENCY_SENSITIVITY_POINTER)
.and_then(|v| v.as_u64())
{
let val = val as u32;
max_val = Some(max_val.map_or(val, |prev: u32| prev.max(val)));
}
}
max_val
}
pub fn set_latency_sensitivity(value: u32) -> std::result::Result<(), String> {
let stack_handle = current_scope_stack();
let mut stack = stack_handle
.write()
.map_err(|e| format!("scope stack lock poisoned: {e}"))?;
let scope = stack.top_mut();
let existing = scope
.metadata
.as_ref()
.and_then(|m| m.pointer(LATENCY_SENSITIVITY_POINTER))
.and_then(|v| v.as_u64())
.map(|v| v as u32);
let effective = match existing {
Some(prev) if prev >= value => return Ok(()),
_ => value,
};
let meta = scope.metadata.get_or_insert_with(|| serde_json::json!({}));
if let Some(obj) = meta.as_object_mut() {
let nemo_flow_adaptive = obj
.entry("nemo_flow_adaptive")
.or_insert_with(|| serde_json::json!({}));
if let Some(np_obj) = nemo_flow_adaptive.as_object_mut() {
np_obj.insert(
"latency_sensitivity".to_string(),
serde_json::json!(effective),
);
}
}
Ok(())
}
pub fn resolve_agent_id() -> Option<String> {
let stack_handle = current_scope_stack();
let stack = match stack_handle.read() {
Ok(s) => s,
Err(_) => return None,
};
stack
.scopes()
.iter()
.skip(1) .find(|s| matches!(s.scope_type, ScopeType::Agent))
.map(|s| s.name.clone())
}
pub fn resolve_shared_parent_scope_identity() -> Option<SharedParentScopeIdentity> {
let stack_handle = current_scope_stack();
let stack = match stack_handle.read() {
Ok(s) => s,
Err(_) => return None,
};
let root_uuid = stack.root_uuid();
let shared_parent_uuid = stack.top().parent_uuid.unwrap_or(root_uuid);
Some(SharedParentScopeIdentity {
root_uuid,
shared_parent_uuid,
})
}
#[cfg(test)]
#[path = "../tests/unit/context_helpers_tests.rs"]
mod tests;