diff pkg/controllers/importqueue.go @ 1189:3d50f558870c

REST GET call to /imports now has the ability to be filtered by kinds or states. Something like &states=queued,running,failed,pending,accepted&kinds=sr Note: The states are not the current states of the import queue, yet. The import queue will be adjusted soon.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 16 Nov 2018 12:08:46 +0100
parents a04126989d91
children 3afa71405b87
line wrap: on
line diff
--- a/pkg/controllers/importqueue.go	Thu Nov 15 19:06:53 2018 +0100
+++ b/pkg/controllers/importqueue.go	Fri Nov 16 12:08:46 2018 +0100
@@ -14,17 +14,22 @@
 package controllers
 
 import (
+	"context"
 	"database/sql"
 	"fmt"
+	"log"
 	"net/http"
 	"strconv"
+	"strings"
 
+	"gemma.intevation.de/gemma/pkg/imports"
 	"gemma.intevation.de/gemma/pkg/models"
 	"github.com/gorilla/mux"
+	"github.com/jackc/pgx/pgtype"
 )
 
 const (
-	selectImportsUnpagedSQL = `
+	selectImportsSQL = `
 SELECT
   id,
   state::varchar,
@@ -32,10 +37,7 @@
   kind,
   username
 FROM waterway.imports
-ORDER BY id`
-
-	selectImportPagedSQL = selectImportsUnpagedSQL + `
-LIMIT $1 OFFSET $2`
+`
 
 	selectHasImportSQL = `
 SELECT true FROM Waterway.imports WHERE id = $1`
@@ -60,27 +62,96 @@
 DELETE FROM waterway.imports WHERE id = $1`
 )
 
+func toTextArray(txt string, allowed []string) *pgtype.TextArray {
+	parts := strings.Split(txt, ",")
+	var accepted []string
+	for _, part := range parts {
+		if part = strings.ToLower(strings.TrimSpace(part)); len(part) == 0 {
+			continue
+		}
+		for _, a := range allowed {
+			if part == a {
+				accepted = append(accepted, part)
+				break
+			}
+		}
+	}
+	if len(accepted) == 0 {
+		return nil
+	}
+	var ta pgtype.TextArray
+	if err := ta.Set(accepted); err != nil {
+		log.Printf("warn: %v\n", err)
+		return nil
+	}
+	return &ta
+}
+
+func queryImportListStmt(
+	conn *sql.Conn,
+	ctx context.Context,
+	vars map[string]string,
+) (*sql.Rows, error) {
+
+	var (
+		stmt   strings.Builder
+		args   []interface{}
+		states *pgtype.TextArray
+		kinds  *pgtype.TextArray
+	)
+
+	if st, found := vars["states"]; found {
+		states = toTextArray(st, imports.ImportStateNames)
+	}
+
+	if ks, found := vars["kinds"]; found {
+		kinds = toTextArray(ks, imports.ImportKindNames)
+	}
+
+	stmt.WriteString(selectImportsSQL)
+	if states != nil || kinds != nil {
+		stmt.WriteString(" WHERE ")
+	}
+
+	if states != nil {
+		fmt.Fprintf(&stmt, " states = ANY($%d) ", len(args)+1)
+		args = append(args, states)
+	}
+
+	if states != nil && kinds != nil {
+		stmt.WriteString("AND")
+	}
+
+	if kinds != nil {
+		fmt.Fprintf(&stmt, " kind = ANY($%d) ", len(args)+1)
+		args = append(args, kinds)
+	}
+
+	stmt.WriteString(" ORDER BY enqueued DESC ")
+
+	if lim, found := vars["limit"]; found {
+		fmt.Fprintf(&stmt, " LIMIT $%d ", len(args)+1)
+		limit, _ := strconv.ParseInt(lim, 10, 64)
+		args = append(args, limit)
+	}
+
+	if ofs, found := vars["offset"]; found {
+		fmt.Fprintf(&stmt, " OFFSET $%d ", len(args)+1)
+		offset, _ := strconv.ParseInt(ofs, 10, 64)
+		args = append(args, offset)
+	}
+
+	return conn.QueryContext(ctx, stmt.String(), args...)
+}
+
 func listImports(
 	_ interface{},
 	req *http.Request,
 	conn *sql.Conn,
 ) (jr JSONResult, err error) {
-	vars := mux.Vars(req)
-
-	off, of := vars["offset"]
-	lim, lf := vars["limit"]
 
 	var rows *sql.Rows
-
-	if of && lf {
-		offset, _ := strconv.ParseInt(off, 10, 64)
-		limit, _ := strconv.ParseInt(lim, 10, 64)
-		rows, err = conn.QueryContext(
-			req.Context(), selectImportPagedSQL, limit, offset)
-	} else {
-		rows, err = conn.QueryContext(
-			req.Context(), selectImportsUnpagedSQL)
-	}
+	rows, err = queryImportListStmt(conn, req.Context(), mux.Vars(req))
 	if err != nil {
 		return
 	}