huskies: merge 491_story_watcher_fires_on_crdt_state_transitions_instead_of_filesystem_events
This commit is contained in:
+31
-18
@@ -302,25 +302,11 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the CRDT state layer backed by SQLite.
|
||||
// Uses the same pipeline.db file — the crdt_ops table lives alongside
|
||||
// the legacy pipeline_items table.
|
||||
let crdt_db_path = app_state
|
||||
.project_root
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.map(|root| root.join(".huskies").join("pipeline.db"));
|
||||
// TODO(491): Initialise CRDT state layer once the watcher story lands.
|
||||
// if let Some(db_path) = crdt_db_path
|
||||
// && let Err(e) = db::crdt::init(&db_path).await
|
||||
// {
|
||||
// slog!("[crdt] Failed to initialise CRDT state layer: {e}");
|
||||
// }
|
||||
// (CRDT state layer is initialised above alongside the legacy pipeline.db.)
|
||||
|
||||
let workflow = Arc::new(std::sync::Mutex::new(WorkflowState::default()));
|
||||
|
||||
// Filesystem watcher: broadcast channel for work/ pipeline changes.
|
||||
// Event bus: broadcast channel for pipeline lifecycle events.
|
||||
// Created before AgentPool so the pool can emit AgentStateChanged events.
|
||||
let (watcher_tx, _) = broadcast::channel::<io::watcher::WatcherEvent>(1024);
|
||||
let agents = Arc::new(AgentPool::new(port, watcher_tx.clone()));
|
||||
@@ -329,6 +315,10 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
// When orphans are found, auto-assign is triggered to reassign free agents.
|
||||
let watchdog_root: Option<PathBuf> = app_state.project_root.lock().unwrap().clone();
|
||||
AgentPool::spawn_watchdog(Arc::clone(&agents), watchdog_root);
|
||||
|
||||
// Filesystem watcher: only watches config files (project.toml, agents.toml) and
|
||||
// handles the sweep of done→archived. Work-item pipeline events are now driven
|
||||
// by CRDT state transitions via crdt_state::subscribe().
|
||||
if let Some(ref root) = *app_state.project_root.lock().unwrap() {
|
||||
let work_dir = root.join(".huskies").join("work");
|
||||
if work_dir.is_dir() {
|
||||
@@ -339,8 +329,31 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge CRDT state-transition events to the watcher broadcast channel.
|
||||
// This replaces the filesystem watcher as the source of WorkItem events.
|
||||
{
|
||||
let crdt_watcher_tx = watcher_tx.clone();
|
||||
if let Some(mut crdt_rx) = crdt_state::subscribe() {
|
||||
tokio::spawn(async move {
|
||||
while let Ok(evt) = crdt_rx.recv().await {
|
||||
let (action, commit_msg) =
|
||||
io::watcher::stage_metadata(&evt.to_stage, &evt.story_id)
|
||||
.unwrap_or(("update", format!("huskies: update {}", evt.story_id)));
|
||||
let watcher_evt = io::watcher::WatcherEvent::WorkItem {
|
||||
stage: evt.to_stage,
|
||||
item_id: evt.story_id,
|
||||
action: action.to_string(),
|
||||
commit_msg,
|
||||
from_stage: evt.from_stage,
|
||||
};
|
||||
let _ = crdt_watcher_tx.send(watcher_evt);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to watcher events so that auto-assign triggers when a work item
|
||||
// file is moved into an active pipeline stage (2_current/, 3_qa/, 4_merge/).
|
||||
// enters an active pipeline stage (2_current/, 3_qa/, 4_merge/).
|
||||
{
|
||||
let watcher_auto_rx = watcher_tx.subscribe();
|
||||
let watcher_auto_agents = Arc::clone(&agents);
|
||||
@@ -353,7 +366,7 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
&& matches!(stage.as_str(), "2_current" | "3_qa" | "4_merge")
|
||||
{
|
||||
slog!(
|
||||
"[auto-assign] Watcher detected work item in {stage}/; \
|
||||
"[auto-assign] CRDT transition detected in {stage}/; \
|
||||
triggering auto-assign."
|
||||
);
|
||||
watcher_auto_agents.auto_assign_available_work(&root).await;
|
||||
|
||||
Reference in New Issue
Block a user