feat: cron arithmetic and persisted workflow schedules

This commit is contained in:
2026-08-04 13:51:10 +01:00
parent b877024365
commit d0e1cc4ad6
5 changed files with 155 additions and 2 deletions
+18
View File
@@ -44,6 +44,20 @@ type StepOverride struct {
SecretRefs []string `bson:"secret_refs,omitempty" json:"secret_refs,omitempty"`
}
type Schedule struct {
Enabled bool `bson:"enabled" json:"enabled"`
Cron string `bson:"cron" json:"cron"` // 5-field: minute hour dom month dow
TZ string `bson:"tz" json:"tz"` // IANA name, e.g. Europe/London
}
// Skip records why an occurrence did not run. Recording a reason nobody reads
// is the same as not recording one, so this is surfaced in the UI.
type Skip struct {
Reason string `bson:"reason" json:"reason"` // "missed" | "already_running"
Due time.Time `bson:"due" json:"due"`
At time.Time `bson:"at" json:"at"`
}
type Workflow struct {
ID bson.ObjectID `bson:"_id,omitempty" json:"-"`
InstanceID string `bson:"instance_id" json:"instance_id"`
@@ -52,6 +66,10 @@ type Workflow struct {
TargetServerIDs []string `bson:"target_server_ids" json:"target_server_ids"`
TargetTags map[string]string `bson:"target_tags,omitempty" json:"target_tags,omitempty"`
Steps []WorkflowStepRef `bson:"steps" json:"steps"`
Schedule *Schedule `bson:"schedule,omitempty" json:"schedule,omitempty"`
NextRunAt *time.Time `bson:"next_run_at,omitempty" json:"next_run_at,omitempty"`
LastRunAt *time.Time `bson:"last_run_at,omitempty" json:"last_run_at,omitempty"`
LastSkipped *Skip `bson:"last_skipped,omitempty" json:"last_skipped,omitempty"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}