*: add api to query last run per group
This commit is contained in:
parent
21447fc59d
commit
48ab496beb
|
@ -302,6 +302,7 @@ func (h *RunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
phaseFilter := q["phase"]
|
phaseFilter := q["phase"]
|
||||||
groups := q["group"]
|
groups := q["group"]
|
||||||
changeGroups := q["changegroup"]
|
changeGroups := q["changegroup"]
|
||||||
|
_, lastRun := q["lastrun"]
|
||||||
|
|
||||||
limitS := q.Get("limit")
|
limitS := q.Get("limit")
|
||||||
limit := DefaultRunsLimit
|
limit := DefaultRunsLimit
|
||||||
|
@ -327,7 +328,7 @@ func (h *RunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
start := q.Get("start")
|
start := q.Get("start")
|
||||||
|
|
||||||
runsResp, resp, err := h.runserviceClient.GetRuns(ctx, phaseFilter, groups, changeGroups, start, limit, asc)
|
runsResp, resp, err := h.runserviceClient.GetRuns(ctx, phaseFilter, groups, lastRun, changeGroups, start, limit, asc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
http.Error(w, err.Error(), http.StatusNotFound)
|
http.Error(w, err.Error(), http.StatusNotFound)
|
||||||
|
|
|
@ -361,6 +361,7 @@ func (h *RunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
changeGroups := query["changegroup"]
|
changeGroups := query["changegroup"]
|
||||||
groups := query["group"]
|
groups := query["group"]
|
||||||
|
_, lastRun := query["lastrun"]
|
||||||
|
|
||||||
limitS := query.Get("limit")
|
limitS := query.Get("limit")
|
||||||
limit := DefaultRunsLimit
|
limit := DefaultRunsLimit
|
||||||
|
@ -406,7 +407,7 @@ func (h *RunsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
err = h.readDB.Do(func(tx *db.Tx) error {
|
err = h.readDB.Do(func(tx *db.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
runs, err = h.readDB.GetRuns(tx, groups, phaseFilter, start, limit, sortOrder)
|
runs, err = h.readDB.GetRuns(tx, groups, lastRun, phaseFilter, start, limit, sortOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.log.Errorf("err: %+v", err)
|
h.log.Errorf("err: %+v", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -143,7 +143,7 @@ func (c *Client) GetArchive(ctx context.Context, taskID string, step int) (*http
|
||||||
return c.getResponse(ctx, "GET", "/executor/archives", q, nil, nil)
|
return c.getResponse(ctx, "GET", "/executor/archives", q, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetRuns(ctx context.Context, phaseFilter, groups, changeGroups []string, start string, limit int, asc bool) (*GetRunsResponse, *http.Response, error) {
|
func (c *Client) GetRuns(ctx context.Context, phaseFilter, groups []string, lastRun bool, changeGroups []string, start string, limit int, asc bool) (*GetRunsResponse, *http.Response, error) {
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
for _, phase := range phaseFilter {
|
for _, phase := range phaseFilter {
|
||||||
q.Add("phase", phase)
|
q.Add("phase", phase)
|
||||||
|
@ -151,6 +151,9 @@ func (c *Client) GetRuns(ctx context.Context, phaseFilter, groups, changeGroups
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
q.Add("group", group)
|
q.Add("group", group)
|
||||||
}
|
}
|
||||||
|
if lastRun {
|
||||||
|
q.Add("lastrun", "")
|
||||||
|
}
|
||||||
for _, changeGroup := range changeGroups {
|
for _, changeGroup := range changeGroups {
|
||||||
q.Add("changegroup", changeGroup)
|
q.Add("changegroup", changeGroup)
|
||||||
}
|
}
|
||||||
|
@ -170,19 +173,19 @@ func (c *Client) GetRuns(ctx context.Context, phaseFilter, groups, changeGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetQueuedRuns(ctx context.Context, start string, limit int) (*GetRunsResponse, *http.Response, error) {
|
func (c *Client) GetQueuedRuns(ctx context.Context, start string, limit int) (*GetRunsResponse, *http.Response, error) {
|
||||||
return c.GetRuns(ctx, []string{"queued"}, []string{"."}, nil, start, limit, true)
|
return c.GetRuns(ctx, []string{"queued"}, []string{}, false, nil, start, limit, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetGroupQueuedRuns(ctx context.Context, group string, limit int, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
func (c *Client) GetGroupQueuedRuns(ctx context.Context, group string, limit int, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
||||||
return c.GetRuns(ctx, []string{"queued"}, []string{group}, changeGroups, "", limit, false)
|
return c.GetRuns(ctx, []string{"queued"}, []string{group}, false, changeGroups, "", limit, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetGroupRunningRuns(ctx context.Context, group string, limit int, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
func (c *Client) GetGroupRunningRuns(ctx context.Context, group string, limit int, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
||||||
return c.GetRuns(ctx, []string{"running"}, []string{group}, changeGroups, "", limit, false)
|
return c.GetRuns(ctx, []string{"running"}, []string{group}, false, changeGroups, "", limit, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetGroupFirstQueuedRuns(ctx context.Context, group string, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
func (c *Client) GetGroupFirstQueuedRuns(ctx context.Context, group string, changeGroups []string) (*GetRunsResponse, *http.Response, error) {
|
||||||
return c.GetRuns(ctx, []string{"queued"}, []string{group}, changeGroups, "", 1, true)
|
return c.GetRuns(ctx, []string{"queued"}, []string{group}, false, changeGroups, "", 1, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateRun(ctx context.Context, req *RunCreateRequest) (*http.Response, error) {
|
func (c *Client) CreateRun(ctx context.Context, req *RunCreateRequest) (*http.Response, error) {
|
||||||
|
|
|
@ -349,14 +349,14 @@ func (r *ReadDB) Run(ctx context.Context) {
|
||||||
|
|
||||||
func (r *ReadDB) HandleEvents(ctx context.Context) error {
|
func (r *ReadDB) HandleEvents(ctx context.Context) error {
|
||||||
var revision int64
|
var revision int64
|
||||||
var lastRuns []*types.Run
|
var lastRuns []*RunData
|
||||||
err := r.rdb.Do(func(tx *db.Tx) error {
|
err := r.rdb.Do(func(tx *db.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
revision, err = r.getRevision(tx)
|
revision, err = r.getRevision(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lastRuns, err = r.GetActiveRuns(tx, nil, nil, "", 1, types.SortOrderDesc)
|
lastRuns, err = r.GetActiveRuns(tx, nil, true, nil, "", 1, types.SortOrderDesc)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -370,7 +370,7 @@ func (r *ReadDB) HandleEvents(ctx context.Context) error {
|
||||||
|
|
||||||
var lastRun *types.Run
|
var lastRun *types.Run
|
||||||
if len(lastRuns) > 0 {
|
if len(lastRuns) > 0 {
|
||||||
lastRun = lastRuns[0]
|
lastRun = lastRuns[0].Run
|
||||||
}
|
}
|
||||||
if lastRun != nil {
|
if lastRun != nil {
|
||||||
if runSequence == nil {
|
if runSequence == nil {
|
||||||
|
@ -685,8 +685,8 @@ func (r *ReadDB) GetChangeGroupsUpdateTokens(tx *db.Tx, groups []string) (*types
|
||||||
return &types.ChangeGroupsUpdateToken{CurRevision: revision, ChangeGroupsRevisions: changeGroupsRevisions}, nil
|
return &types.ChangeGroupsUpdateToken{CurRevision: revision, ChangeGroupsRevisions: changeGroupsRevisions}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) GetActiveRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*types.Run, error) {
|
func (r *ReadDB) GetActiveRuns(tx *db.Tx, groups []string, lastRun bool, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*RunData, error) {
|
||||||
return r.getRunsFilteredActive(tx, groups, phaseFilter, startRunID, limit, sortOrder)
|
return r.getRunsFilteredActive(tx, groups, lastRun, phaseFilter, startRunID, limit, sortOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) PrefetchRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) error {
|
func (r *ReadDB) PrefetchRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) error {
|
||||||
|
@ -712,7 +712,7 @@ func (r *ReadDB) PrefetchRuns(tx *db.Tx, groups []string, phaseFilter []types.Ru
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) GetRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*types.Run, error) {
|
func (r *ReadDB) GetRuns(tx *db.Tx, groups []string, lastRun bool, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*types.Run, error) {
|
||||||
useLTS := false
|
useLTS := false
|
||||||
for _, phase := range phaseFilter {
|
for _, phase := range phaseFilter {
|
||||||
if phase == types.RunPhaseFinished {
|
if phase == types.RunPhaseFinished {
|
||||||
|
@ -723,27 +723,44 @@ func (r *ReadDB) GetRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhas
|
||||||
useLTS = true
|
useLTS = true
|
||||||
}
|
}
|
||||||
|
|
||||||
runs, err := r.getRunsFilteredActive(tx, groups, phaseFilter, startRunID, limit, sortOrder)
|
runDataRDB, err := r.getRunsFilteredActive(tx, groups, lastRun, phaseFilter, startRunID, limit, sortOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !useLTS {
|
lastRunsMap := map[string]*RunData{}
|
||||||
return runs, err
|
runsMap := map[string]*RunData{}
|
||||||
}
|
for _, r := range runDataRDB {
|
||||||
|
|
||||||
// skip if the phase requested is not finished
|
|
||||||
runsltsIDs, err := r.getRunsFilteredLTS(tx, groups, startRunID, limit, sortOrder)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
runsMap := map[string]*types.Run{}
|
|
||||||
for _, r := range runs {
|
|
||||||
runsMap[r.ID] = r
|
runsMap[r.ID] = r
|
||||||
|
lastRunsMap[r.GroupPath] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
if useLTS {
|
||||||
|
// skip if the phase requested is not finished
|
||||||
|
runDataLTS, err := r.GetRunsFilteredLTS(tx, groups, lastRun, phaseFilter, startRunID, limit, sortOrder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rd := range runDataLTS {
|
||||||
|
if lastRun {
|
||||||
|
if lr, ok := lastRunsMap[rd.GroupPath]; ok {
|
||||||
|
switch sortOrder {
|
||||||
|
case types.SortOrderAsc:
|
||||||
|
if rd.ID < lr.ID {
|
||||||
|
lastRunsMap[rd.GroupPath] = rd
|
||||||
|
}
|
||||||
|
case types.SortOrderDesc:
|
||||||
|
if rd.ID > lr.ID {
|
||||||
|
lastRunsMap[rd.GroupPath] = rd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lastRunsMap[rd.GroupPath] = rd
|
||||||
|
runsMap[rd.ID] = rd
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runsMap[rd.ID] = rd
|
||||||
}
|
}
|
||||||
for _, runID := range runsltsIDs {
|
|
||||||
if _, ok := runsMap[runID]; !ok {
|
|
||||||
runsMap[runID] = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,14 +784,14 @@ func (r *ReadDB) GetRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhas
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
|
||||||
run := runsMap[runID]
|
rd := runsMap[runID]
|
||||||
if run != nil {
|
if rd.Run != nil {
|
||||||
aruns = append(aruns, run)
|
aruns = append(aruns, rd.Run)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// get run from lts
|
// get run from lts
|
||||||
run, err = store.LTSGetRun(r.wal, runID)
|
run, err := store.LTSGetRun(r.wal, runID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -785,13 +802,13 @@ func (r *ReadDB) GetRuns(tx *db.Tx, groups []string, phaseFilter []types.RunPhas
|
||||||
return aruns, nil
|
return aruns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) getRunsFilteredQuery(phaseFilter []types.RunPhase, groups []string, startRunID string, limit int, sortOrder types.SortOrder, lts bool) sq.SelectBuilder {
|
func (r *ReadDB) getRunsFilteredQuery(phaseFilter []types.RunPhase, groups []string, lastRun bool, startRunID string, limit int, sortOrder types.SortOrder, lts bool) sq.SelectBuilder {
|
||||||
runt := "run"
|
runt := "run"
|
||||||
runlabelt := "rungroup"
|
rungroupt := "rungroup"
|
||||||
fields := []string{"data"}
|
fields := []string{"data"}
|
||||||
if lts {
|
if lts {
|
||||||
runt = "run_lts"
|
runt = "run_lts"
|
||||||
runlabelt = "rungroup_lts"
|
rungroupt = "rungroup_lts"
|
||||||
fields = []string{"id"}
|
fields = []string{"id"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,20 +835,28 @@ func (r *ReadDB) getRunsFilteredQuery(phaseFilter []types.RunPhase, groups []str
|
||||||
s = s.Limit(uint64(limit))
|
s = s.Limit(uint64(limit))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = s.Join(fmt.Sprintf("%s as rungroup on rungroup.id = run.id", rungroupt))
|
||||||
if len(groups) > 0 {
|
if len(groups) > 0 {
|
||||||
s = s.Join(fmt.Sprintf("%s as rungroup on rungroup.runid = run.id", runlabelt))
|
|
||||||
cond := sq.Or{}
|
cond := sq.Or{}
|
||||||
for _, group := range groups {
|
for _, groupPath := range groups {
|
||||||
cond = append(cond, sq.Eq{"rungroup.grouppath": group})
|
// add ending slash to distinguish between final group (i.e project/projectid/branch/feature and project/projectid/branch/feature02)
|
||||||
|
if !strings.HasSuffix(groupPath, "/") {
|
||||||
|
groupPath += "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
cond = append(cond, sq.Like{"run.grouppath": groupPath + "%"})
|
||||||
}
|
}
|
||||||
s = s.Where(sq.Or{cond})
|
s = s.Where(sq.Or{cond})
|
||||||
|
if lastRun {
|
||||||
|
s = s.GroupBy("run.grouppath")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) getRunsFilteredActive(tx *db.Tx, groups []string, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*types.Run, error) {
|
func (r *ReadDB) getRunsFilteredActive(tx *db.Tx, groups []string, lastRun bool, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*RunData, error) {
|
||||||
s := r.getRunsFilteredQuery(phaseFilter, groups, startRunID, limit, sortOrder, false)
|
s := r.getRunsFilteredQuery(phaseFilter, groups, lastRun, startRunID, limit, sortOrder, false)
|
||||||
|
|
||||||
q, args, err := s.ToSql()
|
q, args, err := s.ToSql()
|
||||||
r.log.Debugf("q: %s, args: %s", q, util.Dump(args))
|
r.log.Debugf("q: %s, args: %s", q, util.Dump(args))
|
||||||
|
@ -842,8 +867,8 @@ func (r *ReadDB) getRunsFilteredActive(tx *db.Tx, groups []string, phaseFilter [
|
||||||
return fetchRuns(tx, q, args...)
|
return fetchRuns(tx, q, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) getRunsFilteredLTS(tx *db.Tx, groups []string, startRunID string, limit int, sortOrder types.SortOrder) ([]string, error) {
|
func (r *ReadDB) GetRunsFilteredLTS(tx *db.Tx, groups []string, lastRun bool, phaseFilter []types.RunPhase, startRunID string, limit int, sortOrder types.SortOrder) ([]*RunData, error) {
|
||||||
s := r.getRunsFilteredQuery(nil, groups, startRunID, limit, sortOrder, true)
|
s := r.getRunsFilteredQuery(phaseFilter, groups, lastRun, startRunID, limit, sortOrder, true)
|
||||||
|
|
||||||
q, args, err := s.ToSql()
|
q, args, err := s.ToSql()
|
||||||
r.log.Debugf("q: %s, args: %s", q, util.Dump(args))
|
r.log.Debugf("q: %s, args: %s", q, util.Dump(args))
|
||||||
|
@ -851,7 +876,7 @@ func (r *ReadDB) getRunsFilteredLTS(tx *db.Tx, groups []string, startRunID strin
|
||||||
return nil, errors.Wrap(err, "failed to build query")
|
return nil, errors.Wrap(err, "failed to build query")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetchRunsLTS(tx, q, args...)
|
return fetchRuns(tx, q, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReadDB) GetRun(runID string) (*types.Run, error) {
|
func (r *ReadDB) GetRun(runID string) (*types.Run, error) {
|
||||||
|
@ -882,10 +907,17 @@ func (r *ReadDB) getRun(tx *db.Tx, runID string) (*types.Run, error) {
|
||||||
if len(runs) == 0 {
|
if len(runs) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return runs[0], nil
|
return runs[0].Run, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchRuns(tx *db.Tx, q string, args ...interface{}) ([]*types.Run, error) {
|
type RunData struct {
|
||||||
|
ID string
|
||||||
|
GroupPath string
|
||||||
|
Phase string
|
||||||
|
Run *types.Run
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchRuns(tx *db.Tx, q string, args ...interface{}) ([]*RunData, error) {
|
||||||
rows, err := tx.Query(q, args...)
|
rows, err := tx.Query(q, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -894,38 +926,23 @@ func fetchRuns(tx *db.Tx, q string, args ...interface{}) ([]*types.Run, error) {
|
||||||
return scanRuns(rows)
|
return scanRuns(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchRunsLTS(tx *db.Tx, q string, args ...interface{}) ([]string, error) {
|
func scanRun(rows *sql.Rows) (*RunData, error) {
|
||||||
rows, err := tx.Query(q, args...)
|
r := &RunData{}
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
return scanRunsLTS(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanRun(rows *sql.Rows) (*types.Run, error) {
|
|
||||||
var data []byte
|
var data []byte
|
||||||
if err := rows.Scan(&data); err != nil {
|
if err := rows.Scan(&r.ID, &r.GroupPath, &r.Phase, &data); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to scan rows")
|
return nil, errors.Wrap(err, "failed to scan rows")
|
||||||
}
|
}
|
||||||
var run *types.Run
|
if len(data) > 0 {
|
||||||
if err := json.Unmarshal(data, &run); err != nil {
|
if err := json.Unmarshal(data, &r.Run); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to unmarshal run")
|
return nil, errors.Wrap(err, "failed to unmarshal run")
|
||||||
}
|
}
|
||||||
|
|
||||||
return run, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanRunLTS(rows *sql.Rows) (string, error) {
|
|
||||||
var id string
|
|
||||||
if err := rows.Scan(&id); err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to scan rows")
|
|
||||||
}
|
}
|
||||||
return id, nil
|
|
||||||
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanRuns(rows *sql.Rows) ([]*types.Run, error) {
|
func scanRuns(rows *sql.Rows) ([]*RunData, error) {
|
||||||
runs := []*types.Run{}
|
runs := []*RunData{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
r, err := scanRun(rows)
|
r, err := scanRun(rows)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -939,21 +956,6 @@ func scanRuns(rows *sql.Rows) ([]*types.Run, error) {
|
||||||
return runs, nil
|
return runs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanRunsLTS(rows *sql.Rows) ([]string, error) {
|
|
||||||
ids := []string{}
|
|
||||||
for rows.Next() {
|
|
||||||
r, err := scanRunLTS(rows)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ids = append(ids, r)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ids, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchChangeGroupsRevision(tx *db.Tx, q string, args ...interface{}) (types.ChangeGroupsRevisions, error) {
|
func fetchChangeGroupsRevision(tx *db.Tx, q string, args ...interface{}) (types.ChangeGroupsRevisions, error) {
|
||||||
rows, err := tx.Query(q, args...)
|
rows, err := tx.Query(q, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue