diff --git a/pkg/scheduler/catalog/template_sync_task.go b/pkg/scheduler/catalog/template_sync_task.go index 6f7e1bd1a..ec609e033 100644 --- a/pkg/scheduler/catalog/template_sync_task.go +++ b/pkg/scheduler/catalog/template_sync_task.go @@ -77,7 +77,7 @@ func (in *TemplateSyncTask) Process(ctx context.Context, args ...any) error { serr := pkgcatalog.SyncTemplates(ctx, in.modelClient, c) uerr = pkgcatalog.UpdateStatusWithSyncErr( - ctx, + context.Background(), // Make sure status will be updated, in case of task timeout. in.modelClient, c, serr, diff --git a/pkg/settings/modifier.go b/pkg/settings/modifier.go index e1d5143c6..e9f0330a0 100644 --- a/pkg/settings/modifier.go +++ b/pkg/settings/modifier.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "time" imgdistref "github.com/distribution/distribution/reference" @@ -144,6 +145,34 @@ func cronExpression(ctx context.Context, name, oldVal, newVal string) (bool, err return err == nil, err } +// cronAtLeast implements the modifyValidator stereotype, +// which means the value can be modified if it's cron expression and at least the given duration. +// This modifier allows blank new value, +// if not allowed, combine with notBlank. +func cronAtLeast(d time.Duration) modifyValidator { + return func(ctx context.Context, name, oldVal, newVal string) (bool, error) { + // Allow blank, + // combine with notBlank if disallowed. + if newVal == "" { + return true, nil + } + + expr, err := cron.ParseCronExpr(newVal, false) + if err != nil { + return false, err + } + + next := expr.Next(time.Now()) + + duration := expr.Next(next).Sub(next) + if duration < d { + return false, fmt.Errorf("cron expression %q is too short, at least %v", newVal, d) + } + + return true, nil + } +} + // containerImageReference implements the modifyValidator stereotype, // which means the value can be modified if it's container image reference. // This modifier allows blank new value, diff --git a/pkg/settings/settings.go b/pkg/settings/settings.go index 94b886d7e..5d0ce0736 100644 --- a/pkg/settings/settings.go +++ b/pkg/settings/settings.go @@ -1,6 +1,8 @@ package settings import ( + "time" + "k8s.io/utils/pointer" "github.com/seal-io/walrus/pkg/casdoor" @@ -204,12 +206,12 @@ var ( modifyWith(notBlank, cronExpression), ) // CatalogTemplateSyncCronExpr indicates the cron expression of catalog template synchronization event, - // default cron expression means sync at 1 o'clock evey day. + // default cron expression means sync at 1 o'clock evey day, and new cron must be at least 30 minutes. CatalogTemplateSyncCronExpr = newValue( "CatalogTemplateSyncCronExpr", private, initializeFrom("0 0 1 * * *"), - modifyWith(notBlank, cronExpression), + modifyWith(notBlank, cronExpression, cronAtLeast(30*time.Minute)), ) ) diff --git a/pkg/templates/terraform.go b/pkg/templates/terraform.go index 4bba43eb9..f98a3547e 100644 --- a/pkg/templates/terraform.go +++ b/pkg/templates/terraform.go @@ -11,7 +11,6 @@ import ( "sort" "strings" "sync" - "time" "github.com/hashicorp/go-getter" "github.com/hashicorp/go-version" @@ -104,8 +103,7 @@ func (s schemaSyncer) Do(_ context.Context, message template.BusMessage) error { logger := log.WithName("template") gopool.Go(func() { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() + ctx := context.Background() m := message.Refer logger.Debugf("syncing schema for template %s", m.ID) diff --git a/staging/utils/cron/cron.go b/staging/utils/cron/cron.go index 0b53d1351..981bd93dd 100644 --- a/staging/utils/cron/cron.go +++ b/staging/utils/cron/cron.go @@ -216,19 +216,23 @@ func (in *scheduler) Schedule(jobName string, cron Expr, task Task, taskArgs ... return } - const atLeast = 5 * time.Minute + const ( + // The minimum timeout is 5 minutes. + atLeast = 5 * time.Minute + // The maximum timeout is 6 hours. + atMost = 6 * time.Hour + ) var ( now = time.Now() - next = ceParsed.Next(now).Sub(now) + next = ceParsed.Next(now).Sub(now) * 3 ) - if next > atLeast { - next >>= 1 - } - - if next < atLeast { + switch { + case next < atLeast: next = atLeast + case next > atMost: + next = atMost } tt := timeoutTask{