feat: add scheduled and recurring job support - #112
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
7a705f1 to
0811d13
Compare
| CRD_GROUP, CRD_VERSION, namespace, "fournosjobs", child_body, | ||
| ) | ||
| child_name = created["metadata"]["name"] | ||
| patch.status["lastScheduledTime"] = now.strftime("%Y-%m-%dT%H:%M:%SZ") |
There was a problem hiding this comment.
maybe an annotation, so that we can wipe it easily to retrigger ?
There was a problem hiding this comment.
forget, status is better
maybe we can have an annotation triggerNow: false that we can edit to triggerNow: true
when the controller sees it, it triggers the job and changes the annotation back to triggerNow: false
| child_spec.pop("schedule", None) | ||
| child_spec.pop("scheduledStartTime", None) | ||
|
|
||
| safe_name = name[:40] |
| try: | ||
| ts = datetime.fromisoformat(raw) | ||
| if ts.tzinfo is None: | ||
| ts = ts.replace(tzinfo=UTC) | ||
| return ts | ||
| except (ValueError, TypeError): | ||
| return None |
There was a problem hiding this comment.
I'm not sure about this silent catch 🤔
should make the fjob FAILED if the timestamp is invalid
25632e0 to
afe62f5
Compare
|
/test ? |
|
/test deploy-fournos-wip |
1 similar comment
|
/test deploy-fournos-wip |
Add two new optional fields to the FournosJob CRD: - `spec.scheduledStartTime` (ISO 8601): defers job execution until a specific time. The job enters a new `Scheduled` phase and the operator transitions it to `Resolving` once the time is reached. When omitted, the job starts immediately (existing behavior unchanged). - `spec.schedule` (cron expression): turns the FournosJob into a recurring template in `Recurring` phase. The operator creates child FournosJob CRs on each cron tick, labeled with `fournos.dev/recurring-parent` for easy querying. Requires the `croniter` dependency. The two fields are mutually exclusive. Both features build on the existing 5-second kopf timer loop — scheduled jobs do a lightweight datetime comparison, recurring jobs use croniter to determine the next fire time. New CRD additions: - spec.scheduledStartTime, spec.schedule - status.lastScheduledTime (for recurring jobs) - Scheduled and Recurring phases - Printer columns for scheduled time and cron expression Co-authored-by: Cursor <cursoragent@cursor.com>
afe62f5 to
2fe3aaf
Compare
|
/test deploy-fournos-wip |
Summary
spec.scheduledStartTime(ISO 8601 datetime) to defer a one-time job execution to a future time. The job enters a newScheduledphase and automatically transitions toResolvingonce the time is reached.spec.schedule(cron expression, e.g.0 20 * * *) to turn a FournosJob into a recurring template. The operator creates child FournosJob CRs on each cron tick, labeled withfournos.dev/recurring-parentfor querying.Changes
manifests/crd.yamlscheduledStartTime,schedule,lastScheduledTimefields;Scheduled/Recurringphases; printer columnsfournos/core/constants.pyPhase.SCHEDULED,Phase.RECURRING,LABEL_RECURRING_PARENTfournos/handlers/lifecycle.pyreconcile_scheduled,reconcile_recurring, scheduling gate inon_create, cron validationfournos/operator.pyScheduled/Recurringto timer filter and reconcile routingfournos/handlers/__init__.pypyproject.tomlcroniter>=5.0dependencyExample: one-time scheduled job
Example: recurring job (every day at 20:00 UTC)
Query all child runs:
kubectl get fjobs -l fournos.dev/recurring-parent=nightly-llm-benchTest plan
scheduledStartTimeorschedule— verify existing behavior unchangedscheduledStartTimeset 1 minute in the future — verify it entersScheduledphase and transitions toResolvingafter the time passesscheduledStartTimein the past — verify it starts immediatelyscheduleexpression — verify it fails with a clear errorscheduledStartTimeandschedule— verify mutual exclusivity validationschedule: "*/1 * * * *"— verify child jobs are created every minute with thefournos.dev/recurring-parentlabelMade with Cursor