@@ -46,6 +46,7 @@ import (
46
46
"github.com/coder/coder/v2/provisionerd/proto"
47
47
"github.com/coder/coder/v2/provisionersdk"
48
48
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
49
+ "github.com/coder/quartz"
49
50
)
50
51
51
52
const (
@@ -61,8 +62,9 @@ const (
61
62
type Options struct {
62
63
OIDCConfig promoauth.OAuth2Config
63
64
ExternalAuthConfigs []* externalauth.Config
64
- // TimeNowFn is only used in tests
65
- TimeNowFn func () time.Time
65
+
66
+ // Clock for testing
67
+ Clock quartz.Clock
66
68
67
69
// AcquireJobLongPollDur is used in tests
68
70
AcquireJobLongPollDur time.Duration
@@ -104,7 +106,7 @@ type server struct {
104
106
105
107
OIDCConfig promoauth.OAuth2Config
106
108
107
- TimeNowFn func () time. Time
109
+ Clock quartz. Clock
108
110
109
111
acquireJobLongPollDur time.Duration
110
112
@@ -191,6 +193,9 @@ func NewServer(
191
193
if options .HeartbeatInterval == 0 {
192
194
options .HeartbeatInterval = DefaultHeartbeatInterval
193
195
}
196
+ if options .Clock == nil {
197
+ options .Clock = quartz .NewReal ()
198
+ }
194
199
195
200
s := & server {
196
201
lifecycleCtx : lifecycleCtx ,
@@ -213,7 +218,7 @@ func NewServer(
213
218
UserQuietHoursScheduleStore : userQuietHoursScheduleStore ,
214
219
DeploymentValues : deploymentValues ,
215
220
OIDCConfig : options .OIDCConfig ,
216
- TimeNowFn : options .TimeNowFn ,
221
+ Clock : options .Clock ,
217
222
acquireJobLongPollDur : options .AcquireJobLongPollDur ,
218
223
heartbeatInterval : options .HeartbeatInterval ,
219
224
heartbeatFn : options .HeartbeatFn ,
@@ -229,11 +234,8 @@ func NewServer(
229
234
230
235
// timeNow should be used when trying to get the current time for math
231
236
// calculations regarding workspace start and stop time.
232
- func (s * server ) timeNow () time.Time {
233
- if s .TimeNowFn != nil {
234
- return dbtime .Time (s .TimeNowFn ())
235
- }
236
- return dbtime .Now ()
237
+ func (s * server ) timeNow (tags ... string ) time.Time {
238
+ return dbtime .Time (s .Clock .Now (tags ... ))
237
239
}
238
240
239
241
// heartbeatLoop runs heartbeatOnce at the interval specified by HeartbeatInterval
@@ -365,7 +367,7 @@ func (s *server) AcquireJobWithCancel(stream proto.DRPCProvisionerDaemon_Acquire
365
367
logger .Error (streamCtx , "recv error and failed to cancel acquire job" , slog .Error (recvErr ))
366
368
// Well, this is awkward. We hit an error receiving from the stream, but didn't cancel before we locked a job
367
369
// in the database. We need to mark this job as failed so the end user can retry if they want to.
368
- now := dbtime . Now ()
370
+ now := s . timeNow ()
369
371
err := s .Database .UpdateProvisionerJobWithCompleteByID (
370
372
//nolint:gocritic // Provisionerd has specific authz rules.
371
373
dbauthz .AsProvisionerd (context .Background ()),
@@ -406,15 +408,15 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
406
408
err := s .Database .UpdateProvisionerJobWithCompleteByID (ctx , database.UpdateProvisionerJobWithCompleteByIDParams {
407
409
ID : job .ID ,
408
410
CompletedAt : sql.NullTime {
409
- Time : dbtime . Now (),
411
+ Time : s . timeNow (),
410
412
Valid : true ,
411
413
},
412
414
Error : sql.NullString {
413
415
String : errorMessage ,
414
416
Valid : true ,
415
417
},
416
418
ErrorCode : job .ErrorCode ,
417
- UpdatedAt : dbtime . Now (),
419
+ UpdatedAt : s . timeNow (),
418
420
})
419
421
if err != nil {
420
422
return xerrors .Errorf ("update provisioner job: %w" , err )
@@ -792,7 +794,7 @@ func (s *server) UpdateJob(ctx context.Context, request *proto.UpdateJobRequest)
792
794
}
793
795
err = s .Database .UpdateProvisionerJobByID (ctx , database.UpdateProvisionerJobByIDParams {
794
796
ID : parsedID ,
795
- UpdatedAt : dbtime . Now (),
797
+ UpdatedAt : s . timeNow (),
796
798
})
797
799
if err != nil {
798
800
return nil , xerrors .Errorf ("update job: %w" , err )
@@ -869,7 +871,7 @@ func (s *server) UpdateJob(ctx context.Context, request *proto.UpdateJobRequest)
869
871
err := s .Database .UpdateTemplateVersionDescriptionByJobID (ctx , database.UpdateTemplateVersionDescriptionByJobIDParams {
870
872
JobID : job .ID ,
871
873
Readme : string (request .Readme ),
872
- UpdatedAt : dbtime . Now (),
874
+ UpdatedAt : s . timeNow (),
873
875
})
874
876
if err != nil {
875
877
return nil , xerrors .Errorf ("update template version description: %w" , err )
@@ -958,7 +960,7 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
958
960
return nil , xerrors .Errorf ("job already completed" )
959
961
}
960
962
job .CompletedAt = sql.NullTime {
961
- Time : dbtime . Now (),
963
+ Time : s . timeNow (),
962
964
Valid : true ,
963
965
}
964
966
job .Error = sql.NullString {
@@ -973,7 +975,7 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
973
975
err = s .Database .UpdateProvisionerJobWithCompleteByID (ctx , database.UpdateProvisionerJobWithCompleteByIDParams {
974
976
ID : jobID ,
975
977
CompletedAt : job .CompletedAt ,
976
- UpdatedAt : dbtime . Now (),
978
+ UpdatedAt : s . timeNow (),
977
979
Error : job .Error ,
978
980
ErrorCode : job .ErrorCode ,
979
981
})
@@ -1008,15 +1010,15 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
1008
1010
if jobType .WorkspaceBuild .State != nil {
1009
1011
err = db .UpdateWorkspaceBuildProvisionerStateByID (ctx , database.UpdateWorkspaceBuildProvisionerStateByIDParams {
1010
1012
ID : input .WorkspaceBuildID ,
1011
- UpdatedAt : dbtime . Now (),
1013
+ UpdatedAt : s . timeNow (),
1012
1014
ProvisionerState : jobType .WorkspaceBuild .State ,
1013
1015
})
1014
1016
if err != nil {
1015
1017
return xerrors .Errorf ("update workspace build state: %w" , err )
1016
1018
}
1017
1019
err = db .UpdateWorkspaceBuildDeadlineByID (ctx , database.UpdateWorkspaceBuildDeadlineByIDParams {
1018
1020
ID : input .WorkspaceBuildID ,
1019
- UpdatedAt : dbtime . Now (),
1021
+ UpdatedAt : s . timeNow (),
1020
1022
Deadline : build .Deadline ,
1021
1023
MaxDeadline : build .MaxDeadline ,
1022
1024
})
@@ -1382,17 +1384,17 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
1382
1384
err = s .Database .UpdateTemplateVersionExternalAuthProvidersByJobID (ctx , database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams {
1383
1385
JobID : jobID ,
1384
1386
ExternalAuthProviders : json .RawMessage (externalAuthProvidersMessage ),
1385
- UpdatedAt : dbtime . Now (),
1387
+ UpdatedAt : s . timeNow (),
1386
1388
})
1387
1389
if err != nil {
1388
1390
return nil , xerrors .Errorf ("update template version external auth providers: %w" , err )
1389
1391
}
1390
1392
1391
1393
err = s .Database .UpdateProvisionerJobWithCompleteByID (ctx , database.UpdateProvisionerJobWithCompleteByIDParams {
1392
1394
ID : jobID ,
1393
- UpdatedAt : dbtime . Now (),
1395
+ UpdatedAt : s . timeNow (),
1394
1396
CompletedAt : sql.NullTime {
1395
- Time : dbtime . Now (),
1397
+ Time : s . timeNow (),
1396
1398
Valid : true ,
1397
1399
},
1398
1400
Error : completedError ,
@@ -1687,9 +1689,9 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
1687
1689
1688
1690
err = s .Database .UpdateProvisionerJobWithCompleteByID (ctx , database.UpdateProvisionerJobWithCompleteByIDParams {
1689
1691
ID : jobID ,
1690
- UpdatedAt : dbtime . Now (),
1692
+ UpdatedAt : s . timeNow (),
1691
1693
CompletedAt : sql.NullTime {
1692
- Time : dbtime . Now (),
1694
+ Time : s . timeNow (),
1693
1695
Valid : true ,
1694
1696
},
1695
1697
Error : sql.NullString {},
0 commit comments