@@ -16,6 +16,8 @@ import (
16
16
"github.com/coder/coder/v2/coderd/database/db2sdk"
17
17
"github.com/coder/coder/v2/coderd/database/dbauthz"
18
18
"github.com/coder/coder/v2/coderd/database/dbtime"
19
+ "github.com/coder/coder/v2/coderd/database/provisionerjobs"
20
+ "github.com/coder/coder/v2/coderd/database/pubsub"
19
21
"github.com/coder/coder/v2/coderd/schedule"
20
22
"github.com/coder/coder/v2/coderd/schedule/cron"
21
23
"github.com/coder/coder/v2/coderd/wsbuilder"
@@ -26,6 +28,7 @@ import (
26
28
type Executor struct {
27
29
ctx context.Context
28
30
db database.Store
31
+ ps pubsub.Pubsub
29
32
templateScheduleStore * atomic.Pointer [schedule.TemplateScheduleStore ]
30
33
log slog.Logger
31
34
tick <- chan time.Time
@@ -40,11 +43,12 @@ type Stats struct {
40
43
}
41
44
42
45
// New returns a new wsactions executor.
43
- func NewExecutor (ctx context.Context , db database.Store , tss * atomic.Pointer [schedule.TemplateScheduleStore ], log slog.Logger , tick <- chan time.Time ) * Executor {
46
+ func NewExecutor (ctx context.Context , db database.Store , ps pubsub. Pubsub , tss * atomic.Pointer [schedule.TemplateScheduleStore ], log slog.Logger , tick <- chan time.Time ) * Executor {
44
47
le := & Executor {
45
48
//nolint:gocritic // Autostart has a limited set of permissions.
46
49
ctx : dbauthz .AsAutostart (ctx ),
47
50
db : db ,
51
+ ps : ps ,
48
52
templateScheduleStore : tss ,
49
53
tick : tick ,
50
54
log : log .Named ("autobuild" ),
@@ -129,6 +133,7 @@ func (e *Executor) runOnce(t time.Time) Stats {
129
133
log := e .log .With (slog .F ("workspace_id" , wsID ))
130
134
131
135
eg .Go (func () error {
136
+ var job * database.ProvisionerJob
132
137
err := e .db .InTx (func (tx database.Store ) error {
133
138
// Re-check eligibility since the first check was outside the
134
139
// transaction and the workspace settings may have changed.
@@ -168,7 +173,8 @@ func (e *Executor) runOnce(t time.Time) Stats {
168
173
SetLastWorkspaceBuildJobInTx (& latestJob ).
169
174
Reason (reason )
170
175
171
- if _ , _ , err := builder .Build (e .ctx , tx , nil ); err != nil {
176
+ _ , job , err = builder .Build (e .ctx , tx , nil )
177
+ if err != nil {
172
178
log .Error (e .ctx , "unable to transition workspace" ,
173
179
slog .F ("transition" , nextTransition ),
174
180
slog .Error (err ),
@@ -230,6 +236,17 @@ func (e *Executor) runOnce(t time.Time) Stats {
230
236
if err != nil {
231
237
log .Error (e .ctx , "workspace scheduling failed" , slog .Error (err ))
232
238
}
239
+ if job != nil && err == nil {
240
+ // Note that we can't refactor such that posting the job happens inside wsbuilder because it's called
241
+ // with an outer transaction like this, and we need to make sure the outer transaction commits before
242
+ // posting the job. If we post before the transaction commits, provisionerd might try to acquire the
243
+ // job, fail, and then sit idle instead of picking up the job.
244
+ err = provisionerjobs .PostJob (e .ps , * job )
245
+ if err != nil {
246
+ // Client probably doesn't care about this error, so just log it.
247
+ log .Error (e .ctx , "failed to post provisioner job to pubsub" , slog .Error (err ))
248
+ }
249
+ }
233
250
return nil
234
251
})
235
252
}
0 commit comments