fix: fence compaction commit and status

This commit is contained in:
2026-09-16 04:58:38 +09:00
parent c0fe20e8a2
commit cfe772ea7d
6 changed files with 145 additions and 23 deletions
+42 -2
View File
@@ -1403,7 +1403,21 @@ impl App {
}
}
Event::CompactionProgress { compaction } => {
self.compaction_progress = compaction;
self.compaction_progress = compaction.filter(|progress| {
matches!(
(&self.worker_state.state, progress.trigger),
(
protocol::WorkerState::Busy(protocol::WorkerBusyState::Maintenance(
protocol::WorkerMaintenanceState::Compacting
)),
protocol::CompactionTrigger::Manual
) | (
protocol::WorkerState::Busy(protocol::WorkerBusyState::Run(_)),
protocol::CompactionTrigger::PreRun
| protocol::CompactionTrigger::RequestThreshold
)
)
});
}
Event::CompactStart { lifecycle } => {
let should_apply = match &self.active_compaction {
@@ -1522,9 +1536,19 @@ impl App {
Event::WorkerState { snapshot } => {
self.rewind_refresh_fence = false;
self.apply_worker_state_snapshot(&snapshot);
if let Some(progress) = self.compaction_progress.take() {
let _ = self.handle_worker_event(Event::CompactionProgress {
compaction: Some(progress),
});
}
}
Event::CommandAcknowledged { acknowledgement } => {
self.apply_worker_state_snapshot(&acknowledgement.state);
if let Some(progress) = self.compaction_progress.take() {
let _ = self.handle_worker_event(Event::CompactionProgress {
compaction: Some(progress),
});
}
}
// Command telemetry is an operational Web Console surface. The
// TUI continues to render the final Bash ToolResult from history.
@@ -1694,7 +1718,7 @@ impl App {
}
}
self.active_compaction = None;
self.compaction_progress = compaction;
let _ = self.handle_worker_event(Event::CompactionProgress { compaction });
}
fn append_assistant_text(&mut self, text: &str) {
@@ -4299,9 +4323,25 @@ mod completion_flow_tests {
));
}
#[test]
fn compaction_progress_is_hidden_when_worker_state_is_inconsistent() {
let mut app = App::new("test".into());
app.handle_worker_event(Event::CompactionProgress {
compaction: Some(protocol::InFlightCompaction {
phase: protocol::CompactionPhase::Preparing,
started_at_ms: 100,
trigger: protocol::CompactionTrigger::Manual,
}),
});
assert!(app.compaction_progress.is_none());
}
#[test]
fn snapshot_restores_and_runtime_clear_removes_compaction_progress() {
let mut app = App::new("test".into());
app.worker_state.state = protocol::WorkerState::Busy(
protocol::WorkerBusyState::Maintenance(protocol::WorkerMaintenanceState::Compacting),
);
app.apply_in_flight_snapshot(InFlightSnapshot {
compaction: Some(protocol::InFlightCompaction {
phase: protocol::CompactionPhase::Summarizing,
+17 -5
View File
@@ -139,10 +139,17 @@ fn draw_run_status(frame: &mut Frame, app: &App, area: Rect) {
}
fn run_status_line(app: &App, now: Instant) -> Line<'static> {
let elapsed = app
.run_started_at
.and_then(|started_at| now.checked_duration_since(started_at))
.unwrap_or_default();
let elapsed = if let Some(progress) = &app.compaction_progress {
let now_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64;
std::time::Duration::from_millis(now_ms.saturating_sub(progress.started_at_ms))
} else {
app.run_started_at
.and_then(|started_at| now.checked_duration_since(started_at))
.unwrap_or_default()
};
let spinner_index =
((elapsed.as_millis() / RUN_SPINNER_FRAME_MS) as usize) % RUN_SPINNER_FRAMES.len();
let request_label = if app.run_requests == 1 {
@@ -161,8 +168,13 @@ fn run_status_line(app: &App, now: Instant) -> Line<'static> {
Span::raw(" "),
];
if let Some(progress) = &app.compaction_progress {
let phase = match progress.phase {
protocol::CompactionPhase::Preparing => "preparing",
protocol::CompactionPhase::Summarizing => "summarizing",
protocol::CompactionPhase::Committing => "committing",
};
spans.push(Span::styled(
format!("Compacting · {:?}", progress.phase).to_lowercase(),
format!("Compacting · {phase}"),
Style::default().fg(Color::Cyan),
));
spans.push(Span::styled(" | ", Style::default().fg(Color::DarkGray)));