agents: run cron Scheduler inside the long-running daemon (HIR-119)#10
Merged
agents: run cron Scheduler inside the long-running daemon (HIR-119)#10
Conversation
Spawns a tokio task on `pypes start` that loads every Action::Cron entry across all agents on boot, sleeps until the next due fire, dispatches the wrapped webhook through the existing executor, advances the scheduler, and logs every fire to the daemon's stderr. POST /agents triggers an in-process reload via tokio::sync::Notify so newly stored cron actions go live without restarting the daemon. - src/scheduler_loop.rs: SchedulerHandle + tokio loop with select! over reload signal and Scheduler::next_due - src/server/server.rs: AppState wraps db + SchedulerHandle; serve() spawns the loop before binding the listener - src/server/handler.rs: agents_create signals reload after writes - README: drop the single-process caveat; document automatic firing - CHANGELOG: Unreleased entry - Integration tests use wiremock to assert the loop fires stored cron actions and reloads pick up newly added agents Closes HIR-119. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Collaborator
Author
|
CTO review — see HIR-119 thread for full notes. tl;dr: approved, CI green, ready to merge once Jared manually verifies on his box. Two non-blocking follow-up suggestions captured in the issue thread (CLI mutation reload + scheduler error logging). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pypes startthat loads everyAction::Cronentry across all agents on boot, sleeps until the next due fire, dispatches the wrapped webhook through the existing executor, advances the scheduler, and logs each fire to~/.agents/tmp/daemon.err.POST /agentsnow triggers an in-process scheduler reload viatokio::sync::Notifyso newly stored cron actions go live without restarting the daemon.Closes HIR-119. Follow-up to HIR-118 (#9).
What changed
src/scheduler_loop.rs(new):SchedulerHandle+ tokio loop withselect!overNotify::notified()(reload signal) andScheduler::next_due(). Empty schedule parks onpending::<()>().awaitso reloads still wake it.src/server/server.rs: introducesAppState { db, scheduler };serve()spawns the scheduler loop on the same tokio runtime that hosts axum, before binding the listener.src/server/handler.rs:agents_createcallsstate.scheduler.reload()after the db write.src/lib.rs: re-exportsscheduler_loop.README.md: drops the "single-process / fires only while running" caveat from the## Action Executors → Cronsection and documents that firing happens automatically oncepypes startis up.CHANGELOG.md: Unreleased entry.Tests
cargo test— 21 passed (was 18). Two new wiremock-backed integration tests insrc/scheduler_loop.rs:loop_fires_stored_cron_action_against_mock_receiver— stores an agent with a* * * * * *cron action pointing at a mock, spawns the loop, asserts the mock is hit within 2.5s.reload_picks_up_newly_added_agents— starts with an empty db, confirms no fires, then writes the cron agent + callshandle.reload(), asserts the mock is hit within 2.5s.collect_cron_actions_returns_only_cron_entries_across_all_agents— unit-level coverage for the db walker.Manual verification
Observed log output (excerpt):
Mock receiver got three POSTs spaced one second apart, exactly matching the cron expression.
Out of scope (per ticket)
Utc::now()on boot).pypes add agent,pypes rm agent) — those bypass the daemon process; reload remains scoped to the HTTP API surface as the ticket requested.Test plan
cargo testpasses locallypypes startdaemonized +POST /agentsfires the cron action against a mock receiver and logs each fire to~/.agents/tmp/daemon.errpr_checkworkflow green