@@ -40,16 +40,17 @@ var (
40
40
)
41
41
42
42
type Server struct {
43
- AccessURL * url.URL
44
- ID uuid.UUID
45
- Logger slog.Logger
46
- Provisioners []database.ProvisionerType
47
- Tags json.RawMessage
48
- Database database.Store
49
- Pubsub database.Pubsub
50
- Telemetry telemetry.Reporter
51
- QuotaCommitter * atomic.Pointer [proto.QuotaCommitter ]
52
- Auditor * atomic.Pointer [audit.Auditor ]
43
+ AccessURL * url.URL
44
+ ID uuid.UUID
45
+ Logger slog.Logger
46
+ Provisioners []database.ProvisionerType
47
+ Tags json.RawMessage
48
+ Database database.Store
49
+ Pubsub database.Pubsub
50
+ Telemetry telemetry.Reporter
51
+ QuotaCommitter * atomic.Pointer [proto.QuotaCommitter ]
52
+ Auditor * atomic.Pointer [audit.Auditor ]
53
+ TemplateScheduleStore * atomic.Pointer [TemplateScheduleStore ]
53
54
54
55
AcquireJobDebounce time.Duration
55
56
}
@@ -520,12 +521,12 @@ func (server *Server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*p
520
521
521
522
var build database.WorkspaceBuild
522
523
err := server .Database .InTx (func (db database.Store ) error {
523
- workspaceBuild , err := server . Database .GetWorkspaceBuildByID (ctx , input .WorkspaceBuildID )
524
+ workspaceBuild , err := db .GetWorkspaceBuildByID (ctx , input .WorkspaceBuildID )
524
525
if err != nil {
525
526
return xerrors .Errorf ("get workspace build: %w" , err )
526
527
}
527
528
528
- build , err = server . Database .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
529
+ build , err = db .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
529
530
ID : input .WorkspaceBuildID ,
530
531
UpdatedAt : database .Now (),
531
532
ProvisionerState : jobType .WorkspaceBuild .State ,
@@ -611,6 +612,8 @@ func (server *Server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*p
611
612
}
612
613
613
614
// CompleteJob is triggered by a provision daemon to mark a provisioner job as completed.
615
+ //
616
+ //nolint:gocyclo
614
617
func (server * Server ) CompleteJob (ctx context.Context , completed * proto.CompletedJob ) (* proto.Empty , error ) {
615
618
jobID , err := uuid .Parse (completed .JobId )
616
619
if err != nil {
@@ -715,39 +718,49 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
715
718
var getWorkspaceError error
716
719
717
720
err = server .Database .InTx (func (db database.Store ) error {
718
- now := database .Now ()
719
- var workspaceDeadline time.Time
721
+ var (
722
+ now = database .Now ()
723
+ // deadline is the time when the workspace will be stopped. The
724
+ // value can be bumped by user activity or manually by the user
725
+ // via the UI.
726
+ deadline time.Time
727
+ // maxDeadline is the maximum value for deadline.
728
+ maxDeadline time.Time
729
+ )
730
+
720
731
workspace , getWorkspaceError = db .GetWorkspaceByID (ctx , workspaceBuild .WorkspaceID )
721
- if getWorkspaceError == nil {
722
- if workspace .Ttl .Valid {
723
- workspaceDeadline = now .Add (time .Duration (workspace .Ttl .Int64 ))
724
- }
725
- } else {
726
- // Huh? Did the workspace get deleted?
727
- // In any case, since this is just for the TTL, try and continue anyway.
732
+ if getWorkspaceError != nil {
728
733
server .Logger .Error (ctx ,
729
734
"fetch workspace for build" ,
730
735
slog .F ("workspace_build_id" , workspaceBuild .ID ),
731
736
slog .F ("workspace_id" , workspaceBuild .WorkspaceID ),
732
737
)
738
+ return getWorkspaceError
739
+ }
740
+ if workspace .Ttl .Valid {
741
+ deadline = now .Add (time .Duration (workspace .Ttl .Int64 ))
733
742
}
734
743
735
- var workspaceMaxDeadline time.Time
736
- template , err := db .GetTemplateByID (ctx , workspace .TemplateID )
737
- if err == nil {
738
- if template .MaxTtl > 0 {
739
- workspaceMaxDeadline = now .Add (time .Duration (template .MaxTtl ))
740
- if ! workspaceDeadline .IsZero () && workspaceMaxDeadline .Before (workspaceDeadline ) {
741
- workspaceDeadline = workspaceMaxDeadline
742
- }
744
+ templateSchedule , err := (* server .TemplateScheduleStore .Load ()).GetTemplateScheduleOptions (ctx , db , workspace .TemplateID )
745
+ if err != nil {
746
+ return xerrors .Errorf ("get template schedule options: %w" , err )
747
+ }
748
+ if ! templateSchedule .UserSchedulingEnabled {
749
+ // The user is not permitted to set their own TTL.
750
+ deadline = time.Time {}
751
+ }
752
+ if deadline .IsZero () && templateSchedule .DefaultTTL > 0 {
753
+ deadline = now .Add (templateSchedule .DefaultTTL )
754
+ }
755
+ if templateSchedule .MaxTTL > 0 {
756
+ maxDeadline = now .Add (templateSchedule .MaxTTL )
757
+
758
+ if deadline .IsZero () || maxDeadline .Before (deadline ) {
759
+ // If the workspace doesn't have a deadline or the max
760
+ // deadline is sooner than the workspace deadline, use the
761
+ // max deadline as the actual deadline.
762
+ deadline = maxDeadline
743
763
}
744
- } else {
745
- server .Logger .Error (ctx ,
746
- "fetch template for build" ,
747
- slog .F ("workspace_build_id" , workspaceBuild .ID ),
748
- slog .F ("workspace_id" , workspaceBuild .WorkspaceID ),
749
- slog .F ("template_id" , workspace .TemplateID ),
750
- )
751
764
}
752
765
753
766
err = db .UpdateProvisionerJobWithCompleteByID (ctx , database.UpdateProvisionerJobWithCompleteByIDParams {
@@ -763,8 +776,8 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete
763
776
}
764
777
_ , err = db .UpdateWorkspaceBuildByID (ctx , database.UpdateWorkspaceBuildByIDParams {
765
778
ID : workspaceBuild .ID ,
766
- Deadline : workspaceDeadline ,
767
- MaxDeadline : workspaceMaxDeadline ,
779
+ Deadline : deadline ,
780
+ MaxDeadline : maxDeadline ,
768
781
ProvisionerState : jobType .WorkspaceBuild .State ,
769
782
UpdatedAt : now ,
770
783
})
0 commit comments