add reminder delivery timer + main.rs wiring (#2635 inc 1)
This commit is contained in:
parent
92276e4e14
commit
174e277340
2 changed files with 324 additions and 0 deletions
|
|
@ -20,6 +20,7 @@ mod mcp_config;
|
|||
mod paths;
|
||||
mod plugins;
|
||||
mod prompt;
|
||||
mod reminder_timer;
|
||||
mod reminders;
|
||||
mod serve_common;
|
||||
mod stats;
|
||||
|
|
@ -233,6 +234,11 @@ enum RecvOutcome {
|
|||
LocalTodo,
|
||||
}
|
||||
|
||||
/// Reminder fires are pushed as a *real* `DeliveredMessage` (unlike
|
||||
/// `LocalTodo`'s synthetic hint) since the body/id is per-row data the
|
||||
/// producer (`reminder_timer`) already resolved — so the select arm
|
||||
/// wraps it straight into `RecvOutcome::Message`, no dedicated variant.
|
||||
|
||||
/// Wire surface abstraction. `AgentSurface` is the only impl — the trait
|
||||
/// exists to keep the turn loop generic and testable. Every function that
|
||||
/// talks to the broker goes through this so there are zero hard-coded
|
||||
|
|
@ -474,6 +480,22 @@ async fn serve_main<S: Surface>(socket: &Path, poll_ms: u64) -> Result<()> {
|
|||
tracing::error!(error = ?e, "open todos db failed — in-agent todo socket disabled");
|
||||
}
|
||||
}
|
||||
// Harness-local reminders (#2635 increment 1): a due reminder fires
|
||||
// straight into an mpsc channel the serve loop races against the
|
||||
// broker long-poll (unlike todos, a fire carries real per-row data,
|
||||
// so a bare `Notify` doesn't fit — see `reminder_timer` docs).
|
||||
// Best-effort like the todo store above: `reminder_timer::run` parks
|
||||
// forever (never sends) instead of exiting when the store can't
|
||||
// open, so the channel never observes a "closed" state.
|
||||
let (reminder_tx, reminder_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let reminder_store = match reminders::Reminders::open(&paths::reminders_db()) {
|
||||
Ok(store) => Some(Arc::new(store)),
|
||||
Err(e) => {
|
||||
tracing::error!(error = ?e, "open reminders db failed — reminder delivery disabled");
|
||||
None
|
||||
}
|
||||
};
|
||||
tokio::spawn(reminder_timer::run(reminder_store, reminder_tx));
|
||||
if matches!(initial, LoginState::NeedsLogin) {
|
||||
login::wait_for_login(&claude_dir, login_state.clone(), &bus, poll_ms).await;
|
||||
} else {
|
||||
|
|
@ -491,6 +513,7 @@ async fn serve_main<S: Surface>(socket: &Path, poll_ms: u64) -> Result<()> {
|
|||
stats,
|
||||
&files,
|
||||
todo_wake,
|
||||
reminder_rx,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
|
@ -513,6 +536,7 @@ async fn serve_loop<S: Surface>(
|
|||
stats: Option<TurnStats>,
|
||||
files: &turn::TurnFiles,
|
||||
todo_wake: Arc<tokio::sync::Notify>,
|
||||
mut reminder_rx: tokio::sync::mpsc::UnboundedReceiver<hive_sh4re::DeliveredMessage>,
|
||||
) -> Result<()> {
|
||||
tracing::info!(socket = %socket.display(), "harness serve");
|
||||
S::requeue_inflight(socket).await;
|
||||
|
|
@ -537,6 +561,7 @@ async fn serve_loop<S: Surface>(
|
|||
biased;
|
||||
o = S::recv_next(socket) => o,
|
||||
() = todo_wake.notified() => RecvOutcome::LocalTodo,
|
||||
Some(dm) = reminder_rx.recv() => RecvOutcome::Message(dm),
|
||||
}
|
||||
} {
|
||||
RecvOutcome::Message(first) => first,
|
||||
|
|
|
|||
Loading…
Reference in a new issue