mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
feat(coderd): activity bump for full TTL instead of 1h (#5732)
This commit is contained in:
@ -43,13 +43,29 @@ func activityBumpWorkspace(log slog.Logger, db database.Store, workspaceID uuid.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We sent bumpThreshold slightly under bumpAmount to minimize DB writes.
|
workspace, err := s.GetWorkspaceByID(ctx, workspaceID)
|
||||||
const (
|
if err != nil {
|
||||||
bumpAmount = time.Hour
|
return xerrors.Errorf("get workspace: %w", err)
|
||||||
bumpThreshold = time.Hour - (time.Minute * 10)
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// We bump by the original TTL to prevent counter-intuitive behavior
|
||||||
|
// as the TTL wraps. For example, if I set the TTL to 12 hours, sign off
|
||||||
|
// work at midnight, come back at 10am, I would want another full day
|
||||||
|
// of uptime. In the prior implementation, the workspace would enter
|
||||||
|
// a state of always expiring 1 hour in the future
|
||||||
|
bumpAmount = time.Duration(workspace.Ttl.Int64)
|
||||||
|
// DB writes are expensive so we only bump when 5% of the deadline
|
||||||
|
// has elapsed.
|
||||||
|
bumpEvery = bumpAmount / 20
|
||||||
|
timeSinceLastBump = bumpAmount - time.Until(build.Deadline)
|
||||||
)
|
)
|
||||||
|
|
||||||
if !build.Deadline.Before(time.Now().Add(bumpThreshold)) {
|
if timeSinceLastBump < bumpEvery {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if bumpAmount == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,14 +19,17 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
const ttl = time.Minute
|
||||||
|
|
||||||
setupActivityTest := func(t *testing.T) (client *codersdk.Client, workspace codersdk.Workspace, assertBumped func(want bool)) {
|
setupActivityTest := func(t *testing.T) (client *codersdk.Client, workspace codersdk.Workspace, assertBumped func(want bool)) {
|
||||||
var ttlMillis int64 = 60 * 1000
|
ttlMillis := int64(ttl / time.Millisecond)
|
||||||
|
|
||||||
client = coderdtest.New(t, &coderdtest.Options{
|
client = coderdtest.New(t, &coderdtest.Options{
|
||||||
AppHostname: proxyTestSubdomainRaw,
|
AppHostname: proxyTestSubdomainRaw,
|
||||||
IncludeProvisionerDaemon: true,
|
IncludeProvisionerDaemon: true,
|
||||||
|
// Agent stats trigger the activity bump, so we want to report
|
||||||
|
// very frequently in tests.
|
||||||
AgentStatsRefreshInterval: time.Millisecond * 100,
|
AgentStatsRefreshInterval: time.Millisecond * 100,
|
||||||
MetricsCacheRefreshInterval: time.Millisecond * 100,
|
|
||||||
})
|
})
|
||||||
user := coderdtest.CreateFirstUser(t, client)
|
user := coderdtest.CreateFirstUser(t, client)
|
||||||
|
|
||||||
@ -67,11 +70,11 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return workspace.LatestBuild.Deadline.Time != firstDeadline
|
return workspace.LatestBuild.Deadline.Time != firstDeadline
|
||||||
},
|
},
|
||||||
testutil.WaitShort, testutil.IntervalFast,
|
testutil.WaitLong, testutil.IntervalFast,
|
||||||
"deadline %v never updated", firstDeadline,
|
"deadline %v never updated", firstDeadline,
|
||||||
)
|
)
|
||||||
|
|
||||||
require.WithinDuration(t, database.Now().Add(time.Hour), workspace.LatestBuild.Deadline.Time, 3*time.Second)
|
require.WithinDuration(t, database.Now().Add(ttl), workspace.LatestBuild.Deadline.Time, 3*time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +90,8 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Must send network traffic after a few seconds to surpass bump threshold.
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
sshConn, err := conn.SSHClient(ctx)
|
sshConn, err := conn.SSHClient(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_ = sshConn.Close()
|
_ = sshConn.Close()
|
||||||
|
@ -62,7 +62,7 @@ export const Language = {
|
|||||||
ttlLabel: "Time until shutdown (hours)",
|
ttlLabel: "Time until shutdown (hours)",
|
||||||
ttlCausesShutdownHelperText: "Your workspace will shut down",
|
ttlCausesShutdownHelperText: "Your workspace will shut down",
|
||||||
ttlCausesShutdownAfterStart:
|
ttlCausesShutdownAfterStart:
|
||||||
"after its next start. We delay shutdown by an hour whenever we detect activity",
|
"after its next start. We delay shutdown by this time whenever we detect activity",
|
||||||
ttlCausesNoShutdownHelperText:
|
ttlCausesNoShutdownHelperText:
|
||||||
"Your workspace will not automatically shut down.",
|
"Your workspace will not automatically shut down.",
|
||||||
formTitle: "Workspace schedule",
|
formTitle: "Workspace schedule",
|
||||||
|
Reference in New Issue
Block a user