Skip to content

Commit 5e01e6e

Browse files
authored
fix: check if logs are completed before publishing (#6824)
1 parent 48f9521 commit 5e01e6e

File tree

1 file changed

+49
-23
lines changed

1 file changed

+49
-23
lines changed

coderd/provisionerjobs.go

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,47 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
5454
}
5555
}
5656

57+
if !follow {
58+
logs, err := api.Database.GetProvisionerLogsAfterID(ctx, database.GetProvisionerLogsAfterIDParams{
59+
JobID: job.ID,
60+
CreatedAfter: after,
61+
})
62+
if errors.Is(err, sql.ErrNoRows) {
63+
err = nil
64+
}
65+
if err != nil {
66+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
67+
Message: "Internal error fetching provisioner logs.",
68+
Detail: err.Error(),
69+
})
70+
return
71+
}
72+
if logs == nil {
73+
logs = []database.ProvisionerJobLog{}
74+
}
75+
76+
logger.Debug(ctx, "Finished non-follow job logs")
77+
httpapi.Write(ctx, rw, http.StatusOK, convertProvisionerJobLogs(logs))
78+
return
79+
}
80+
81+
// if we are following logs, start the subscription before we query the database, so that we don't miss any logs
82+
// between the end of our query and the start of the subscription. We might get duplicates, so we'll keep track
83+
// of processed IDs.
84+
var bufferedLogs <-chan *database.ProvisionerJobLog
85+
if follow {
86+
bl, closeFollow, err := api.followProvisionerJobLogs(actor, job.ID)
87+
if err != nil {
88+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
89+
Message: "Internal error watching provisioner logs.",
90+
Detail: err.Error(),
91+
})
92+
return
93+
}
94+
defer closeFollow()
95+
bufferedLogs = bl
96+
}
97+
5798
logs, err := api.Database.GetProvisionerLogsAfterID(ctx, database.GetProvisionerLogsAfterIDParams{
5899
JobID: job.ID,
59100
CreatedAfter: after,
@@ -72,12 +113,6 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
72113
logs = []database.ProvisionerJobLog{}
73114
}
74115

75-
if !follow {
76-
logger.Debug(ctx, "Finished non-follow job logs")
77-
httpapi.Write(ctx, rw, http.StatusOK, convertProvisionerJobLogs(logs))
78-
return
79-
}
80-
81116
api.WebsocketWaitMutex.Lock()
82117
api.WebsocketWaitGroup.Add(1)
83118
api.WebsocketWaitMutex.Unlock()
@@ -106,28 +141,19 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
106141
return
107142
}
108143
}
144+
job, err = api.Database.GetProvisionerJobByID(ctx, job.ID)
145+
if err != nil {
146+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
147+
Message: "Internal error fetching provisioner job.",
148+
Detail: err.Error(),
149+
})
150+
return
151+
}
109152
if job.CompletedAt.Valid {
110153
// job was complete before we queried the database for historical logs
111154
return
112155
}
113156

114-
// if we are following logs, start the subscription before we query the database, so that we don't miss any logs
115-
// between the end of our query and the start of the subscription. We might get duplicates, so we'll keep track
116-
// of processed IDs.
117-
var bufferedLogs <-chan *database.ProvisionerJobLog
118-
if follow {
119-
bl, closeFollow, err := api.followProvisionerJobLogs(actor, job.ID)
120-
if err != nil {
121-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
122-
Message: "Internal error watching provisioner logs.",
123-
Detail: err.Error(),
124-
})
125-
return
126-
}
127-
defer closeFollow()
128-
bufferedLogs = bl
129-
}
130-
131157
for {
132158
select {
133159
case <-ctx.Done():

0 commit comments

Comments
 (0)