@@ -2,13 +2,16 @@ package coderd
2
2
3
3
import (
4
4
"context"
5
+ "database/sql"
6
+ "errors"
5
7
"time"
6
8
7
9
"github.com/google/uuid"
8
10
"golang.org/x/xerrors"
9
11
10
12
"cdr.dev/slog"
11
13
"github.com/coder/coder/v2/coderd/database"
14
+ "github.com/coder/coder/v2/coderd/database/dbtime"
12
15
)
13
16
14
17
// activityBumpWorkspace automatically bumps the workspace's auto-off timer
@@ -18,72 +21,78 @@ func activityBumpWorkspace(ctx context.Context, log slog.Logger, db database.Sto
18
21
// low priority operations fail first.
19
22
ctx , cancel := context .WithTimeout (ctx , time .Second * 15 )
20
23
defer cancel ()
24
+ // if err := db.ActivityBumpWorkspace(ctx, workspaceID); err != nil {
25
+ // if !xerrors.Is(err, context.Canceled) && !database.IsQueryCanceledError(err) {
26
+ // // Bump will fail if the context is canceled, but this is ok.
27
+ // log.Error(ctx, "bump failed", slog.Error(err),
28
+ // slog.F("workspace_id", workspaceID),
29
+ // )
30
+ // }
31
+ // return
32
+ // }
21
33
22
34
err := db .InTx (func (s database.Store ) error {
23
- if err := s .ActivityBumpWorkspace (ctx , workspaceID ); err != nil {
24
- return xerrors .Errorf ("activity bump workspace: %w" , err )
35
+ build , err := s .GetLatestWorkspaceBuildByWorkspaceID (ctx , workspaceID )
36
+ if errors .Is (err , sql .ErrNoRows ) {
37
+ return nil
38
+ } else if err != nil {
39
+ return xerrors .Errorf ("get latest workspace build: %w" , err )
25
40
}
26
- // build, err := s.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspaceID)
27
- // if errors.Is(err, sql.ErrNoRows) {
28
- // return nil
29
- // } else if err != nil {
30
- // return xerrors.Errorf("get latest workspace build: %w", err)
31
- // }
32
41
33
- // job, err := s.GetProvisionerJobByID(ctx, build.JobID)
34
- // if err != nil {
35
- // return xerrors.Errorf("get provisioner job: %w", err)
36
- // }
42
+ job , err := s .GetProvisionerJobByID (ctx , build .JobID )
43
+ if err != nil {
44
+ return xerrors .Errorf ("get provisioner job: %w" , err )
45
+ }
46
+
47
+ if build .Transition != database .WorkspaceTransitionStart || ! job .CompletedAt .Valid {
48
+ return nil
49
+ }
37
50
38
- // if build.Transition != database.WorkspaceTransitionStart || !job.CompletedAt.Valid {
39
- // return nil
40
- // }
51
+ if build .Deadline .IsZero () {
52
+ // Workspace shutdown is manual
53
+ return nil
54
+ }
41
55
42
- // if build.Deadline.IsZero() {
43
- // // Workspace shutdown is manual
44
- // return nil
45
- // }
56
+ workspace , err := s . GetWorkspaceByID ( ctx , workspaceID )
57
+ if err != nil {
58
+ return xerrors . Errorf ( "get workspace: %w" , err )
59
+ }
46
60
47
- // workspace, err := s.GetWorkspaceByID(ctx, workspaceID)
48
- // if err != nil {
49
- // return xerrors.Errorf("get workspace: %w", err)
50
- // }
61
+ var (
62
+ // We bump by the original TTL to prevent counter-intuitive behavior
63
+ // as the TTL wraps. For example, if I set the TTL to 12 hours, sign off
64
+ // work at midnight, come back at 10am, I would want another full day
65
+ // of uptime. In the prior implementation, the workspace would enter
66
+ // a state of always expiring 1 hour in the future
67
+ bumpAmount = time .Duration (workspace .Ttl .Int64 )
68
+ // DB writes are expensive so we only bump when 5% of the deadline
69
+ // has elapsed.
70
+ bumpEvery = bumpAmount / 20
71
+ timeSinceLastBump = bumpAmount - time .Until (build .Deadline )
72
+ )
51
73
52
- // var (
53
- // We bump by the original TTL to prevent counter-intuitive behavior
54
- // as the TTL wraps. For example, if I set the TTL to 12 hours, sign off
55
- // work at midnight, come back at 10am, I would want another full day
56
- // of uptime. In the prior implementation, the workspace would enter
57
- // a state of always expiring 1 hour in the future
58
- // bumpAmount = time.Duration(workspace.Ttl.Int64)
59
- // DB writes are expensive so we only bump when 5% of the deadline
60
- // has elapsed.
61
- // bumpEvery = bumpAmount / 20
62
- // timeSinceLastBump = bumpAmount - time.Until(build.Deadline)
63
- // )
74
+ if timeSinceLastBump < bumpEvery {
75
+ return nil
76
+ }
64
77
65
- // if timeSinceLastBump < bumpEvery {
66
- // return nil
67
- // }
68
- //
69
- // if bumpAmount == 0 {
70
- // return nil
71
- // }
72
- //
73
- // newDeadline := dbtime.Now().Add(bumpAmount)
74
- // if !build.MaxDeadline.IsZero() && newDeadline.After(build.MaxDeadline) {
75
- // newDeadline = build.MaxDeadline
76
- // }
77
- //
78
- // if err := s.UpdateWorkspaceBuildByID(ctx, database.UpdateWorkspaceBuildByIDParams{
79
- // ID: build.ID,
80
- // UpdatedAt: dbtime.Now(),
81
- // ProvisionerState: build.ProvisionerState,
82
- // Deadline: newDeadline,
83
- // MaxDeadline: build.MaxDeadline,
84
- // }); err != nil {
85
- // return xerrors.Errorf("update workspace build: %w", err)
86
- // }
78
+ if bumpAmount == 0 {
79
+ return nil
80
+ }
81
+
82
+ newDeadline := dbtime .Now ().Add (bumpAmount )
83
+ if ! build .MaxDeadline .IsZero () && newDeadline .After (build .MaxDeadline ) {
84
+ newDeadline = build .MaxDeadline
85
+ }
86
+
87
+ if err := s .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
88
+ ID : build .ID ,
89
+ UpdatedAt : dbtime .Now (),
90
+ ProvisionerState : build .ProvisionerState ,
91
+ Deadline : newDeadline ,
92
+ MaxDeadline : build .MaxDeadline ,
93
+ }); err != nil {
94
+ return xerrors .Errorf ("update workspace build: %w" , err )
95
+ }
87
96
return nil
88
97
}, nil )
89
98
if err != nil {
0 commit comments