// getWorkFromSpec forcibly retrieves a work unit from a work spec. // It could create a work unit if spec is a continuous spec with no // available units. It ignores other constraints, such as whether the // work spec is paused. func (w *worker) getWorkFromSpec(spec *workSpec, meta *coordinate.WorkSpecMeta) *attempt { var unit *workUnit now := w.Coordinate().clock.Now() if len(spec.available) != 0 { unit = spec.available.Next() } else if meta.CanStartContinuous(now) { // Make a brand new work unit. Its key is the string // form of a time_t. seconds := now.Unix() nano := now.Nanosecond() milli := nano / 1000000 name := fmt.Sprintf("%d.%03d", seconds, milli) var exists bool unit, exists = spec.workUnits[name] if !exists { unit = &workUnit{ name: name, data: map[string]interface{}{}, workSpec: spec, } spec.workUnits[name] = unit } spec.meta.NextContinuous = now.Add(meta.Interval) } else { return nil } return w.makeAttempt(unit, time.Duration(0)) }
func (w *worker) requestAttemptsForSpec(req coordinate.AttemptRequest, spec *workSpec, meta *coordinate.WorkSpecMeta) ([]coordinate.Attempt, error) { var ( attempts []coordinate.Attempt count int err error ) // Adjust the work unit count based on what's possible here count = req.NumberOfWorkUnits if count < 1 { count = 1 } if meta.MaxAttemptsReturned > 0 && count > meta.MaxAttemptsReturned { count = meta.MaxAttemptsReturned } if meta.MaxRunning > 0 && count > meta.MaxRunning-meta.PendingCount { count = meta.MaxRunning - meta.PendingCount } // Now choose units and create attempts err = withTx(w, func(tx *sql.Tx) error { units, err := w.chooseWorkUnits(tx, spec, count) if err != nil { return err } now := w.Coordinate().clock.Now() if len(units) == 0 && meta.CanStartContinuous(now) { units, err = w.createContinuousUnits(tx, spec, meta) } if err != nil { return err } length := time.Duration(15) * time.Minute for _, unit := range units { a, err := makeAttempt(tx, unit, w, length) if err != nil { return err } attempts = append(attempts, a) } return nil }) return attempts, err }