// 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 }