// PostBuild accepts a request to execute a build // for the named package, version, channel and SDK. // // POST /sudo/api/build // func PostBuild(c web.C, w http.ResponseWriter, r *http.Request) { ctx := context.FromC(c) name := r.FormValue("package") number := r.FormValue("version") channel := r.FormValue("channel") rev := r.FormValue("revision") sdk := r.FormValue("sdk") force := r.FormValue("force") // parse the revision number from string to int64 // format so that we can run version comparisons. revision, err := strconv.ParseInt(rev, 10, 64) if err != nil { w.WriteHeader(http.StatusBadRequest) return } // get the build from the datastore. If it does not // yet exist, populate fields required upon creation. build, err := datastore.GetBuild(ctx, name, number, channel, sdk) if err == nil && len(force) == 0 { w.WriteHeader(http.StatusConflict) return } else if err != nil { build.Name = name build.Version = number build.Channel = channel build.SDK = sdk build.Created = time.Now().UTC().Unix() } build.Revision = revision build.Status = resource.StatusPending build.Updated = time.Now().UTC().Unix() if err := datastore.PutBuild(ctx, build); err != nil { w.WriteHeader(http.StatusInternalServerError) return } work := worker.Work{build} go worker.Do(ctx, &work) w.WriteHeader(http.StatusNoContent) }
// do is a blocking function that waits for an // available worker to process work. func (d *Director) do(c context.Context, work *worker.Work) { d.markPending(work) var pool = pool.FromContext(c) var worker = <-pool.Reserve() // var worker worker.Worker // // // waits for an available worker. This is a blocking // // operation and will reject any nil workers to avoid // // a potential panic. // select { // case worker = <-pool.Reserve(): // if worker != nil { // break // } // } d.markStarted(work, worker) worker.Do(c, work) d.markComplete(work) pool.Release(worker) }