implement scheduler #30

Closed
opened 2026-03-09 04:11:51 +00:00 by despiegk · 2 comments
Owner

start from development_kristof branch
make sure we have all newest changes
then create branch development_cron to further work on

see scheduling capabilities in the schema's

  • use cron & scheduling intervals
  • see the job specs

use https://docs.rs/cron_tab/latest/cron_tab/ to do the execution

start from development_kristof branch make sure we have all newest changes then create branch development_cron to further work on see scheduling capabilities in the schema's - use cron & scheduling intervals - see the job specs use https://docs.rs/cron_tab/latest/cron_tab/ to do the execution
despiegk added this to the now milestone 2026-03-09 04:16:39 +00:00
Author
Owner

Implementation Spec for Issue #30: Implement Scheduler

Objective

Implement a scheduler component in zinit_server that reads SchedulePolicy from ActionSpec definitions and automatically creates jobs based on cron expressions and/or interval timers, using the cron_tab crate.

Requirements

  1. Actions with schedule_policy containing a cron expression trigger job creation at specified times
  2. Actions with interval_ms trigger job creation at the specified interval
  3. start_time and end_time respected as scheduling windows
  4. nr_of_instances limits concurrent running jobs from the same action
  5. Scheduler runs as background async task alongside supervisor
  6. New RPC methods: schedule.list, schedule.status
  7. OpenRPC spec updated
  8. CLI command zinit schedules added

Existing Data Model (Already Present)

SchedulePolicy at crates/zinit_lib/src/db/actions/model.rs:336:

  • nr_of_instances: Option<u8> — max concurrent instances
  • cron: String — cron expression
  • interval_ms: u32 — interval-based scheduling
  • start_time: u32 — window start (Unix epoch, 0=always)
  • end_time: u32 — window end (Unix epoch, 0=forever)

Files to Modify/Create

File Action Purpose
crates/zinit_lib/Cargo.toml Modify Add cron_tab + chrono deps
crates/zinit_server/Cargo.toml Modify Add cron_tab + chrono deps
crates/zinit_server/src/scheduler.rs Create Core scheduling loop
crates/zinit_server/src/lib.rs Modify Register scheduler module
crates/zinit_server/src/main.rs Modify Spawn scheduler task
crates/zinit_server/src/rpc/schedule.rs Create RPC handlers
crates/zinit_server/src/rpc/mod.rs Modify Add dispatch routes
crates/zinit_server/src/web.rs Modify Add positional_to_named
crates/zinit_server/openrpc.json Modify Add schedule methods
crates/zinit_lib/src/db/actions/model.rs Modify Add cron validation
crates/zinit/src/cli/args.rs Modify Add Schedules command
crates/zinit/src/cli/commands.rs Modify Add handler

Implementation Plan

Step 1: Add cron_tab + chrono dependencies

Dependencies: none

Step 2: Add cron validation to SchedulePolicy

  • Validate cron expressions parse correctly
  • Validate time windows
  • Add unit tests
    Dependencies: Step 1

Step 3: Create Scheduler module (scheduler.rs)

  • Scheduler struct with Arc<ZinitDb>
  • ScheduleEntry tracking struct
  • Main async loop polling every 1s
  • Cron evaluation via cron_tab
  • Interval evaluation
  • Job creation for due schedules
  • Respects nr_of_instances cap
    Dependencies: Step 2

Step 4: Register and spawn scheduler in server

  • Add pub mod scheduler; to lib.rs
  • Spawn scheduler task in main.rs alongside supervisor
    Dependencies: Step 3

Step 5: Add RPC handlers (schedule.list, schedule.status)

  • Create rpc/schedule.rs with handlers
  • Register in rpc/mod.rs dispatch
  • Add to positional_to_named in web.rs
    Dependencies: Step 4

Step 6: Update OpenRPC specification

  • Add schedule.list and schedule.status methods
  • Add ScheduleInfo and ScheduleStatus schemas
    Dependencies: Step 5

Step 7: Add integration tests

  • Cron scheduling creates jobs automatically
  • Interval scheduling creates jobs
  • nr_of_instances cap works
  • Time windows respected
    Dependencies: Step 4

Step 8: Add CLI command zinit schedules

  • Add Schedules variant to CLI args
  • Implement handler calling schedule.list RPC
    Dependencies: Step 5

Acceptance Criteria

  • Cron-based scheduling creates jobs at correct times
  • Interval-based scheduling creates jobs at correct intervals
  • nr_of_instances limits concurrent jobs
  • Time windows (start_time/end_time) respected
  • schedule.list RPC returns all scheduled actions
  • schedule.status RPC returns detailed info
  • zinit schedules CLI displays scheduled actions
  • All existing tests pass
  • New tests cover scheduling logic
  • Invalid cron expressions logged and skipped (no crash)

Notes

  • Uses cron_tab crate as requested
  • Scheduler only creates jobs (inserts with phase: Pending). Existing supervisor picks them up.
  • 1-second poll interval (sufficient for cron minute-level granularity)
  • Scheduled jobs tagged with "scheduled" for filtering
  • No DB schema changes needed — SchedulePolicy already in ActionSpec JSON
## Implementation Spec for Issue #30: Implement Scheduler ### Objective Implement a scheduler component in zinit_server that reads `SchedulePolicy` from `ActionSpec` definitions and automatically creates jobs based on cron expressions and/or interval timers, using the `cron_tab` crate. ### Requirements 1. Actions with `schedule_policy` containing a cron expression trigger job creation at specified times 2. Actions with `interval_ms` trigger job creation at the specified interval 3. `start_time` and `end_time` respected as scheduling windows 4. `nr_of_instances` limits concurrent running jobs from the same action 5. Scheduler runs as background async task alongside supervisor 6. New RPC methods: `schedule.list`, `schedule.status` 7. OpenRPC spec updated 8. CLI command `zinit schedules` added ### Existing Data Model (Already Present) `SchedulePolicy` at `crates/zinit_lib/src/db/actions/model.rs:336`: - `nr_of_instances: Option<u8>` — max concurrent instances - `cron: String` — cron expression - `interval_ms: u32` — interval-based scheduling - `start_time: u32` — window start (Unix epoch, 0=always) - `end_time: u32` — window end (Unix epoch, 0=forever) ### Files to Modify/Create | File | Action | Purpose | |------|--------|---------| | `crates/zinit_lib/Cargo.toml` | Modify | Add `cron_tab` + `chrono` deps | | `crates/zinit_server/Cargo.toml` | Modify | Add `cron_tab` + `chrono` deps | | `crates/zinit_server/src/scheduler.rs` | **Create** | Core scheduling loop | | `crates/zinit_server/src/lib.rs` | Modify | Register scheduler module | | `crates/zinit_server/src/main.rs` | Modify | Spawn scheduler task | | `crates/zinit_server/src/rpc/schedule.rs` | **Create** | RPC handlers | | `crates/zinit_server/src/rpc/mod.rs` | Modify | Add dispatch routes | | `crates/zinit_server/src/web.rs` | Modify | Add positional_to_named | | `crates/zinit_server/openrpc.json` | Modify | Add schedule methods | | `crates/zinit_lib/src/db/actions/model.rs` | Modify | Add cron validation | | `crates/zinit/src/cli/args.rs` | Modify | Add Schedules command | | `crates/zinit/src/cli/commands.rs` | Modify | Add handler | ### Implementation Plan #### Step 1: Add `cron_tab` + `chrono` dependencies Dependencies: none #### Step 2: Add cron validation to `SchedulePolicy` - Validate cron expressions parse correctly - Validate time windows - Add unit tests Dependencies: Step 1 #### Step 3: Create Scheduler module (`scheduler.rs`) - `Scheduler` struct with `Arc<ZinitDb>` - `ScheduleEntry` tracking struct - Main async loop polling every 1s - Cron evaluation via `cron_tab` - Interval evaluation - Job creation for due schedules - Respects `nr_of_instances` cap Dependencies: Step 2 #### Step 4: Register and spawn scheduler in server - Add `pub mod scheduler;` to lib.rs - Spawn scheduler task in main.rs alongside supervisor Dependencies: Step 3 #### Step 5: Add RPC handlers (`schedule.list`, `schedule.status`) - Create `rpc/schedule.rs` with handlers - Register in `rpc/mod.rs` dispatch - Add to `positional_to_named` in web.rs Dependencies: Step 4 #### Step 6: Update OpenRPC specification - Add `schedule.list` and `schedule.status` methods - Add `ScheduleInfo` and `ScheduleStatus` schemas Dependencies: Step 5 #### Step 7: Add integration tests - Cron scheduling creates jobs automatically - Interval scheduling creates jobs - `nr_of_instances` cap works - Time windows respected Dependencies: Step 4 #### Step 8: Add CLI command `zinit schedules` - Add `Schedules` variant to CLI args - Implement handler calling `schedule.list` RPC Dependencies: Step 5 ### Acceptance Criteria - [ ] Cron-based scheduling creates jobs at correct times - [ ] Interval-based scheduling creates jobs at correct intervals - [ ] `nr_of_instances` limits concurrent jobs - [ ] Time windows (`start_time`/`end_time`) respected - [ ] `schedule.list` RPC returns all scheduled actions - [ ] `schedule.status` RPC returns detailed info - [ ] `zinit schedules` CLI displays scheduled actions - [ ] All existing tests pass - [ ] New tests cover scheduling logic - [ ] Invalid cron expressions logged and skipped (no crash) ### Notes - Uses `cron_tab` crate as requested - Scheduler only creates jobs (inserts with phase: Pending). Existing supervisor picks them up. - 1-second poll interval (sufficient for cron minute-level granularity) - Scheduled jobs tagged with "scheduled" for filtering - No DB schema changes needed — `SchedulePolicy` already in `ActionSpec` JSON
Author
Owner

Test Results

  • zinit_lib: 136 passed, 0 failed
  • zinit_server: 46 passed, 0 failed (includes 9 new scheduler tests)
  • zinit_sdk: compiles clean
  • zinit_cli: compiles clean
  • Total: 182 passed, 0 failed

New Scheduler Tests (9)

  • test_normalize_cron_5_field — 5-field cron normalization
  • test_normalize_cron_6_field — 6-field cron normalization
  • test_normalize_cron_7_field — 7-field cron passthrough
  • test_cron_parsing_valid — valid cron parsing
  • test_cron_parsing_every_5_minutes — every-5-minutes cron
  • test_cron_parsing_invalid — invalid cron rejection
  • test_schedule_policy_cron_set — cron policy creation
  • test_schedule_policy_interval_set — interval policy creation
  • test_cron_next_from — next cron execution time calculation

Implementation Summary

Files Created (3)

  • crates/zinit_server/src/scheduler.rs — Core scheduler module with 1-second tick loop
  • crates/zinit_server/src/rpc/schedule.rs — RPC handlers for schedule.list and schedule.status

Files Modified (10)

  • Cargo.toml — Added cron_tab, cron, chrono workspace deps
  • crates/zinit_server/Cargo.toml — Added scheduler deps
  • crates/zinit_lib/src/db/actions/model.rs — Added list_actions_with_context()
  • crates/zinit_lib/src/db/factory.rs — Added ActionsApi::list_with_context()
  • crates/zinit_server/src/lib.rs — Registered pub mod scheduler
  • crates/zinit_server/src/main.rs — Spawns scheduler alongside supervisor
  • crates/zinit_server/src/rpc/mod.rs — Added schedule.* dispatch routes
  • crates/zinit_server/src/web.rs — Added positional-to-named param mappings
  • crates/zinit_server/openrpc.json — Added schedule.list, schedule.status methods + schemas
  • crates/zinit/src/cli/args.rs + commands.rs + main.rs — Added zinit schedules CLI command
## Test Results - **zinit_lib**: 136 passed, 0 failed - **zinit_server**: 46 passed, 0 failed (includes 9 new scheduler tests) - **zinit_sdk**: compiles clean - **zinit_cli**: compiles clean - **Total**: 182 passed, 0 failed ### New Scheduler Tests (9) - `test_normalize_cron_5_field` — 5-field cron normalization - `test_normalize_cron_6_field` — 6-field cron normalization - `test_normalize_cron_7_field` — 7-field cron passthrough - `test_cron_parsing_valid` — valid cron parsing - `test_cron_parsing_every_5_minutes` — every-5-minutes cron - `test_cron_parsing_invalid` — invalid cron rejection - `test_schedule_policy_cron_set` — cron policy creation - `test_schedule_policy_interval_set` — interval policy creation - `test_cron_next_from` — next cron execution time calculation ## Implementation Summary ### Files Created (3) - `crates/zinit_server/src/scheduler.rs` — Core scheduler module with 1-second tick loop - `crates/zinit_server/src/rpc/schedule.rs` — RPC handlers for `schedule.list` and `schedule.status` ### Files Modified (10) - `Cargo.toml` — Added `cron_tab`, `cron`, `chrono` workspace deps - `crates/zinit_server/Cargo.toml` — Added scheduler deps - `crates/zinit_lib/src/db/actions/model.rs` — Added `list_actions_with_context()` - `crates/zinit_lib/src/db/factory.rs` — Added `ActionsApi::list_with_context()` - `crates/zinit_server/src/lib.rs` — Registered `pub mod scheduler` - `crates/zinit_server/src/main.rs` — Spawns scheduler alongside supervisor - `crates/zinit_server/src/rpc/mod.rs` — Added `schedule.*` dispatch routes - `crates/zinit_server/src/web.rs` — Added positional-to-named param mappings - `crates/zinit_server/openrpc.json` — Added `schedule.list`, `schedule.status` methods + schemas - `crates/zinit/src/cli/args.rs` + `commands.rs` + `main.rs` — Added `zinit schedules` CLI command
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
geomind_code/zinit_archive2#30
No description provided.