Skip to content

feat(cron): add immediate config to control the behaviour on start#461

Merged
jdx merged 1 commit into
jdx:mainfrom
gaojunran:feat-cron-immediate
Jun 4, 2026
Merged

feat(cron): add immediate config to control the behaviour on start#461
jdx merged 1 commit into
jdx:mainfrom
gaojunran:feat-cron-immediate

Conversation

@gaojunran

@gaojunran gaojunran commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

fixes #460

Summary by CodeRabbit

  • New Features

    • Added --cron-immediate flag and cron.immediate configuration option to trigger scheduled cron jobs immediately on daemon startup if scheduled within the last 10 seconds (defaults to false)
  • Documentation

    • Updated CLI command specs, configuration reference, scheduling guide, and JSON schema documentation
  • Tests

    • Added unit tests for the new cron immediate configuration option

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new cron.immediate boolean option to daemon cron configuration. When enabled, cron schedules that would have fired in the 10 seconds before daemon startup trigger immediately upon startup; when disabled (the default), daemons defer to the next scheduled time.

Changes

Cron Immediate Startup Trigger

Layer / File(s) Summary
Cron immediate field definition and serialization
src/config_types.rs, src/daemon.rs
PitchforkTomlCron and Daemon gain an immediate: bool field (default false). Serde support includes proper schema documentation for { schedule, retrigger, immediate } object form and default serialization handling.
CLI argument and command documentation
src/cli/config/add.rs, docs/cli/commands.json, pitchfork.usage.kdl, docs/cli/config/add.md
Add command gains --cron-immediate flag and wires it to the config immediate field. Flag is documented in CLI help metadata and user guide.
Public documentation and reference updates
docs/public/schema.json, docs/reference/configuration.md, docs/guides/scheduling.md
JSON schema, configuration reference, and scheduling guide are updated to document the new immediate option and its startup trigger behavior with examples.
Configuration propagation through state management
src/daemon.rs, src/pitchfork_toml.rs, src/supervisor/state.rs, src/supervisor/lifecycle.rs
cron_immediate flows from TOML config → RunOptions → daemon state persistence, with proper merge semantics during state updates and startup initialization.
Cron triggering behavior for startup
src/supervisor/watchers.rs
check_cron_schedules now conditionally branches on cron_immediate: when true, uses the original 10-second look-back to fire recent schedules; when false, persists last_cron_triggered = now to defer triggering until the next scheduled time.
TUI config editor integration
src/tui/app.rs
Daemon config editor gains a cron_immediate boolean field, with load/save logic to read from and persist to the PitchforkTomlCron struct.
Unit tests for cron immediate parsing
tests/test_pitchfork_toml.rs
New test_daemon_with_cron_immediate verifies TOML parsing with immediate = true; existing cron test now explicitly asserts default immediate = false.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 A cron that wakes and waits no more,
Fires schedules from the startup door!
Immediate, if the flag is set,
Or defers the trigger, need not fret—
The daemon knows its second chance to dance.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main feature addition: a new immediate config option for controlling cron behavior on startup.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an immediate boolean field to cron daemon configuration, letting users control whether a cron fires at startup or strictly waits for the next scheduled time. The default (false) changes the previous always-fire-on-start behaviour.

  • Core fix in watchers.rs: When last_cron_triggered is None and immediate = false, the watcher now anchors last_cron_triggered to now (persisting to state), then continues without triggering — eliminating the previously identified zero-width window where the first cron execution could never occur.
  • immediate = true restores the original 10-second look-back window, so a scheduled time that fell within the 10 s before startup will still fire immediately.
  • The new field is wired end-to-end: TOML parsing, Daemon/RunOptions structs, UpsertDaemonOpts merging, the TUI editor, the config add CLI flag, JSON schema, and docs.

Confidence Score: 5/5

Safe to merge — the end-to-end wiring is complete and the immediate=false anchoring logic correctly prevents the first-tick no-fire regression.

The previously flagged first-tick scheduling problem is properly resolved: set_last_cron_triggered(&id, now) updates in-memory state before continue, so the next watcher tick sees a real timestamp and schedules normally. All struct fields, serialisation, CLI, TUI, and docs paths are consistently updated.

No files require special attention.

Important Files Changed

Filename Overview
src/supervisor/watchers.rs Core cron logic updated: immediate=false now anchors last_cron_triggered to now and continues, correctly fixing the zero-width window problem; immediate=true preserves the 10-second look-back.
src/config_types.rs Adds immediate: bool to PitchforkTomlCron/PitchforkTomlCronRaw, updates is_shorthand to exclude immediate=true from shorthand form, and correctly wires deserialization and serialization paths.
src/daemon.rs Adds cron_immediate: Option<bool> to Daemon and RunOptions; propagated through to_run_options().
src/supervisor/state.rs Adds cron_immediate to UpsertDaemonOpts and merges it with existing state using the same opts.or(existing) pattern as other optional fields.
src/tui/app.rs Adds cron_immediate form field to TUI editor; load/save paths correctly map OptionalBoolean to/from PitchforkTomlCron.immediate.
src/cli/config/add.rs Adds --cron-immediate flag (bool, default false) and passes it into PitchforkTomlCron when building the config.
tests/test_pitchfork_toml.rs Adds a test asserting that cron.immediate = true is parsed correctly; also asserts immediate = false on existing test.
src/pitchfork_toml.rs Threads cron_immediate from PitchforkTomlDaemon to RunOptions via `cron.as_ref().map(

Reviews (2): Last reviewed commit: "feat(cron): add `immediate` config to co..." | Re-trigger Greptile

Comment thread docs/guides/scheduling.md
@gaojunran gaojunran force-pushed the feat-cron-immediate branch from 689fdf9 to 8ac27af Compare June 4, 2026 04:10
@gaojunran gaojunran marked this pull request as ready for review June 4, 2026 14:44

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli/config/add.rs`:
- Around line 123-125: The cron_immediate flag is a no-op unless cron_schedule
is provided; add validation by annotating the cron_immediate field with clap's
requires = "cron_schedule" (e.g., #[clap(long, requires = "cron_schedule")]) and
also add a defensive check in the run() function (or the impl that processes the
parsed args) to return an error or exit early if cron_immediate is true while
cron_schedule is empty, referencing the cron_immediate and cron_schedule fields
and the run() method to ensure both compile-time clap validation and a runtime
fail-fast path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 537ac398-19db-488a-9c58-65be38925a09

📥 Commits

Reviewing files that changed from the base of the PR and between d3680cf and 8ac27af.

📒 Files selected for processing (15)
  • docs/cli/commands.json
  • docs/cli/config/add.md
  • docs/guides/scheduling.md
  • docs/public/schema.json
  • docs/reference/configuration.md
  • pitchfork.usage.kdl
  • src/cli/config/add.rs
  • src/config_types.rs
  • src/daemon.rs
  • src/pitchfork_toml.rs
  • src/supervisor/lifecycle.rs
  • src/supervisor/state.rs
  • src/supervisor/watchers.rs
  • src/tui/app.rs
  • tests/test_pitchfork_toml.rs

Comment thread src/cli/config/add.rs
Comment on lines +123 to +125
/// Trigger cron immediately on first check (default: false)
#[clap(long)]
cron_immediate: bool,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

❓ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Verify that --cron-immediate currently has no declared dependency and is conditionally ignored.
rg -n -C3 'cron_immediate|cron_schedule|PitchforkTomlCron' src/cli/config/add.rs

Repository: endevco/pitchfork

Length of output: 2203


🌐 Web query:

endetvco/pitchfork src/cli/config/add.rs cron_immediate cron_schedule

💡 Result:

In the context of the pitchfork CLI (endevco/pitchfork), cron_immediate and cron_schedule are related to the configuration of daemons managed by the tool. Pitchfork allows users to run daemons on a schedule using cron expressions [1]. While the specific identifiers cron_immediate and cron_schedule do not appear as top-level CLI command flags for pitchfork config add, they correspond to components of the cron configuration within the project configuration file (pitchfork.toml) [2][1]. When configuring a daemon with a cron schedule, the full form of the configuration uses a table containing a schedule field [1]: [daemons.example] run = "./script.sh" cron = { schedule = "0 0 2 * * *", retrigger = "finish" } The configuration logic within the pitchfork codebase handles how these schedules are interpreted and executed. Specifically, the supervisor component of pitchfork includes a Cron Watcher that runs at a configurable interval (defaulting to 10 seconds) to check if any cron-scheduled daemons should be triggered [3][4][5]. The retrigger modes (such as finish, always, success, and fail) define how the system behaves if a scheduled task is triggered while a previous execution is still active [1].

Citations:


🌐 Web query:

endevco/pitchfork "src/cli/config/add.rs" cron_immediate cron_schedule

💡 Result:

In the endevco/pitchfork project, cron scheduling is managed via a configuration field in the daemon definition [1]. While the specific file path src/cli/config/add.rs relates to the CLI command used to add new daemon configurations [2], the core logic for cron scheduling relies on a 'cron' field in the pitchfork.toml file [1]. This 'cron' field accepts either a cron expression string (shorthand) or an inline table (full form) containing a 'schedule' parameter [1]. The 'cron_schedule' terminology is explicitly used in the full form configuration, such as in: [daemons.backup] run = "./scripts/backup.sh" cron = { schedule = "0 0 2 * * *", retrigger = "finish" } Although you mentioned 'cron_immediate', Pitchfork's scheduling documentation primarily emphasizes recurring 'cron' expressions and 'retrigger' modes (such as 'finish', 'always', and 'success') to control daemon execution behavior [1]. The system checks for these scheduled tasks at an interval defined by the 'supervisor.cron_check_interval' setting (defaulting to 10 seconds) [3][4].

Citations:


🌐 Web query:

raw.githubusercontent.com endevco pitchfork src/cli/config/add.rs cron_immediate

💡 Result:

The query “raw.githubusercontent.com endevco pitchfork src/cli/config/add.rs cron_immediate” appears to be looking for Pitchfork source code in endevco/pitchfork (specifically src/cli/config/add.rs) and a symbol/flag named “cron_immediate”. Based on the authoritative sources I found, Pitchfork supports cron scheduling via the daemon configuration field cron = ... and provides cron “retrigger modes” such as finish (default), always, success, and fail (but I did not find any documentation or evidence for a config/CLI option literally named cron_immediate). In particular, the official Pitchfork cron guide describes the cron field and “Retrigger Modes” and does not mention cron_immediate as a mode or flag. [1] I also found official Pitchfork CLI documentation for pitchfork config add, including arguments --cron-schedule and --cron-retrigger, with retrigger behavior restricted to finish, always, success, and fail. This again does not mention any cron_immediate option. [2] So, with high confidence from the cited docs: there is no documented cron_immediate option in the Pitchfork configuration/CLI interface; cron behavior is controlled via --cron-schedule plus --cron-retrigger. [2][1] If you want, paste the exact raw.githubusercontent.com/... URL you expected (or the exact snippet mentioning “cron_immediate”), and I can locate the precise code path/constant for it in the repository.

Citations:


🌐 Web query:

"cron_immediate" "src/cli/config/add.rs" endevco/pitchfork

💡 Result:

The term cron_immediate does not appear to be a standard or public-facing identifier within the endevco/pitchfork project [1][2][3]. While the endevco/pitchfork CLI does provide functionality for managing cron jobs via the pitchfork config add command, its configuration options for cron are documented as --cron-schedule and --cron-retrigger [4]. It is possible that cron_immediate refers to internal source code or a specific private implementation detail within src/cli/config/add.rs that is not exposed in the public documentation or primary API [4][1]. In similar Rust-based scheduling contexts (such as zino-rs), immediate execution flags are sometimes used to run a job immediately upon initialization or scheduling [5][6], but no direct evidence links the specific string cron_immediate to the endevco/pitchfork codebase [4][1][2].

Citations:


🌐 Web query:

"cron-immediate" endevco/pitchfork clap

💡 Result:

The term cron-immediate does not appear to be an official feature, configuration option, or command in the Pitchfork daemon manager [1][2]. Pitchfork is a tool for managing daemons, including support for cron-based scheduling [1][3]. Its documentation defines retrigger modes for cron jobs, which dictate how the supervisor handles a new scheduled run while a previous one is still active [2]. The currently supported retrigger modes are [2]: finish (default): Only triggers a new run if the previous execution has finished [2]. always: Always triggers a new run, stopping the previous one if it is still active [2]. success: Only triggers if the previous execution succeeded (exit code 0) [2]. fail: Only triggers if the previous execution failed [2]. It is possible that "cron-immediate" was a misinterpreted reference to one of these modes (such as "always," which forces execution) or a misunderstanding of how Pitchfork's CLI interface (built with clap) handles task triggering [2][4]. Pitchfork CLI commands are implemented using the Rust clap crate, and interaction with the supervisor is handled via IPC [4][5].

Citations:


🌐 Web query:

"cron_immediate" "clap(" endevco/pitchfork

💡 Result:

The terms "cron_immediate" and "clap(" do not appear as a combined, functional feature within the endevco/pitchfork project [1][2][3]. Pitchfork is a CLI tool for managing daemons and recurring tasks [1][3]. While it does support cron scheduling [1][3] and uses the Rust clap library for its command-line interface [1][3], the specific string "cron_immediate" is not a recognized configuration or command parameter in the project's source code or documentation [1][4][3]. The search results indicate that "cron_immediate" is a parameter used in other software, such as the betterweb/cron Docker container [5], which allows for immediate execution of scheduled jobs. Additionally, "clap(" is a common pattern in Rust codebases when initializing the clap command-line parser [6][7], but it is not a specific identifier associated with a "cron_immediate" feature in pitchfork. If you are seeing these terms in relation to a specific codebase or configuration file, it is possible they originate from a different tool or a misinterpretation of a separate integration [5].

Citations:


Require --cron-schedule when --cron-immediate is set.

Pitchfork’s cron CLI/docs describe cron configuration via --cron-schedule (and retrigger via --cron-retrigger), so if src/cli/config/add.rs exposes --cron-immediate, it should not become an unused/no-op input. Add clap validation (e.g., requires = "cron_schedule" on the argument) and/or fail fast in run() when --cron-immediate is provided without --cron-schedule.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/config/add.rs` around lines 123 - 125, The cron_immediate flag is a
no-op unless cron_schedule is provided; add validation by annotating the
cron_immediate field with clap's requires = "cron_schedule" (e.g., #[clap(long,
requires = "cron_schedule")]) and also add a defensive check in the run()
function (or the impl that processes the parsed args) to return an error or exit
early if cron_immediate is true while cron_schedule is empty, referencing the
cron_immediate and cron_schedule fields and the run() method to ensure both
compile-time clap validation and a runtime fail-fast path.

@jdx jdx merged commit 0d6df2e into jdx:main Jun 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants