feat(#1086): serialize perm changes through rebuild queue
add QueueKind::PermChange — dashboard tool-group and capability handlers no longer write the shared JSON files inline. instead they enqueue a PermChange entry; the FIFO worker applies the file write then calls rebuild_agent so the updated env var takes effect. concurrent batch-apply actions for different agents previously raced on tool-groups.json / capabilities.json (last write wins, earlier change silently dropped). serialising through the queue prevents this. dedup check extended with perm-type discriminant so tool-groups and capabilities changes for the same agent are kept as distinct entries and never collapse into one slot.
This commit is contained in:
parent
dce2bd0686
commit
eae0e875cf
5 changed files with 127 additions and 27 deletions
|
|
@ -2550,16 +2550,21 @@ async fn post_tool_groups(
|
|||
if let Some(reject) = guard_agent_name(&state, &logical).await {
|
||||
return reject;
|
||||
}
|
||||
if let Err(e) = crate::tool_groups::set_groups(&logical, &body.groups) {
|
||||
return error_response(&format!("set tool-groups for {logical}: {e}"));
|
||||
// Validate group names before queuing — fail fast so the operator
|
||||
// sees the error immediately rather than waiting for the worker.
|
||||
if let Err(e) = crate::tool_groups::validate_groups(&body.groups) {
|
||||
return error_response(&format!("invalid tool-groups for {logical}: {e}"));
|
||||
}
|
||||
// Trigger a rebuild so the new HIVE_TOOL_GROUPS env var takes effect.
|
||||
state.coord.rebuild_queue.enqueue(
|
||||
crate::rebuild_queue::QueueKind::Rebuild,
|
||||
// Enqueue a PermChange so the JSON file write is serialised through
|
||||
// the FIFO worker. Prevents concurrent batch-apply actions for
|
||||
// different agents from racing on the shared tool-groups.json.
|
||||
state.coord.rebuild_queue.enqueue_with_perm(
|
||||
logical.clone(),
|
||||
crate::rebuild_queue::QueueSource::Manual,
|
||||
"tool-group change via permissions UI".to_owned(),
|
||||
None,
|
||||
crate::rebuild_queue::PermPayload::ToolGroups {
|
||||
groups: body.groups.clone(),
|
||||
},
|
||||
);
|
||||
state.coord.emit_rebuild_queue_snapshot();
|
||||
tracing::info!(agent = %logical, groups = ?body.groups, "operator: set tool-groups via dashboard");
|
||||
|
|
@ -2614,16 +2619,16 @@ async fn post_capabilities(
|
|||
return error_response(&format!("unknown capability: {cap}"));
|
||||
}
|
||||
}
|
||||
if let Err(e) = crate::capabilities::set_caps(&logical, &body.caps) {
|
||||
return error_response(&format!("set capabilities for {logical}: {e}"));
|
||||
}
|
||||
// Trigger a rebuild so the new HIVE_CAPABILITIES env var takes effect.
|
||||
state.coord.rebuild_queue.enqueue(
|
||||
crate::rebuild_queue::QueueKind::Rebuild,
|
||||
// Enqueue a PermChange so the JSON file write is serialised through
|
||||
// the FIFO worker. Prevents concurrent batch-apply actions for
|
||||
// different agents from racing on the shared capabilities.json.
|
||||
state.coord.rebuild_queue.enqueue_with_perm(
|
||||
logical.clone(),
|
||||
crate::rebuild_queue::QueueSource::Manual,
|
||||
"capability change via dashboard".to_owned(),
|
||||
None,
|
||||
crate::rebuild_queue::PermPayload::Capabilities {
|
||||
caps: body.caps.clone(),
|
||||
},
|
||||
);
|
||||
state.coord.emit_rebuild_queue_snapshot();
|
||||
tracing::info!(agent = %logical, caps = ?body.caps, "operator: set capabilities via dashboard");
|
||||
|
|
|
|||
Loading…
Reference in a new issue