2020-03-28 21:34:09 +00:00
|
|
|
package dist
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-04-04 21:13:45 +00:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"go.uber.org/zap"
|
2020-03-28 21:34:09 +00:00
|
|
|
|
2020-03-29 16:03:07 +00:00
|
|
|
"gitlab.com/slon/shad-go/distbuild/pkg/api"
|
2020-03-28 21:34:09 +00:00
|
|
|
"gitlab.com/slon/shad-go/distbuild/pkg/build"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Build struct {
|
|
|
|
ID build.ID
|
|
|
|
Graph *build.Graph
|
|
|
|
|
2020-04-04 21:36:53 +00:00
|
|
|
reverseFiles map[string]build.ID
|
|
|
|
|
2020-04-04 21:13:45 +00:00
|
|
|
l *zap.Logger
|
|
|
|
c *Coordinator
|
|
|
|
uploadDone chan struct{}
|
2020-03-28 21:34:09 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 21:13:45 +00:00
|
|
|
func NewBuild(graph *build.Graph, c *Coordinator) *Build {
|
2020-03-28 21:34:09 +00:00
|
|
|
id := build.NewID()
|
|
|
|
|
|
|
|
return &Build{
|
|
|
|
ID: id,
|
|
|
|
Graph: graph,
|
|
|
|
|
2020-04-04 21:36:53 +00:00
|
|
|
reverseFiles: make(map[string]build.ID),
|
|
|
|
|
2020-04-04 21:13:45 +00:00
|
|
|
l: c.log.With(zap.String("build_id", id.String())),
|
|
|
|
c: c,
|
|
|
|
uploadDone: make(chan struct{}),
|
2020-03-28 21:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-04 21:21:55 +00:00
|
|
|
func (b *Build) missingFiles() []build.ID {
|
|
|
|
var files []build.ID
|
2020-04-04 21:36:53 +00:00
|
|
|
|
|
|
|
for id, path := range b.Graph.SourceFiles {
|
2020-04-04 21:21:55 +00:00
|
|
|
files = append(files, id)
|
2020-04-04 21:36:53 +00:00
|
|
|
b.reverseFiles[path] = id
|
2020-04-04 21:21:55 +00:00
|
|
|
}
|
2020-04-04 21:36:53 +00:00
|
|
|
|
2020-04-04 21:21:55 +00:00
|
|
|
return files
|
|
|
|
}
|
|
|
|
|
2020-04-04 21:13:45 +00:00
|
|
|
func (b *Build) Run(ctx context.Context, w api.StatusWriter) error {
|
2020-04-04 21:21:55 +00:00
|
|
|
if err := w.Started(&api.BuildStarted{ID: b.ID, MissingFiles: b.missingFiles()}); err != nil {
|
2020-04-04 21:13:45 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
b.l.Debug("waiting for file upload")
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
|
|
|
|
case <-b.uploadDone:
|
|
|
|
}
|
|
|
|
b.l.Debug("file upload completed")
|
|
|
|
|
|
|
|
for _, job := range b.Graph.Jobs {
|
2020-04-05 12:00:33 +00:00
|
|
|
spec := api.JobSpec{
|
|
|
|
Job: job,
|
|
|
|
SourceFiles: make(map[build.ID]string),
|
|
|
|
Artifacts: make(map[build.ID]api.WorkerID),
|
|
|
|
}
|
|
|
|
|
2020-04-04 21:49:25 +00:00
|
|
|
for _, file := range job.Inputs {
|
|
|
|
spec.SourceFiles[b.reverseFiles[file]] = file
|
|
|
|
}
|
2020-04-04 21:13:45 +00:00
|
|
|
|
2020-04-05 12:00:33 +00:00
|
|
|
for _, id := range job.Deps {
|
|
|
|
workerID, ok := b.c.scheduler.LocateArtifact(id)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("artifact %q is missing in cache", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
spec.Artifacts[id] = workerID
|
|
|
|
}
|
|
|
|
|
2020-04-04 21:49:25 +00:00
|
|
|
s := b.c.scheduler.ScheduleJob(&spec)
|
2020-04-04 21:13:45 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return ctx.Err()
|
|
|
|
case <-s.Finished:
|
|
|
|
}
|
|
|
|
|
|
|
|
b.l.Debug("job finished", zap.String("job_id", job.ID.String()))
|
|
|
|
|
|
|
|
jobFinished := api.StatusUpdate{JobFinished: s.Result}
|
|
|
|
if err := w.Updated(&jobFinished); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
finished := api.StatusUpdate{BuildFinished: &api.BuildFinished{}}
|
|
|
|
return w.Updated(&finished)
|
2020-03-28 21:34:09 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 21:13:45 +00:00
|
|
|
func (b *Build) Signal(ctx context.Context, req *api.SignalRequest) (*api.SignalResponse, error) {
|
|
|
|
switch {
|
|
|
|
case req.UploadDone != nil:
|
|
|
|
select {
|
|
|
|
case <-b.uploadDone:
|
|
|
|
return nil, fmt.Errorf("upload already done")
|
|
|
|
default:
|
|
|
|
close(b.uploadDone)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unexpected signal kind")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &api.SignalResponse{}, nil
|
2020-03-28 21:34:09 +00:00
|
|
|
}
|