feat(scheduler): add durable persistence for cron tasks#120
Merged
Conversation
CronCreate now supports `durable: true` to persist jobs across session restarts. Durable tasks are written atomically to `~/.loopal/sessions/<id>/cron.json` and rehydrated on resume before the cron bridge starts, so the TUI panel sees the restored set immediately. Key properties: - Root agent only — sub-agents keep in-memory schedulers to avoid orphan cron files. - No catch-up: one-shot tasks that missed their window are dropped on load; recurring tasks clamp `last_fired` to `now` so the next tick fires on schedule instead of immediately. - Durable tasks bypass the 3-day lifetime cap — persistence would otherwise silently shed user data every few days. - Corrupt files are quarantined as `cron.json.bad-<ts>` rather than overwritten; if quarantine itself fails, the scheduler latches into a read-only mode so subsequent saves cannot clobber the original. - At-least-once delivery: a crash between fire and save may re-fire a one-shot once on resume — documented in the tool description. Architecture: new `DurableStore` trait + `FileDurableStore` with atomic `.tmp`+rename writes. `CronScheduler::with_store` wires the store; `load_persisted` filters expired / missed / unparsable entries; tick loop saves once per tick with a dirty flag for retry.
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
CronCreategains adurable: boolparameter; durable jobs persist to~/.loopal/sessions/<id>/cron.jsonand rehydrate on session resume.last_firedtonowto avoid immediate "catch-up" fires. Durable tasks are exempt from the 3-day lifetime cap..bad-<ts>) and save failures (dirty-flag retry +store_disabledlatch if quarantine itself fails).Changes
loopal-scheduler(newpersistence.rs/persistence_file.rs/scheduler_persistence.rs/id.rs):DurableStoretrait +FileDurableStorewith atomic.tmp+rename writes.CronScheduler::with_store(...)+load_persisted()with filter/clamp/truncate/dedup rules.dirtyflag enables retry.loopal-agent-server(agent_setup.rs/session_start.rs): wiresFileDurableStoreonly for root agents (depth=0);load_persistedruns beforecron_bridge::spawnon resume.loopal-agent(tools/cron.rs):CronCreateschema + description updated withdurableparam and at-least-once note.loopal-protocol(cron_snapshot.rs):CronJobSnapshot.durablewith#[serde(default)]for backward compat.loopal-agent-server/cron_bridge.rs:CronIdentity+to_snapshotcarrydurablethrough to the TUI.Test plan
cron_resume_e2e_test): real IPC server + seedcron.json→ resume →CronsChangedcarries rehydrated task withdurable=true