mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: make GetWorkspacesEligibleForTransition return even less false positives (#15594)
Relates to https://github.com/coder/coder/issues/15082 Further to https://github.com/coder/coder/pull/15429, this reduces the amount of false-positives returned by the 'is eligible for autostart' part of the query. We achieve this by calculating the 'next start at' time of the workspace, storing it in the database, and using it in our `GetWorkspacesEligibleForTransition` query. The prior implementation of the 'is eligible for autostart' query would return _all_ workspaces that at some point in the future _might_ be eligible for autostart. This now ensures we only return workspaces that _should_ be eligible for autostart. We also now pass `currentTick` instead of `t` to the `GetWorkspacesEligibleForTransition` query as otherwise we'll have one round of workspaces that are skipped by `isEligibleForTransition` due to `currentTick` being a truncated version of `t`.
This commit is contained in:
@@ -3,9 +3,13 @@ package schedule
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/schedule/cron"
|
||||
)
|
||||
|
||||
var ErrNoAllowedAutostart = xerrors.New("no allowed autostart")
|
||||
|
||||
// NextAutostart takes the workspace and template schedule and returns the next autostart schedule
|
||||
// after "at". The boolean returned is if the autostart should be allowed to start based on the template
|
||||
// schedule.
|
||||
@@ -28,3 +32,19 @@ func NextAutostart(at time.Time, wsSchedule string, templateSchedule TemplateSch
|
||||
|
||||
return zonedTransition, allowed
|
||||
}
|
||||
|
||||
func NextAllowedAutostart(at time.Time, wsSchedule string, templateSchedule TemplateScheduleOptions) (time.Time, error) {
|
||||
next := at
|
||||
|
||||
// Our cron schedules work on a weekly basis, so to ensure we've exhausted all
|
||||
// possible autostart times we need to check up to 7 days worth of autostarts.
|
||||
for next.Sub(at) < 7*24*time.Hour {
|
||||
var valid bool
|
||||
next, valid = NextAutostart(next, wsSchedule, templateSchedule)
|
||||
if valid {
|
||||
return next, nil
|
||||
}
|
||||
}
|
||||
|
||||
return time.Time{}, ErrNoAllowedAutostart
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package schedule_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/schedule"
|
||||
)
|
||||
|
||||
func TestNextAllowedAutostart(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("WhenScheduleOutOfSync", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// 1st January 2024 is a Monday
|
||||
at := time.Date(2024, time.January, 1, 10, 0, 0, 0, time.UTC)
|
||||
// Monday-Friday 9:00AM UTC
|
||||
sched := "CRON_TZ=UTC 00 09 * * 1-5"
|
||||
// Only allow an autostart on mondays
|
||||
opts := schedule.TemplateScheduleOptions{
|
||||
AutostartRequirement: schedule.TemplateAutostartRequirement{
|
||||
DaysOfWeek: 0b00000001,
|
||||
},
|
||||
}
|
||||
|
||||
// NextAutostart will return a non-allowed autostart time as
|
||||
// our AutostartRequirement only allows Mondays but we expect
|
||||
// this to return a Tuesday.
|
||||
next, allowed := schedule.NextAutostart(at, sched, opts)
|
||||
require.False(t, allowed)
|
||||
require.Equal(t, time.Date(2024, time.January, 2, 9, 0, 0, 0, time.UTC), next)
|
||||
|
||||
// NextAllowedAutostart should return the next allowed autostart time.
|
||||
next, err := schedule.NextAllowedAutostart(at, sched, opts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Date(2024, time.January, 8, 9, 0, 0, 0, time.UTC), next)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user