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.
This commit is contained in:
Cian Johnston
2022-06-02 11:23:34 +01:00
committed by GitHub
parent 51c420c90a
commit dcf03d8ba3
24 changed files with 287 additions and 148 deletions

View File

@ -51,15 +51,15 @@ func autostartShow() *cobra.Command {
return err
}
if workspace.AutostartSchedule == "" {
if workspace.AutostartSchedule == nil || *workspace.AutostartSchedule == "" {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "not enabled\n")
return nil
}
validSchedule, err := schedule.Weekly(workspace.AutostartSchedule)
validSchedule, err := schedule.Weekly(*workspace.AutostartSchedule)
if err != nil {
// This should never happen.
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "invalid autostart schedule %q for workspace %s: %s\n", workspace.AutostartSchedule, workspace.Name, err.Error())
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "invalid autostart schedule %q for workspace %s: %s\n", *workspace.AutostartSchedule, workspace.Name, err.Error())
return nil
}
@ -110,7 +110,7 @@ func autostartEnable() *cobra.Command {
}
err = client.UpdateWorkspaceAutostart(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
Schedule: validSchedule.String(),
Schedule: &spec,
})
if err != nil {
return err
@ -153,7 +153,7 @@ func autostartDisable() *cobra.Command {
}
err = client.UpdateWorkspaceAutostart(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
Schedule: "",
Schedule: nil,
})
if err != nil {
return err

View File

@ -11,6 +11,7 @@ import (
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
)
@ -34,7 +35,7 @@ func TestAutostart(t *testing.T) {
)
err := client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
Schedule: sched,
Schedule: ptr.Ref(sched),
})
require.NoError(t, err)
@ -76,7 +77,7 @@ func TestAutostart(t *testing.T) {
// Ensure autostart schedule updated
updated, err := client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Equal(t, sched, updated.AutostartSchedule, "expected autostart schedule to be set")
require.Equal(t, sched, *updated.AutostartSchedule, "expected autostart schedule to be set")
// Disable schedule
cmd, root = clitest.New(t, "autostart", "disable", workspace.Name)
@ -90,7 +91,7 @@ func TestAutostart(t *testing.T) {
// Ensure autostart schedule updated
updated, err = client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Empty(t, updated.AutostartSchedule, "expected autostart schedule to not be set")
require.Nil(t, updated.AutostartSchedule, "expected autostart schedule to not be set")
})
t.Run("Enable_NotFound", func(t *testing.T) {
@ -155,6 +156,6 @@ func TestAutostart(t *testing.T) {
// Ensure nothing happened
updated, err := client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Equal(t, expectedSchedule, updated.AutostartSchedule, "expected default autostart schedule")
require.Equal(t, expectedSchedule, *updated.AutostartSchedule, "expected default autostart schedule")
})
}

View File

@ -40,8 +40,8 @@ func TestBump(t *testing.T) {
expectedDeadline := workspace.LatestBuild.Deadline.Add(90 * time.Minute)
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
require.NoError(t, err)
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
cmd, root := clitest.New(t, cmdArgs...)
clitest.SetupConfig(t, client, root)
@ -81,8 +81,8 @@ func TestBump(t *testing.T) {
expectedDeadline := workspace.LatestBuild.Deadline.Add(30 * time.Minute)
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
require.NoError(t, err)
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
cmd, root := clitest.New(t, cmdArgs...)
clitest.SetupConfig(t, client, root)
@ -121,8 +121,8 @@ func TestBump(t *testing.T) {
require.NoError(t, err)
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
require.NoError(t, err)
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
cmd, root := clitest.New(t, cmdArgs...)
clitest.SetupConfig(t, client, root)
@ -147,7 +147,7 @@ func TestBump(t *testing.T) {
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
cwr.TTL = nil
cwr.TTLMillis = nil
})
cmdArgs = []string{"bump", workspace.Name}
stdoutBuf = &bytes.Buffer{}
@ -199,8 +199,8 @@ func TestBump(t *testing.T) {
require.NoError(t, err)
// Assert test invariant: workspace build has a deadline set equal to now plus ttl
require.WithinDuration(t, workspace.LatestBuild.Deadline, time.Now().Add(*workspace.TTL), time.Minute)
require.NoError(t, err)
initDeadline := time.Now().Add(time.Duration(*workspace.TTLMillis) * time.Millisecond)
require.WithinDuration(t, initDeadline, workspace.LatestBuild.Deadline, time.Minute)
cmd, root := clitest.New(t, cmdArgs...)
clitest.SetupConfig(t, client, root)

View File

@ -11,6 +11,7 @@ import (
"github.com/coder/coder/cli/cliflag"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/autobuild/schedule"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
)
@ -226,7 +227,7 @@ func create() *cobra.Command {
TemplateID: template.ID,
Name: workspaceName,
AutostartSchedule: &schedSpec,
TTL: &ttl,
TTLMillis: ptr.Ref(ttl.Milliseconds()),
ParameterValues: parameters,
})
if err != nil {

View File

@ -11,6 +11,7 @@ import (
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/autobuild/schedule"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
)
@ -87,15 +88,16 @@ func list() *cobra.Command {
duration := time.Now().UTC().Sub(workspace.LatestBuild.Job.CreatedAt).Truncate(time.Second)
autostartDisplay := "-"
if workspace.AutostartSchedule != "" {
if sched, err := schedule.Weekly(workspace.AutostartSchedule); err == nil {
if !ptr.NilOrEmpty(workspace.AutostartSchedule) {
if sched, err := schedule.Weekly(*workspace.AutostartSchedule); err == nil {
autostartDisplay = sched.Cron()
}
}
autostopDisplay := "-"
if workspace.TTL != nil {
autostopDisplay = durationDisplay(*workspace.TTL)
if !ptr.NilOrZero(workspace.TTLMillis) {
dur := time.Duration(*workspace.TTLMillis) * time.Millisecond
autostopDisplay = durationDisplay(dur)
if has, ext := hasExtension(workspace); has {
autostopDisplay += fmt.Sprintf(" (+%s)", durationDisplay(ext.Round(time.Minute)))
}
@ -128,10 +130,11 @@ func hasExtension(ws codersdk.Workspace) (bool, time.Duration) {
if ws.LatestBuild.Deadline.IsZero() {
return false, 0
}
if ws.TTL == nil {
if ws.TTLMillis == nil {
return false, 0
}
delta := ws.LatestBuild.Deadline.Add(-*ws.TTL).Sub(ws.LatestBuild.CreatedAt)
ttl := time.Duration(*ws.TTLMillis) * time.Millisecond
delta := ws.LatestBuild.Deadline.Add(-ttl).Sub(ws.LatestBuild.CreatedAt)
if delta < time.Minute {
return false, 0
}

View File

@ -22,6 +22,7 @@ import (
"github.com/coder/coder/cli/cliflag"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/autobuild/notify"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand"
)
@ -290,7 +291,7 @@ func notifyCondition(ctx context.Context, client *codersdk.Client, workspaceID u
return time.Time{}, nil
}
if ws.TTL == nil || *ws.TTL == 0 {
if ptr.NilOrZero(ws.TTLMillis) {
return time.Time{}, nil
}

View File

@ -49,12 +49,13 @@ func ttlShow() *cobra.Command {
return xerrors.Errorf("get workspace: %w", err)
}
if workspace.TTL == nil {
if workspace.TTLMillis == nil || *workspace.TTLMillis == 0 {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "not set\n")
return nil
}
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", workspace.TTL)
dur := time.Duration(*workspace.TTLMillis) * time.Millisecond
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", dur)
return nil
},
@ -96,10 +97,10 @@ func ttlset() *cobra.Command {
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "warning: ttl rounded down to %s\n", truncated)
}
err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
TTL: &truncated,
})
if err != nil {
millis := truncated.Milliseconds()
if err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
TTLMillis: &millis,
}); err != nil {
return xerrors.Errorf("update workspace ttl: %w", err)
}
@ -130,7 +131,7 @@ func ttlunset() *cobra.Command {
}
err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
TTL: nil,
TTLMillis: nil,
})
if err != nil {
return xerrors.Errorf("update workspace ttl: %w", err)

View File

@ -11,6 +11,7 @@ import (
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/util/ptr"
"github.com/coder/coder/codersdk"
)
@ -34,7 +35,7 @@ func TestTTL(t *testing.T) {
)
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
TTL: &ttl,
TTLMillis: ptr.Ref(ttl.Milliseconds()),
})
require.NoError(t, err)
@ -73,7 +74,7 @@ func TestTTL(t *testing.T) {
// Ensure ttl updated
updated, err := client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
require.Contains(t, stdoutBuf.String(), "warning: ttl rounded down")
// unset schedule
@ -87,7 +88,7 @@ func TestTTL(t *testing.T) {
// Ensure ttl updated
updated, err = client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Nil(t, updated.TTL, "expected ttl to not be set")
require.Nil(t, updated.TTLMillis, "expected ttl to not be set")
})
t.Run("ZeroInvalid", func(t *testing.T) {
@ -116,7 +117,7 @@ func TestTTL(t *testing.T) {
// Ensure ttl updated
updated, err := client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
require.Contains(t, stdoutBuf.String(), "warning: ttl rounded down")
// A TTL of zero is not considered valid.
@ -131,7 +132,7 @@ func TestTTL(t *testing.T) {
// Ensure ttl remains as before
updated, err = client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "fetch updated workspace")
require.Equal(t, ttl.Truncate(time.Minute), *updated.TTL)
require.Equal(t, ttl.Truncate(time.Minute), time.Duration(*updated.TTLMillis)*time.Millisecond)
})
t.Run("Set_NotFound", func(t *testing.T) {