@@ -26,62 +26,73 @@ func ActivityBumpWorkspace(log slog.Logger, db database.Store) func(h http.Handl
26
26
// We run the bump logic asynchronously since the result doesn't
27
27
// affect the response.
28
28
go func () {
29
- // We cannot use the Request context since the goroutine
30
- // may be around after the request terminates.
31
- // We set a short timeout so if the app is under load, these
32
- // low priority operations fail first.
33
- ctx ,cancel := context .WithTimeout (context .Background (),time .Second * 5 )
34
- defer cancel ()
29
+ bump := func () {
30
+ // We cannot use the Request context since the goroutine
31
+ // may be around after the request terminates.
32
+ // We set a short timeout so if the app is under load, these
33
+ // low priority operations fail first.
34
+ ctx ,cancel := context .WithTimeout (context .Background (),time .Second * 5 )
35
+ defer cancel ()
35
36
36
- err := db .InTx (func (s database.Store )error {
37
- build ,err := s .GetLatestWorkspaceBuildByWorkspaceID (ctx ,workspace .ID )
38
- log .Debug (ctx ,"build" ,slog .F ("build" ,build ))
39
- if errors .Is (err ,sql .ErrNoRows ) {
40
- return nil
41
- }else if err != nil {
42
- return xerrors .Errorf ("get latest workspace build: %w" ,err )
43
- }
37
+ err := db .InTx (func (s database.Store )error {
38
+ build ,err := s .GetLatestWorkspaceBuildByWorkspaceID (ctx ,workspace .ID )
39
+ log .Debug (ctx ,"build" ,slog .F ("build" ,build ))
40
+ if errors .Is (err ,sql .ErrNoRows ) {
41
+ return nil
42
+ }else if err != nil {
43
+ return xerrors .Errorf ("get latest workspace build: %w" ,err )
44
+ }
44
45
45
- job ,err := s .GetProvisionerJobByID (ctx ,build .JobID )
46
- if err != nil {
47
- return xerrors .Errorf ("get provisioner job: %w" ,err )
48
- }
46
+ job ,err := s .GetProvisionerJobByID (ctx ,build .JobID )
47
+ if err != nil {
48
+ return xerrors .Errorf ("get provisioner job: %w" ,err )
49
+ }
49
50
50
- if build .Transition != database .WorkspaceTransitionStart || ! job .CompletedAt .Valid {
51
- return nil
52
- }
51
+ if build .Transition != database .WorkspaceTransitionStart || ! job .CompletedAt .Valid {
52
+ return nil
53
+ }
53
54
54
- if build .Deadline .IsZero () {
55
- // Workspace shutdown is manual
56
- return nil
57
- }
55
+ if build .Deadline .IsZero () {
56
+ // Workspace shutdown is manual
57
+ return nil
58
+ }
58
59
59
- // We sent bumpThreshold slightly under bumpAmount to minimize DB writes.
60
- const (
61
- bumpAmount = time .Hour
62
- bumpThreshold = time .Hour - (time .Minute * 10 )
63
- )
60
+ // We sent bumpThreshold slightly under bumpAmount to minimize DB writes.
61
+ const (
62
+ bumpAmount = time .Hour
63
+ bumpThreshold = time .Hour - (time .Minute * 10 )
64
+ )
64
65
65
- if ! build .Deadline .Before (time .Now ().Add (bumpThreshold )) {
66
- return nil
67
- }
66
+ if ! build .Deadline .Before (time .Now ().Add (bumpThreshold )) {
67
+ return nil
68
+ }
68
69
69
- newDeadline := time .Now ().Add (bumpAmount )
70
+ newDeadline := time .Now ().Add (bumpAmount )
70
71
71
- if err := s .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
72
- ID :build .ID ,
73
- UpdatedAt :build .UpdatedAt ,
74
- ProvisionerState :build .ProvisionerState ,
75
- Deadline :newDeadline ,
76
- });err != nil {
77
- return xerrors .Errorf ("update workspace build: %w" ,err )
78
- }
79
- return nil
80
- })
72
+ if err := s .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
73
+ ID :build .ID ,
74
+ UpdatedAt :build .UpdatedAt ,
75
+ ProvisionerState :build .ProvisionerState ,
76
+ Deadline :newDeadline ,
77
+ });err != nil {
78
+ return xerrors .Errorf ("update workspace build: %w" ,err )
79
+ }
80
+ return nil
81
+ })
81
82
82
- if err != nil {
83
- log .Error (ctx ,"bump failed" ,slog .Error (err ))
83
+ if err != nil {
84
+ log .Error (ctx ,"bump failed" ,slog .Error (err ))
85
+ }else {
86
+ log .Debug (
87
+ ctx ,"bumped deadline from activity" ,
88
+ slog .F ("workspace_id" ,workspace .ID ),
89
+ )
90
+ }
84
91
}
92
+ // For long running connections (e.g. web terminal), we need
93
+ // to bump periodically
94
+ // ticker := time.NewTicker(time.Minute)
95
+ bump ()
85
96
}()
86
97
next .ServeHTTP (w ,r )
87
98
})