Skip to content

Allow fixed calendar time for manual scheduler passes - #156

Merged
senamakel merged 7 commits into
mainfrom
scheduler-clock
Oct 17, 2026
Merged

senamakel merged 7 commits into
mainfrom
scheduler-clock

Conversation

@senamakel

@senamakel senamakel commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

What and why

Manual scheduler passes can now supply StartScheduler.config.now, an RFC3339 calendar instant. Due-job selection, run timestamps, and recurrence use that same instant, allowing hosts and tests to process future schedules without waiting or changing the machine clock. Omitting it preserves system time; automatic poll loops reject a fixed instant.

Schedule contract version 4 advertises this additive setting. Retry sleeps continue to use Tokio timers independently of calendar time.

Validation

  • The new future-job and automatic-loop regressions failed before implementation, then passed.
  • cargo test -p tinyflows-module -p tinyflows-bus: passed (90 tests; the artifact test is separately gated by the existing script).
  • bash scripts/verify-module-artifact.sh: passed, including a fixed-time pass through the compiled dylib and TinyBus.
  • cargo clippy -p tinyflows-module -p tinyflows-bus --all-targets --all-features -- -D warnings: passed.
  • cargo fmt --all -- --check: passed.

Tests cover one-shot due boundaries, recurring next-run calculation, run timestamps, invalid instants, refusal of frozen automatic loops, and Tokio retry sleep with fixed calendar time. Updated the module README and the bus contract documentation.

Summary by CodeRabbit

  • New Features
    • Manual scheduler ticks can now use a specified RFC3339 calendar time to select due jobs, record run timestamps, and calculate the next recurring run. The specified time does not change the system clock; retry delays still use timers.
    • The time defaults to the system clock when omitted. Specifying it for an automatic scheduler loop, or providing an invalid timestamp, returns an error.
  • Documentation
    • Documented the fixed-time option and its requirements, including Schedule contract version 4.

Register a new clock test module and make the shared test state and helpers visible to it. The fake host now records the times it is queried and filters due jobs by enabled flag and next run, and gains a due_jobs_excluding variant so clock-driven scheduling can be exercised.

Auto-committed-on: macbook
Add unit tests covering the schedule clock's timing behaviour so that
future changes to scheduling logic are guarded against regressions.

Auto-committed-on: macbook
Manual schedulers now accept an optional `now` config value that pins calendar time for due selection, run records and rescheduling without touching the machine clock, and automatic loops reject it. The contract version is bumped to 4 to advertise the new option.

Auto-committed-on: macbook
…tants

Extend the manual-tick clock tests so a recurring job is also due at the supplied instant and its next occurrence is computed from that fixed time, and add a test rejecting malformed calendar values. The README now documents the fixed-instant option and its contract version requirement.

Auto-committed-on: macbook
Add a paused-time test asserting that the clock's sleep advances tokio's timer by the requested duration while leaving the calendar instant unchanged. Enable tokio's test-util feature in dev-dependencies so paused time is available.

Auto-committed-on: macbook
Drop the unused `Clock` trait import from the schedule clock tests, since the tests no longer need it in scope.

Auto-committed-on: macbook
The artifact test now supplies a fixed `now` value in the module config and checks that the recorded `started_at` and `finished_at` fields match it, so the test verifies the injected clock is actually used instead of relying on the default empty config.

Auto-committed-on: macbook
@tinysweeper

tinysweeper Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Tiny Sweeper reviewed this change across 5 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below.

State: Incomplete
Priority: none
Reviewed head: c30acbf2f7c2
Updated: 2026-10-17T13:14:02Z

Review snapshot

Change surface Files Review signal Count
Production 3 Active findings 0
Tests 4 Noted findings 0
Documentation 1 Resolved findings 0
Configuration 1 Pending checks/questions 2

Completeness: Incomplete
Test assessment: No supported feature-to-test mapping was available; this does not mean tests are absent or passed.

Features

None identified with supported citations.

Tests

No supported feature-to-test mapping was produced. Test execution is not inferred.

Findings

No active actionable findings.

Could not review: crates/tinyflows-module/README.md, crates/tinyflows-module/tests/module_artifact_tests.rs

Before merge

  • Complete the critique review for crates/tinyflows-module/README.md.
  • Complete the security review for crates/tinyflows-module/tests/module_artifact_tests.rs.

How this fits together

flowchart LR
  n0["StartScheduler<br/>changed"]:::changed
  n1["every<br/>changed"]:::changed
  n2["...dation_without_linking_engine_into_client<br/>changed"]:::changed
  n3["Value"]:::impacted
  n4["...ec_defaults_and_request_types_deserialize"]:::impacted
  n5["connections"]:::impacted
  n6["..._flow_directly_and_preserves_run_identity"]:::impacted
  n7["...uler_lifecycle_uses_module_tick_and_drain"]:::impacted
  n8["Schedule"]:::impacted
  n0 -->|uses| n3
  n1 -->|uses| n8
  n2 -->|uses| n0
  n2 -->|uses| n3
  n3 -->|uses| n8
  n4 -->|calls| n1
  n4 -->|tests| n1
  n6 -->|uses| n3
  n6 -->|calls| n5
  n6 -->|tests| n5
  n7 -->|uses| n0
  n7 -->|calls| n5
  n7 -->|tests| n5
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Success
  • Scope reviewed: incomplete; unanswered: crates/tinyflows-module/README.md
  • Lane summary: Reviewed 8 files; 0 findings. 1 file could not be reviewed: crates/tinyflows-module/README.md. _The code index is behind this pull request (indexed at `f1a1fb262183`), so retrieved context may be out of date._

security

  • Conclusion: Success
  • Scope reviewed: incomplete; unanswered: crates/tinyflows-module/tests/module_artifact_tests.rs
  • Lane summary: Reviewed 7 files; 0 findings. 1 file could not be reviewed: crates/tinyflows-module/tests/module_artifact_tests.rs. 1 file was not security-reviewed: crates/tinyflows-module/README.md (prose or tabular data). _The code index is behind this pull request (indexed at `f1a1fb262183`), so retrieved context may be out of date._

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The change adds a fixed calendar instant (`config.now`) to host-driven manual schedulers, bumping the Schedule contract to version 4, and backs it with tests that pin every claimed property: due-selection at/before the instant, run-record timestamps, recurring rescheduling, refusal for automatic loops, and refusal of malformed `now` values. The tests exercise real behaviour through the bus wire interface and can fail on regression. Repository rules are respected: tests live in `schedule_clock_tests.rs` declared with `#[cfg(test)] #[path = ...]` at the module bottom, no inline test module is added, and the new clock module is small and documented. I found no defect in the changed code. _The code index is behind this pull request (indexed at `f1a1fb262183`), so retrieved context may be out of date._

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The description accurately matches the diff: it adds an optional fixed RFC3339 instant for manual scheduler passes (contract v4), refuses it for automatic loops, keeps retry sleeps on Tokio timers, and documents and tests all of that. The implementation in `start_scheduler` parses `config.now` before `SchedulerConfig`, rejects a fixed instant without `manual_ticks`, and swaps in the `FixedClock` only when supplied — exactly what the PR body claims. No reportable defects found; the change looks sound against the evidence available (the `Clock`/`Ports` plumbing itself was not shown, but the tests exercising due selection, records, invalid instants and the automatic-loop refusal are shown and consistent). _The code index is behind this pull request (indexed at `f1a1fb262183`), so retrieved context may be out of date._
Evidence and run details
  • Models: ladder/vectors-oai3, glm-5.3-flash, , deepseek-v4.1-flash
  • Spend: $0.007904
  • Tokens: 647766 input · 28888 output · 20544 cached · 500 embedding
Head State Pass summary
c30acbf2f7c2 incomplete 0 active finding(s), 0 resolved finding(s) (at 2026-10-17T13:14:02Z)

tinysweeper 0.1.2

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T13:08:40.451322Z c30acbf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a5ecea7d-4147-4047-9345-bbfd3ae67021
📥 Commits

Reviewing files that changed from the base of the PR and between a63b2f5 and c30acbf.

📒 Files selected for processing: 9
  • crates/tinyflows-bus/src/schedule/mod.rs
  • crates/tinyflows-bus/src/schedule/mod_tests.rs
  • crates/tinyflows-module/Cargo.toml
  • crates/tinyflows-module/README.md
  • crates/tinyflows-module/src/schedule_clock.rs
  • crates/tinyflows-module/src/schedule_clock_tests.rs
  • crates/tinyflows-module/src/schedule_service.rs
  • crates/tinyflows-module/src/schedule_service_tests.rs
  • crates/tinyflows-module/tests/module_artifact_tests.rs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

The Schedule contract advances to version 4. Manual schedulers can use an optional configured UTC instant for due-job selection, run timestamps, and rescheduling. Automatic scheduler loops reject this option.

Changes: Fixed-Time Manual Scheduler

Layer / File(s) Summary
Contract and configuration
crates/tinyflows-bus/src/schedule/mod.rs, crates/tinyflows-bus/src/schedule/mod_tests.rs, crates/tinyflows-module/README.md
The Schedule contract version changes to 4. The contract and README describe the optional RFC3339 config.now, its use for manual ticks, and its restriction to manual schedulers.
Fixed clock and scheduler startup
crates/tinyflows-module/src/schedule_service.rs, crates/tinyflows-module/src/schedule_clock.rs
start_scheduler parses config.now as a UTC timestamp. It returns an error for invalid values or when a fixed time is configured without manual ticks. Otherwise, it uses FixedClock, which returns the stored instant while using Tokio timers for sleeps.
Behavior tests and support
crates/tinyflows-module/Cargo.toml, crates/tinyflows-module/src/schedule_clock_tests.rs, crates/tinyflows-module/src/schedule_service_tests.rs, crates/tinyflows-module/tests/module_artifact_tests.rs
Tests cover fixed-clock sleeps, due-job selection, run timestamps, rescheduling, and rejected configurations. Test support tracks jobs and observed times, and Tokio enables test-util for the clock tests.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Host
  participant ScheduleService
  participant ManualScheduler
  participant FixedClock
  participant due_jobs
  Host->>ScheduleService: start_scheduler with config.now and manual_ticks
  ScheduleService->>FixedClock: create with parsed UTC instant
  ManualScheduler->>FixedClock: now()
  FixedClock-->>ManualScheduler: configured instant
  ManualScheduler->>due_jobs: due_jobs(instant)
  due_jobs-->>ManualScheduler: due jobs
Loading
Merge Risk: ⚪ Minimal · up to c30ac

This change adds an optional fixed calendar time for manual scheduler passes. Default behavior is unchanged and automatic loops refuse the option. The supplied context shows no concrete merge-blocking risk.

Security architecture risk: 🔵 Low · up to c30ac

Fixed-time execution is restricted to manual schedulers and retains the existing execution and storage routes. No introduced security defect was established. The main remaining uncertainty is whether deployed hosts appropriately authorize caller-selected scheduling time and handle mixed contract versions.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The new input can make future jobs eligible immediately and influence recurrence and history in the selected store, including jobs that invoke host execution, delivery, or flow triggers. Effective tenant and asset exposure depends on existing bus permissions and callback bindings; the inspected change does not establish a new cross-tenant route.

Trust Boundaries and Controls

  • observed — The new time validation and manual-only guard run before scheduler creation. The service already exposes ExecuteJob with caller-supplied job data and ScheduleStore operations for schedule and history mutation. These preexisting capabilities are counterevidence to treating caller-selected time alone as a newly introduced privilege escalation; deployed per-method authorization remains unverified.

Resilience and Maintainability Implications

  • observed — The module-owned document path claims occurrences before execution using generation, creation identity, execution definition, schedule, and next-run checks. Completion preserves newer generations and does not move next-run backward. These controls are independent of clock expiry. The existing claim-before-execution design can lose an occurrence after interruption, but avoids automatic replay merely because completion persistence failed.

Hardening Proposals

  • proposed — Hosts that delegate manual scheduler access could explicitly authorize calendar-time overrides and distinguish simulated scheduler timestamps from trusted wall-clock audit time. Clients relying on this option could verify version-4 capability before requesting a pass.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 7 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: supporting fixed calendar time for manual scheduler passes.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 7 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit sets the clock just so
For manual ticks to watch jobs grow
The due ones hop into the queue
Their run times match the chosen cue
Tokio sleeps while minutes flow
Then off through clover fields we go!

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

@tinysweeper tinysweeper 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.

tinysweeper found nothing blocking, but could not review everything, so this is not an approval: crates/tinyflows-module/README.md, crates/tinyflows-module/tests/module_artifact_tests.rs.

             $0.0079 · 647,766 in / 28,888 out · 20,544 cached (3%) · ladder/vectors-oai3, glm-5.3-flash, , deepseek-v4.1-flash · 500 embedded
critique:    $0.0037 · 271,907 in / 14,096 out · 0 cached (0%)      · glm-5.3-flash, , deepseek-v4.1-flash
security:    $0.0021 · 274,659 in / 3,917 out  · 18,368 cached (7%) · glm-5.3-flash, deepseek-v4.1-flash
tests:       $0.0016 · 60,692 in  / 7,917 out  · 2,176 cached (4%)  · glm-5.3-flash, deepseek-v4.1-flash
description: $0.0003 · 34,172 in  / 584 out    · 0 cached (0%)      · glm-5.3-flash

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Oct 17, 2026
@senamakel
senamakel merged commit 7e5e091 into main Oct 17, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant