Run executes the job. the idea here is to run two goroutines to work on the job: doCleanFinish and heartbeat, then use the `r.cond` to wait until the job is either complete or failed. This function then sends the complete or failed message --- the exception to this is if something calls Fail() on
()
| 180 | // that goroutine on the context passed into Fail(), and it marks okToSend false to signal us here |
| 181 | // that this function should not also send a terminal message. |
| 182 | func (r *Runner) Run() { |
| 183 | start := time.Now() |
| 184 | ctx, span := r.startTrace(r.notStopped, tracing.FuncName()) |
| 185 | defer span.End() |
| 186 | |
| 187 | concurrentGauge := r.metrics.ConcurrentJobs.WithLabelValues(r.job.Provisioner) |
| 188 | concurrentGauge.Inc() |
| 189 | defer func() { |
| 190 | status := "success" |
| 191 | if r.failedJob != nil { |
| 192 | status = "failed" |
| 193 | } |
| 194 | |
| 195 | concurrentGauge.Dec() |
| 196 | if build := r.job.GetWorkspaceBuild(); build != nil { |
| 197 | r.metrics.WorkspaceBuilds.WithLabelValues( |
| 198 | build.Metadata.WorkspaceOwner, |
| 199 | build.Metadata.WorkspaceName, |
| 200 | build.Metadata.TemplateName, |
| 201 | build.Metadata.TemplateVersion, |
| 202 | build.Metadata.WorkspaceTransition.String(), |
| 203 | status, |
| 204 | ).Inc() |
| 205 | r.metrics.WorkspaceBuildTimings.WithLabelValues( |
| 206 | build.Metadata.TemplateName, |
| 207 | build.Metadata.TemplateVersion, |
| 208 | build.Metadata.WorkspaceTransition.String(), |
| 209 | status, |
| 210 | ).Observe(time.Since(start).Seconds()) |
| 211 | } |
| 212 | r.metrics.JobTimings.WithLabelValues(r.job.Provisioner, status).Observe(time.Since(start).Seconds()) |
| 213 | }() |
| 214 | |
| 215 | r.mutex.Lock() |
| 216 | defer r.mutex.Unlock() |
| 217 | defer r.stop() |
| 218 | |
| 219 | go r.doCleanFinish(ctx) |
| 220 | go r.heartbeatRoutine(ctx) |
| 221 | for r.failedJob == nil && r.completedJob == nil { |
| 222 | r.cond.Wait() |
| 223 | } |
| 224 | if !r.okToSend { |
| 225 | // nothing else to do. |
| 226 | return |
| 227 | } |
| 228 | if r.failedJob != nil { |
| 229 | span.RecordError(xerrors.New(r.failedJob.Error)) |
| 230 | span.SetStatus(codes.Error, r.failedJob.Error) |
| 231 | |
| 232 | r.logger.Debug(ctx, "sending FailedJob") |
| 233 | err := r.sender.FailJob(ctx, r.failedJob) |
| 234 | if err != nil { |
| 235 | r.logger.Error(ctx, "sending FailJob failed", slog.Error(err)) |
| 236 | } else { |
| 237 | r.logger.Debug(ctx, "sent FailedJob") |
| 238 | } |
| 239 | } else { |
nothing calls this directly
no test coverage detected