Skip to content

Commit dcf03d8

Browse files
authored
chore: refactor time.Duration -> int64 milliseconds for FE consumption (#1944)
* Changes all public-facing codersdk types to use a plain int64 (milliseconds) instead of time.Duration. * Makes autostart_schedule a *string as it may not be present. * Adds a utils/ptr package with some useful methods.
1 parent 51c420c commit dcf03d8

24 files changed

+287
-148
lines changed

cli/autostart.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ func autostartShow() *cobra.Command {
5151
return err
5252
}
5353

54-
if workspace.AutostartSchedule == "" {
54+
if workspace.AutostartSchedule == nil || *workspace.AutostartSchedule == "" {
5555
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "not enabled\n")
5656
return nil
5757
}
5858

59-
validSchedule, err := schedule.Weekly(workspace.AutostartSchedule)
59+
validSchedule, err := schedule.Weekly(*workspace.AutostartSchedule)
6060
if err != nil {
6161
// This should never happen.
62-
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "invalid autostart schedule %q for workspace %s: %s\n", workspace.AutostartSchedule, workspace.Name, err.Error())
62+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "invalid autostart schedule %q for workspace %s: %s\n", *workspace.AutostartSchedule, workspace.Name, err.Error())
6363
return nil
6464
}
6565

@@ -110,7 +110,7 @@ func autostartEnable() *cobra.Command {
110110
}
111111

112112
err = client.UpdateWorkspaceAutostart(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
113-
Schedule: validSchedule.String(),
113+
Schedule: &spec,
114114
})
115115
if err != nil {
116116
return err
@@ -153,7 +153,7 @@ func autostartDisable() *cobra.Command {
153153
}
154154

155155
err = client.UpdateWorkspaceAutostart(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
156-
Schedule: "",
156+
Schedule: nil,
157157
})
158158
if err != nil {
159159
return err

cli/autostart_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/coder/coder/cli/clitest"
1313
"github.com/coder/coder/coderd/coderdtest"
14+
"github.com/coder/coder/coderd/util/ptr"
1415
"github.com/coder/coder/codersdk"
1516
)
1617

@@ -34,7 +35,7 @@ func TestAutostart(t *testing.T) {
3435
)
3536

3637
err := client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
37-
Schedule: sched,
38+
Schedule: ptr.Ref(sched),
3839
})
3940
require.NoError(t, err)
4041

@@ -76,7 +77,7 @@ func TestAutostart(t *testing.T) {
7677
// Ensure autostart schedule updated
7778
updated, err := client.Workspace(ctx, workspace.ID)
7879
require.NoError(t, err, "fetch updated workspace")
79-
require.Equal(t, sched, updated.AutostartSchedule, "expected autostart schedule to be set")
80+
require.Equal(t, sched, *updated.AutostartSchedule, "expected autostart schedule to be set")
8081

8182
// Disable schedule
8283
cmd, root = clitest.New(t, "autostart", "disable", workspace.Name)
@@ -90,7 +91,7 @@ func TestAutostart(t *testing.T) {
9091
// Ensure autostart schedule updated
9192
updated, err = client.Workspace(ctx, workspace.ID)
9293
require.NoError(t, err, "fetch updated workspace")
93-
require.Empty(t, updated.AutostartSchedule, "expected autostart schedule to not be set")
94+
require.Nil(t, updated.AutostartSchedule, "expected autostart schedule to not be set")
9495
})
9596

9697
t.Run("Enable_NotFound", func(t *testing.T) {
@@ -155,6 +156,6 @@ func TestAutostart(t *testing.T) {
155156
// Ensure nothing happened
156157
updated, err := client.Workspace(ctx, workspace.ID)
157158
require.NoError(t, err, "fetch updated workspace")
158-
require.Equal(t, expectedSchedule, updated.AutostartSchedule, "expected default autostart schedule")
159+
require.Equal(t, expectedSchedule, *updated.AutostartSchedule, "expected default autostart schedule")
159160
})
160161
}

cli/bump_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func TestBump(t *testing.T) {
4040
expectedDeadline := workspace.LatestBuild.Deadline.Add(90 * time.Minute)
4141

4242
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
43-
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
44-
require.NoError(t, err)
43+
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
44+
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
4545

4646
cmd, root := clitest.New(t, cmdArgs...)
4747
clitest.SetupConfig(t, client, root)
@@ -81,8 +81,8 @@ func TestBump(t *testing.T) {
8181
expectedDeadline := workspace.LatestBuild.Deadline.Add(30 * time.Minute)
8282

8383
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
84-
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
85-
require.NoError(t, err)
84+
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
85+
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
8686

8787
cmd, root := clitest.New(t, cmdArgs...)
8888
clitest.SetupConfig(t, client, root)
@@ -121,8 +121,8 @@ func TestBump(t *testing.T) {
121121
require.NoError(t, err)
122122

123123
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
124-
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
125-
require.NoError(t, err)
124+
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
125+
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
126126

127127
cmd, root := clitest.New(t, cmdArgs...)
128128
clitest.SetupConfig(t, client, root)
@@ -147,7 +147,7 @@ func TestBump(t *testing.T) {
147147
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
148148
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
149149
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
150-
cwr.TTL = nil
150+
cwr.TTLMillis = nil
151151
})
152152
cmdArgs = []string{"bump", workspace.Name}
153153
stdoutBuf = &bytes.Buffer{}
@@ -199,8 +199,8 @@ func TestBump(t *testing.T) {
199199
require.NoError(t, err)
200200

201201
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
202-
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
203-
require.NoError(t, err)
202+
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
203+
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
204204

205205
cmd, root := clitest.New(t, cmdArgs...)
206206
clitest.SetupConfig(t, client, root)

cli/create.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/coder/coder/cli/cliflag"
1212
"github.com/coder/coder/cli/cliui"
1313
"github.com/coder/coder/coderd/autobuild/schedule"
14+
"github.com/coder/coder/coderd/util/ptr"
1415
"github.com/coder/coder/codersdk"
1516
)
1617

@@ -226,7 +227,7 @@ func create() *cobra.Command {
226227
TemplateID: template.ID,
227228
Name: workspaceName,
228229
AutostartSchedule: &schedSpec,
229-
TTL: &ttl,
230+
TTLMillis: ptr.Ref(ttl.Milliseconds()),
230231
ParameterValues: parameters,
231232
})
232233
if err != nil {

cli/list.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/coder/coder/cli/cliui"
1313
"github.com/coder/coder/coderd/autobuild/schedule"
14+
"github.com/coder/coder/coderd/util/ptr"
1415
"github.com/coder/coder/codersdk"
1516
)
1617

@@ -87,15 +88,16 @@ func list() *cobra.Command {
8788

8889
duration := time.Now().UTC().Sub(workspace.LatestBuild.Job.CreatedAt).Truncate(time.Second)
8990
autostartDisplay := "-"
90-
if workspace.AutostartSchedule != "" {
91-
if sched, err := schedule.Weekly(workspace.AutostartSchedule); err == nil {
91+
if !ptr.NilOrEmpty(workspace.AutostartSchedule) {
92+
if sched, err := schedule.Weekly(*workspace.AutostartSchedule); err == nil {
9293
autostartDisplay = sched.Cron()
9394
}
9495
}
9596

9697
autostopDisplay := "-"
97-
if workspace.TTL != nil {
98-
autostopDisplay = durationDisplay(*workspace.TTL)
98+
if !ptr.NilOrZero(workspace.TTLMillis) {
99+
dur := time.Duration(*workspace.TTLMillis) * time.Millisecond
100+
autostopDisplay = durationDisplay(dur)
99101
if has, ext := hasExtension(workspace); has {
100102
autostopDisplay += fmt.Sprintf(" (+%s)", durationDisplay(ext.Round(time.Minute)))
101103
}
@@ -128,10 +130,11 @@ func hasExtension(ws codersdk.Workspace) (bool, time.Duration) {
128130
if ws.LatestBuild.Deadline.IsZero() {
129131
return false, 0
130132
}
131-
if ws.TTL == nil {
133+
if ws.TTLMillis == nil {
132134
return false, 0
133135
}
134-
delta := ws.LatestBuild.Deadline.Add(-*ws.TTL).Sub(ws.LatestBuild.CreatedAt)
136+
ttl := time.Duration(*ws.TTLMillis) * time.Millisecond
137+
delta := ws.LatestBuild.Deadline.Add(-ttl).Sub(ws.LatestBuild.CreatedAt)
135138
if delta < time.Minute {
136139
return false, 0
137140
}

cli/ssh.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/coder/coder/cli/cliflag"
2323
"github.com/coder/coder/cli/cliui"
2424
"github.com/coder/coder/coderd/autobuild/notify"
25+
"github.com/coder/coder/coderd/util/ptr"
2526
"github.com/coder/coder/codersdk"
2627
"github.com/coder/coder/cryptorand"
2728
)
@@ -290,7 +291,7 @@ func notifyCondition(ctx context.Context, client *codersdk.Client, workspaceID u
290291
return time.Time{}, nil
291292
}
292293

293-
if ws.TTL == nil || *ws.TTL == 0 {
294+
if ptr.NilOrZero(ws.TTLMillis) {
294295
return time.Time{}, nil
295296
}
296297

cli/ttl.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ func ttlShow() *cobra.Command {
4949
return xerrors.Errorf("get workspace: %w", err)
5050
}
5151

52-
if workspace.TTL == nil {
52+
if workspace.TTLMillis == nil || *workspace.TTLMillis == 0 {
5353
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "not set\n")
5454
return nil
5555
}
5656

57-
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", workspace.TTL)
57+
dur := time.Duration(*workspace.TTLMillis) * time.Millisecond
58+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", dur)
5859

5960
return nil
6061
},
@@ -96,10 +97,10 @@ func ttlset() *cobra.Command {
9697
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "warning: ttl rounded down to %s\n", truncated)
9798
}
9899

99-
err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
100-
TTL: &truncated,
101-
})
102-
if err != nil {
100+
millis := truncated.Milliseconds()
101+
if err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
102+
TTLMillis: &millis,
103+
}); err != nil {
103104
return xerrors.Errorf("update workspace ttl: %w", err)
104105
}
105106

@@ -130,7 +131,7 @@ func ttlunset() *cobra.Command {
130131
}
131132

132133
err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
133-
TTL: nil,
134+
TTLMillis: nil,
134135
})
135136
if err != nil {
136137
return xerrors.Errorf("update workspace ttl: %w", err)

cli/ttl_test.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/coder/coder/cli/clitest"
1313
"github.com/coder/coder/coderd/coderdtest"
14+
"github.com/coder/coder/coderd/util/ptr"
1415
"github.com/coder/coder/codersdk"
1516
)
1617

@@ -34,7 +35,7 @@ func TestTTL(t *testing.T) {
3435
)
3536

3637
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
37-
TTL: &ttl,
38+
TTLMillis: ptr.Ref(ttl.Milliseconds()),
3839
})
3940
require.NoError(t, err)
4041

@@ -73,7 +74,7 @@ func TestTTL(t *testing.T) {
7374
// Ensure ttl updated
7475
updated, err := client.Workspace(ctx, workspace.ID)
7576
require.NoError(t, err, "fetch updated workspace")
76-
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
77+
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
7778
require.Contains(t, stdoutBuf.String(), "warning: ttl rounded down")
7879

7980
// unset schedule
@@ -87,7 +88,7 @@ func TestTTL(t *testing.T) {
8788
// Ensure ttl updated
8889
updated, err = client.Workspace(ctx, workspace.ID)
8990
require.NoError(t, err, "fetch updated workspace")
90-
require.Nil(t, updated.TTL, "expected ttl to not be set")
91+
require.Nil(t, updated.TTLMillis, "expected ttl to not be set")
9192
})
9293

9394
t.Run("ZeroInvalid", func(t *testing.T) {
@@ -116,7 +117,7 @@ func TestTTL(t *testing.T) {
116117
// Ensure ttl updated
117118
updated, err := client.Workspace(ctx, workspace.ID)
118119
require.NoError(t, err, "fetch updated workspace")
119-
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
120+
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
120121
require.Contains(t, stdoutBuf.String(), "warning: ttl rounded down")
121122

122123
// A TTL of zero is not considered valid.
@@ -131,7 +132,7 @@ func TestTTL(t *testing.T) {
131132
// Ensure ttl remains as before
132133
updated, err = client.Workspace(ctx, workspace.ID)
133134
require.NoError(t, err, "fetch updated workspace")
134-
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
135+
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
135136
})
136137

137138
t.Run("Set_NotFound", func(t *testing.T) {

coderd/autobuild/executor/lifecycle_executor_test.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/coder/coder/coderd/autobuild/schedule"
1515
"github.com/coder/coder/coderd/coderdtest"
1616
"github.com/coder/coder/coderd/database"
17+
"github.com/coder/coder/coderd/util/ptr"
1718
"github.com/coder/coder/codersdk"
1819

1920
"github.com/google/uuid"
@@ -44,7 +45,7 @@ func TestExecutorAutostartOK(t *testing.T) {
4445
sched, err := schedule.Weekly("* * * * *")
4546
require.NoError(t, err)
4647
require.NoError(t, client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
47-
Schedule: sched.String(),
48+
Schedule: ptr.Ref(sched.String()),
4849
}))
4950

5051
// When: the autobuild executor ticks
@@ -95,7 +96,7 @@ func TestExecutorAutostartTemplateUpdated(t *testing.T) {
9596
sched, err := schedule.Weekly("* * * * *")
9697
require.NoError(t, err)
9798
require.NoError(t, client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
98-
Schedule: sched.String(),
99+
Schedule: ptr.Ref(sched.String()),
99100
}))
100101

101102
// When: the autobuild executor ticks
@@ -138,7 +139,7 @@ func TestExecutorAutostartAlreadyRunning(t *testing.T) {
138139
sched, err := schedule.Weekly("* * * * *")
139140
require.NoError(t, err)
140141
require.NoError(t, client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
141-
Schedule: sched.String(),
142+
Schedule: ptr.Ref(sched.String()),
142143
}))
143144

144145
// When: the autobuild executor ticks
@@ -316,12 +317,12 @@ func TestExecutorAutostopNotEnabled(t *testing.T) {
316317
})
317318
// Given: we have a user with a workspace that has no TTL set
318319
workspace = mustProvisionWorkspace(t, client, func(cwr *codersdk.CreateWorkspaceRequest) {
319-
cwr.TTL = nil
320+
cwr.TTLMillis = nil
320321
})
321322
)
322323

323324
// Given: workspace has no TTL set
324-
require.Nil(t, workspace.TTL)
325+
require.Nil(t, workspace.TTLMillis)
325326

326327
// Given: workspace is running
327328
require.Equal(t, codersdk.WorkspaceTransitionStart, workspace.LatestBuild.Transition)
@@ -359,7 +360,7 @@ func TestExecutorWorkspaceDeleted(t *testing.T) {
359360
sched, err := schedule.Weekly("* * * * *")
360361
require.NoError(t, err)
361362
require.NoError(t, client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
362-
Schedule: sched.String(),
363+
Schedule: ptr.Ref(sched.String()),
363364
}))
364365

365366
// Given: workspace is deleted
@@ -402,7 +403,7 @@ func TestExecutorWorkspaceAutostartTooEarly(t *testing.T) {
402403
sched, err := schedule.Weekly(futureTimeCron)
403404
require.NoError(t, err)
404405
require.NoError(t, client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
405-
Schedule: sched.String(),
406+
Schedule: ptr.Ref(sched.String()),
406407
}))
407408

408409
// When: the autobuild executor ticks
@@ -461,7 +462,7 @@ func TestExecutorWorkspaceAutostopNoWaitChangedMyMind(t *testing.T) {
461462
)
462463

463464
// Given: the user changes their mind and decides their workspace should not auto-stop
464-
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{TTL: nil})
465+
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{TTLMillis: nil})
465466
require.NoError(t, err)
466467

467468
// When: the autobuild executor ticks after the deadline

0 commit comments

Comments
 (0)