Files
codex/prs/bolinfest/study/PR-1827-study.md
2025-09-02 15:17:45 -07:00

2.8 KiB
Raw Blame History

DOs

  • Use a dedicated event variant: Represent expected interruptions with a specific, structured event (not an error), so higher layers decide presentation.
// Good: add a new structured variant
pub enum EventMsg {
    // ...
    TurnInterrupted(TurnInterruptedEvent),
    // ...
}

// Emitting it
self.handle.abort();
let event = Event {
    id: self.sub_id,
    msg: EventMsg::TurnInterrupted(TurnInterruptedEvent { /* fields as needed */ }),
};
let _ = self.sess.tx_event.send(event).await;
  • Let the UI choose how to render: Handle the structured variant in the UI without string checks; update UI state there.
// Good: UI decides presentation for structured event
match event.msg {
    EventMsg::TurnInterrupted(_) => {
        self.add_to_history(HistoryCell::new_background_event("Response interrupted.".into()));
        self.bottom_pane.set_task_running(false);
        self.request_redraw();
    }
    _ => {}
}
  • Preserve event-loop semantics: Keep the receive/forward loop stable; dont introduce adhoc breaks based on particular events.
// Good: forward all events; exit only on channel error or stream end
res = codex.next_event() => match res {
    Ok(event) => {
        debug!("Received event: {event:?}");
        if tx.send(event).is_err() {
            error!("Error sending event");
            break;
        }
        // No special-case break here
    }
    Err(e) => {
        debug!("Event stream ended: {e:?}");
        break;
    }
}
  • Downgrade severity for expected conditions: Use debug! (or lower) when the stream ends in normal/expected scenarios.
// Good: normal termination is not an error
Err(e) => {
    debug!("Event stream ended: {e:?}");
    break;
}

DONTs

  • Dont emit errors for expected interrupts: Avoid EventMsg::Error for user-initiated cancels or routine shutdowns.
// Bad: misclassifies an expected case as an error
let event = Event {
    id: self.sub_id,
    msg: EventMsg::Error(ErrorEvent { message: "Turn interrupted".into() }),
};
  • Dont drive UI logic by string matching: Avoid brittle checks like “contains('Turn interrupted')”.
// Bad: brittle UI logic
if message.contains("Turn interrupted") {
    self.bottom_pane.set_task_running(false);
}
  • Dont change control flow by special-casing events: Breaking on ShutdownComplete (or similar) can be unsafe without a broader audit.
// Bad: ad-hoc control-flow change
if matches!(event.msg, EventMsg::ShutdownComplete) {
    break; // may skip required drains/cleanups
}
  • Dont log normal endings as errors: Reserve error! for genuine failures, not expected stream termination.
// Bad: noisy logging for a normal condition
Err(e) => {
    error!("Error receiving event: {e:?}");
    break;
}