// DelWorkUnits deletes work units from an existing work spec. If // options is empty, this does nothing. On success, returns the // number of work units deleted. func (jobs *JobServer) DelWorkUnits(workSpecName string, options map[string]interface{}) (int, string, error) { workSpec, err := jobs.Namespace.WorkSpec(workSpecName) var ( count int dwuOptions DelWorkUnitsOptions status coordinate.WorkUnitStatus ) if err == nil { err = decode(&dwuOptions, options) } if err == nil && !dwuOptions.All { status, err = translateWorkUnitStatus(dwuOptions.State) } if err == nil { var query coordinate.WorkUnitQuery if !dwuOptions.All { if dwuOptions.WorkUnitKeys != nil { query.Names = dwuOptions.WorkUnitKeys } else if status != coordinate.AnyStatus { query.Statuses = []coordinate.WorkUnitStatus{status} } } count, err = workSpec.DeleteWorkUnits(query) } return count, "", err }
// PrioritizeWorkUnits changes the priorities of some number of work // units. The actual work units are in options["work_unit_keys"]. A // higher priority results in the work units being scheduled sooner. func (jobs *JobServer) PrioritizeWorkUnits(workSpecName string, options map[string]interface{}) (bool, string, error) { var ( err error query coordinate.WorkUnitQuery workSpec coordinate.WorkSpec ) pwuOptions := PrioritizeWorkUnitsOptions{ Priority: math.NaN(), Adjustment: math.NaN(), } workSpec, err = jobs.Namespace.WorkSpec(workSpecName) if err == nil { err = decode(&pwuOptions, options) } if err == nil && pwuOptions.WorkUnitKeys == nil { return false, "missing work_unit_keys", err } if err == nil { query.Names = pwuOptions.WorkUnitKeys if !math.IsNaN(pwuOptions.Priority) { err = workSpec.SetWorkUnitPriorities(query, pwuOptions.Priority) } else if !math.IsNaN(pwuOptions.Adjustment) { err = workSpec.AdjustWorkUnitPriorities(query, pwuOptions.Adjustment) } } return err == nil, "", err }
// GetWorkUnits retrieves the keys and data dictionaries for some number // of work units. If options contains "work_unit_keys", those specific // work units are retrieved; otherwise the work units are based on // which of GetWorkUnitsOptions are present. // // On success, the return value is a slice of cborrpc.PythonTuple // objects where each contains the work unit key as a byte slice and // the data dictionary. func (jobs *JobServer) GetWorkUnits(workSpecName string, options map[string]interface{}) ([]interface{}, string, error) { var workUnits map[string]coordinate.WorkUnit gwuOptions := GetWorkUnitsOptions{ Limit: 1000, } spec, err := jobs.Namespace.WorkSpec(workSpecName) var decoder *mapstructure.Decoder if err == nil { config := mapstructure.DecoderConfig{ DecodeHook: mapstructure.ComposeDecodeHookFunc(gwuStateHook, cborrpc.DecodeBytesAsString), Result: &gwuOptions, } decoder, err = mapstructure.NewDecoder(&config) } if err == nil { err = decoder.Decode(options) } if err == nil { query := coordinate.WorkUnitQuery{ Names: gwuOptions.WorkUnitKeys, } if gwuOptions.WorkUnitKeys == nil { query.PreviousName = gwuOptions.Start query.Limit = gwuOptions.Limit } if gwuOptions.WorkUnitKeys == nil && gwuOptions.State != nil { query.Statuses = make([]coordinate.WorkUnitStatus, len(gwuOptions.State)) for i, state := range gwuOptions.State { query.Statuses[i], err = translateWorkUnitStatus(state) if err != nil { break } } } if err == nil { workUnits, err = spec.WorkUnits(query) } } if err != nil { return nil, "", err } // The marshalled result is a list of pairs of (key, data). var result []interface{} for name, unit := range workUnits { var data map[string]interface{} attempt, err := unit.ActiveAttempt() if err == nil && attempt != nil { data, err = attempt.Data() } if err == nil && data == nil { data, err = unit.Data() } if err != nil { return nil, "", err } tuple := cborrpc.PythonTuple{Items: []interface{}{[]byte(name), data}} result = append(result, tuple) } return result, "", nil }