shad-go/distbuild/pkg/dist/build.go

120 lines
2.3 KiB
Go
Raw Normal View History

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
}