mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: improve build deadline code (#19203)
- Adds/improves a lot of comments to make the autostop calculation code clearer - Changes the behavior of the enterprise template schedule store to match the behavior of the workspace TTL endpoint when the new TTL is zero - Fixes a bug in the workspace TTL endpoint where it could unset the build deadline, even though a max_deadline was specified - Adds a new constraint to the workspace_builds table that enforces the deadline is non-zero and below the max_deadline if it is set - Adds CHECK constraint enum generation to scripts/dbgen, used for testing the above constraint - Adds Dean and Danielle as CODEOWNERS for the autostop calculation code
This commit is contained in:
+71
-47
@@ -50,8 +50,19 @@ type CalculateAutostopParams struct {
|
||||
// by autobuild.NextAutostart
|
||||
WorkspaceAutostart string
|
||||
|
||||
Now time.Time
|
||||
Workspace database.WorkspaceTable
|
||||
// WorkspaceBuildCompletedAt is the time when the workspace build was
|
||||
// completed.
|
||||
//
|
||||
// We always want to calculate using the build completion time, and not just
|
||||
// the current time, to avoid forcing a workspace build's max_deadline being
|
||||
// pushed to the next potential cron instance.
|
||||
//
|
||||
// E.g. if this function is called for an existing workspace build, which
|
||||
// currently has a max_deadline within the next 2 hours (see leeway
|
||||
// above), and the current time is passed into this function, the
|
||||
// max_deadline will be updated to be much later than expected.
|
||||
WorkspaceBuildCompletedAt time.Time
|
||||
Workspace database.WorkspaceTable
|
||||
}
|
||||
|
||||
type AutostopTime struct {
|
||||
@@ -68,8 +79,8 @@ type AutostopTime struct {
|
||||
// Deadline is the time when the workspace will be stopped, as long as it
|
||||
// doesn't see any new activity (such as SSH, app requests, etc.). When activity
|
||||
// is detected the deadline is bumped by the workspace's TTL (this only happens
|
||||
// when activity is detected and more than 20% of the TTL has passed to save
|
||||
// database queries).
|
||||
// when activity is detected and more than 5% of the TTL has passed to save
|
||||
// database queries, see the ActivityBumpWorkspace query).
|
||||
//
|
||||
// MaxDeadline is the maximum value for deadline. The deadline cannot be bumped
|
||||
// past this value, so it denotes the absolute deadline that the workspace build
|
||||
@@ -77,55 +88,45 @@ type AutostopTime struct {
|
||||
// requirement" settings and the user's "quiet hours" settings to pick a time
|
||||
// outside of working hours.
|
||||
//
|
||||
// Deadline is a cost saving measure, while max deadline is a
|
||||
// compliance/updating measure.
|
||||
// Note that the deadline is checked at the database level:
|
||||
//
|
||||
// (deadline IS NOT zero AND deadline <= max_deadline) UNLESS max_deadline is zero.
|
||||
//
|
||||
// Deadline is intended as a cost saving measure, not as a hard policy. It is
|
||||
// derived from either the workspace's TTL or the template's TTL, depending on
|
||||
// the template's policy, to ensure workspaces are stopped when they are idle.
|
||||
//
|
||||
// MaxDeadline is intended as a compliance policy. It is derived from the
|
||||
// template's autostop requirement to cap workspace uptime and effectively force
|
||||
// people to update often.
|
||||
//
|
||||
// Note that only the build's CURRENT deadline property influences automation in
|
||||
// the autobuild package. As stated above, the MaxDeadline property is only used
|
||||
// to cap the value of a build's deadline.
|
||||
func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (AutostopTime, error) {
|
||||
ctx, span := tracing.StartSpan(ctx,
|
||||
trace.WithAttributes(attribute.String("coder.workspace_id", params.Workspace.ID.String())),
|
||||
trace.WithAttributes(attribute.String("coder.template_id", params.Workspace.TemplateID.String())),
|
||||
)
|
||||
defer span.End()
|
||||
defer span.End()
|
||||
|
||||
var (
|
||||
db = params.Database
|
||||
workspace = params.Workspace
|
||||
now = params.Now
|
||||
db = params.Database
|
||||
workspace = params.Workspace
|
||||
buildCompletedAt = params.WorkspaceBuildCompletedAt
|
||||
|
||||
autostop AutostopTime
|
||||
)
|
||||
|
||||
var ttl time.Duration
|
||||
if workspace.Ttl.Valid {
|
||||
// When the workspace is made it copies the template's TTL, and the user
|
||||
// can unset it to disable it (unless the template has
|
||||
// UserAutoStopEnabled set to false, see below).
|
||||
ttl = time.Duration(workspace.Ttl.Int64)
|
||||
}
|
||||
|
||||
if workspace.Ttl.Valid {
|
||||
// When the workspace is made it copies the template's TTL, and the user
|
||||
// can unset it to disable it (unless the template has
|
||||
// UserAutoStopEnabled set to false, see below).
|
||||
autostop.Deadline = now.Add(time.Duration(workspace.Ttl.Int64))
|
||||
}
|
||||
|
||||
templateSchedule, err := params.TemplateScheduleStore.Get(ctx, db, workspace.TemplateID)
|
||||
if err != nil {
|
||||
return autostop, xerrors.Errorf("get template schedule options: %w", err)
|
||||
}
|
||||
if !templateSchedule.UserAutostopEnabled {
|
||||
// The user is not permitted to set their own TTL, so use the template
|
||||
// default.
|
||||
ttl = 0
|
||||
if templateSchedule.DefaultTTL > 0 {
|
||||
ttl = templateSchedule.DefaultTTL
|
||||
}
|
||||
}
|
||||
|
||||
ttl := workspaceTTL(workspace, templateSchedule)
|
||||
if ttl > 0 {
|
||||
// Only apply non-zero TTLs.
|
||||
autostop.Deadline = now.Add(ttl)
|
||||
autostop.Deadline = buildCompletedAt.Add(ttl)
|
||||
if params.WorkspaceAutostart != "" {
|
||||
// If the deadline passes the next autostart, we need to extend the deadline to
|
||||
// autostart + deadline. ActivityBumpWorkspace already covers this case
|
||||
@@ -137,14 +138,14 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// 3. User starts workspace at 9:45pm.
|
||||
// - The initial deadline is calculated to be 9:45am
|
||||
// - This crosses the autostart deadline, so the deadline is extended to 9pm
|
||||
nextAutostart, ok := NextAutostart(params.Now, params.WorkspaceAutostart, templateSchedule)
|
||||
nextAutostart, ok := NextAutostart(params.WorkspaceBuildCompletedAt, params.WorkspaceAutostart, templateSchedule)
|
||||
if ok && autostop.Deadline.After(nextAutostart) {
|
||||
autostop.Deadline = nextAutostart.Add(ttl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use the autostop_requirement algorithm.
|
||||
// Enforce the template autostop requirement if it's configured correctly.
|
||||
if templateSchedule.AutostopRequirement.DaysOfWeek != 0 {
|
||||
// The template has a autostop requirement, so determine the max deadline
|
||||
// of this workspace build.
|
||||
@@ -161,10 +162,10 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// workspace.
|
||||
if userQuietHoursSchedule.Schedule != nil {
|
||||
loc := userQuietHoursSchedule.Schedule.Location()
|
||||
now := now.In(loc)
|
||||
buildCompletedAtInLoc := buildCompletedAt.In(loc)
|
||||
// Add the leeway here so we avoid checking today's quiet hours if
|
||||
// the workspace was started <1h before midnight.
|
||||
startOfStopDay := truncateMidnight(now.Add(autostopRequirementLeeway))
|
||||
startOfStopDay := truncateMidnight(buildCompletedAtInLoc.Add(autostopRequirementLeeway))
|
||||
|
||||
// If the template schedule wants to only autostop on n-th weeks
|
||||
// then change the startOfDay to be the Monday of the next
|
||||
@@ -183,7 +184,7 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// hour of the scheduled stop time will always bounce to the next
|
||||
// stop window).
|
||||
checkSchedule := userQuietHoursSchedule.Schedule.Next(startOfStopDay.Add(autostopRequirementBuffer))
|
||||
if checkSchedule.Before(now.Add(autostopRequirementLeeway)) {
|
||||
if checkSchedule.Before(buildCompletedAtInLoc.Add(autostopRequirementLeeway)) {
|
||||
// Set the first stop day we try to tomorrow because today's
|
||||
// schedule is too close to now or has already passed.
|
||||
startOfStopDay = nextDayMidnight(startOfStopDay)
|
||||
@@ -213,14 +214,17 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
startOfStopDay = nextDayMidnight(startOfStopDay)
|
||||
}
|
||||
|
||||
// If the startOfDay is within an hour of now, then we add an hour.
|
||||
// If the startOfDay is within an hour of the build completion time,
|
||||
// then we add an hour.
|
||||
checkTime := startOfStopDay
|
||||
if checkTime.Before(now.Add(time.Hour)) {
|
||||
checkTime = now.Add(time.Hour)
|
||||
if checkTime.Before(buildCompletedAtInLoc.Add(time.Hour)) {
|
||||
checkTime = buildCompletedAtInLoc.Add(time.Hour)
|
||||
} else {
|
||||
// If it's not within an hour of now, subtract 15 minutes to
|
||||
// give a little leeway. This prevents skipped stop events
|
||||
// because autostart perfectly lines up with autostop.
|
||||
// If it's not within an hour of the build completion time,
|
||||
// subtract 15 minutes to give a little leeway. This prevents
|
||||
// skipped stop events because the build time (e.g. autostart
|
||||
// time) perfectly lines up with the max_deadline minus the
|
||||
// leeway.
|
||||
checkTime = checkTime.Add(autostopRequirementBuffer)
|
||||
}
|
||||
|
||||
@@ -238,15 +242,35 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
autostop.Deadline = autostop.MaxDeadline
|
||||
}
|
||||
|
||||
if (!autostop.Deadline.IsZero() && autostop.Deadline.Before(now)) || (!autostop.MaxDeadline.IsZero() && autostop.MaxDeadline.Before(now)) {
|
||||
if (!autostop.Deadline.IsZero() && autostop.Deadline.Before(buildCompletedAt)) || (!autostop.MaxDeadline.IsZero() && autostop.MaxDeadline.Before(buildCompletedAt)) {
|
||||
// Something went wrong with the deadline calculation, so we should
|
||||
// bail.
|
||||
return autostop, xerrors.Errorf("deadline calculation error, computed deadline or max deadline is in the past for workspace build: deadline=%q maxDeadline=%q now=%q", autostop.Deadline, autostop.MaxDeadline, now)
|
||||
return autostop, xerrors.Errorf("deadline calculation error, computed deadline or max deadline is in the past for workspace build: deadline=%q maxDeadline=%q now=%q", autostop.Deadline, autostop.MaxDeadline, buildCompletedAt)
|
||||
}
|
||||
|
||||
return autostop, nil
|
||||
}
|
||||
|
||||
// workspaceTTL returns the TTL to use for a workspace.
|
||||
//
|
||||
// If the template forbids custom workspace TTLs, then we always use the
|
||||
// template's configured TTL (or 0 if the template has no TTL configured).
|
||||
func workspaceTTL(workspace database.WorkspaceTable, templateSchedule TemplateScheduleOptions) time.Duration {
|
||||
// If the template forbids custom workspace TTLs, then we always use the
|
||||
// template's configured TTL (or 0 if the template has no TTL configured).
|
||||
if !templateSchedule.UserAutostopEnabled {
|
||||
// This is intentionally a nested if statement because of the else if.
|
||||
if templateSchedule.DefaultTTL > 0 {
|
||||
return templateSchedule.DefaultTTL
|
||||
}
|
||||
return 0
|
||||
}
|
||||
if workspace.Ttl.Valid {
|
||||
return time.Duration(workspace.Ttl.Int64)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// truncateMidnight truncates a time to midnight in the time object's timezone.
|
||||
// t.Truncate(24 * time.Hour) truncates based on the internal time and doesn't
|
||||
// factor daylight savings properly.
|
||||
|
||||
@@ -76,8 +76,8 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
t.Log("saturdayMidnightAfterDstOut", saturdayMidnightAfterDstOut)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
now time.Time
|
||||
name string
|
||||
buildCompletedAt time.Time
|
||||
|
||||
wsAutostart string
|
||||
templateAutoStart schedule.TemplateAutostartRequirement
|
||||
@@ -98,7 +98,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "OK",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -108,7 +108,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -118,7 +118,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTL",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -128,7 +128,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateDefaultTTLIgnored",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -138,7 +138,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 2 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -148,7 +148,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateBlockWorkspaceTTL",
|
||||
now: now,
|
||||
buildCompletedAt: now,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
@@ -158,7 +158,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirement",
|
||||
now: wednesdayMidnightUTC,
|
||||
buildCompletedAt: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -172,7 +172,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirement1HourSkip",
|
||||
now: saturdayMidnightSydney.Add(-59 * time.Minute),
|
||||
buildCompletedAt: saturdayMidnightSydney.Add(-59 * time.Minute),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -188,7 +188,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// The next autostop requirement should be skipped if the
|
||||
// workspace is started within 1 hour of it.
|
||||
name: "TemplateAutostopRequirementDaily",
|
||||
now: fridayEveningSydney,
|
||||
buildCompletedAt: fridayEveningSydney,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -202,7 +202,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirementFortnightly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
buildCompletedAt: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -216,7 +216,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirementFortnightly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
buildCompletedAt: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -230,7 +230,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirementTriweekly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
buildCompletedAt: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -246,7 +246,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirementTriweekly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
buildCompletedAt: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -262,7 +262,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
name: "TemplateAutostopRequirementOverridesWorkspaceTTL",
|
||||
// now doesn't have to be UTC, but it helps us ensure that
|
||||
// timezones are compared correctly in this test.
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
buildCompletedAt: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -276,7 +276,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "TemplateAutostopRequirementOverridesTemplateDefaultTTL",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
buildCompletedAt: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -293,7 +293,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// The epoch is 2023-01-02 in each timezone. We set the time to
|
||||
// 1 second before 11pm the previous day, as this is the latest time
|
||||
// we allow due to our 2h leeway logic.
|
||||
now: time.Date(2023, 1, 1, 21, 59, 59, 0, sydneyLoc),
|
||||
buildCompletedAt: time.Date(2023, 1, 1, 21, 59, 59, 0, sydneyLoc),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -306,7 +306,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "DaylightSavings/OK",
|
||||
now: duringDst,
|
||||
buildCompletedAt: duringDst,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -320,7 +320,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "DaylightSavings/SwitchMidWeek/In",
|
||||
now: beforeDstIn,
|
||||
buildCompletedAt: beforeDstIn,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -334,7 +334,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "DaylightSavings/SwitchMidWeek/Out",
|
||||
now: beforeDstOut,
|
||||
buildCompletedAt: beforeDstOut,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
@@ -348,7 +348,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "DaylightSavings/QuietHoursFallsOnDstSwitch/In",
|
||||
now: beforeDstIn.Add(-24 * time.Hour),
|
||||
buildCompletedAt: beforeDstIn.Add(-24 * time.Hour),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstInQuietHours,
|
||||
@@ -362,7 +362,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "DaylightSavings/QuietHoursFallsOnDstSwitch/Out",
|
||||
now: beforeDstOut.Add(-24 * time.Hour),
|
||||
buildCompletedAt: beforeDstOut.Add(-24 * time.Hour),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstOutQuietHours,
|
||||
@@ -382,7 +382,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// activity on the workspace.
|
||||
name: "AutostopCrossAutostartBorder",
|
||||
// Starting at 9:45pm, with the autostart at 9am.
|
||||
now: pastDateNight,
|
||||
buildCompletedAt: pastDateNight,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: time.Hour * 12,
|
||||
workspaceTTL: time.Hour * 12,
|
||||
@@ -405,7 +405,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// Same as AutostopCrossAutostartBorder, but just misses the autostart.
|
||||
name: "AutostopCrossMissAutostartBorder",
|
||||
// Starting at 8:45pm, with the autostart at 9am.
|
||||
now: time.Date(pastDateNight.Year(), pastDateNight.Month(), pastDateNight.Day(), 20, 30, 0, 0, chicago),
|
||||
buildCompletedAt: time.Date(pastDateNight.Year(), pastDateNight.Month(), pastDateNight.Day(), 20, 30, 0, 0, chicago),
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: time.Hour * 12,
|
||||
workspaceTTL: time.Hour * 12,
|
||||
@@ -429,7 +429,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// The autostop deadline is before the autostart threshold.
|
||||
name: "AutostopCrossAutostartBorderMaxEarlyDeadline",
|
||||
// Starting at 9:45pm, with the autostart at 9am.
|
||||
now: pastDateNight,
|
||||
buildCompletedAt: pastDateNight,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: time.Hour * 12,
|
||||
workspaceTTL: time.Hour * 12,
|
||||
@@ -459,7 +459,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
// So the deadline is > 12 hours, but stops at the max deadline.
|
||||
name: "AutostopCrossAutostartBorderMaxDeadline",
|
||||
// Starting at 9:45pm, with the autostart at 9am.
|
||||
now: pastDateNight,
|
||||
buildCompletedAt: pastDateNight,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: time.Hour * 12,
|
||||
workspaceTTL: time.Hour * 12,
|
||||
@@ -571,7 +571,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
Database: db,
|
||||
TemplateScheduleStore: templateScheduleStore,
|
||||
UserQuietHoursScheduleStore: userQuietHoursScheduleStore,
|
||||
Now: c.now,
|
||||
WorkspaceBuildCompletedAt: c.buildCompletedAt,
|
||||
Workspace: workspace,
|
||||
WorkspaceAutostart: c.wsAutostart,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user