changeset 398:0b8921797064

To reduce the number of REST calls to the GeoServer when publishing gemma tables fetch all the features of the datastore at once instead of querying each table/feature for existence. Speeds up the startup significantly when publishing more features.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 14 Aug 2018 11:44:29 +0200
parents b5555bf6d45c
children 6c09aa214948
files cmd/gemma/geoserver.go
diffstat 1 files changed, 54 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/cmd/gemma/geoserver.go	Tue Aug 14 09:59:55 2018 +0200
+++ b/cmd/gemma/geoserver.go	Tue Aug 14 11:44:29 2018 +0200
@@ -181,33 +181,65 @@
 		tables   = config.GeoServerTables()
 	)
 
+	if len(tables) == 0 {
+		log.Println("info: no tables to publish")
+		return nil
+	}
+
 	log.Printf("info: number of tables to publish %d\n", len(tables))
 
+	var features struct {
+		FeatureTypes struct {
+			FeatureType []struct {
+				Name string `json:"name"`
+			} `json:"featureType"`
+		} `json:"featureTypes"`
+	}
+
+	hasFeature := func(name string) bool {
+		for _, ft := range features.FeatureTypes.FeatureType {
+			if ft.Name == name {
+				return true
+			}
+		}
+		return false
+	}
+
+	// Fetch all featuretypes.
+	req, err := http.NewRequest(
+		http.MethodGet,
+		url+"/rest/workspaces/"+workspaceName+
+			"/datastores/"+datastoreName+
+			"/featuretypes.json",
+		nil)
+	if err != nil {
+		return err
+	}
+	auth(req)
+	resp, err := http.DefaultClient.Do(req)
+	if err != nil {
+		return err
+	}
+
+	err = json.NewDecoder(resp.Body).Decode(&features)
+	resp.Body.Close()
+	if err != nil {
+		// XXX: Quirk in the JSON return by GeoServer:
+		// If there are no features in the datastore
+		// featureType deserializes to an empty string ""
+		// instead of an empty array *palmface*.
+		// So assume there no features.
+		hasFeature = func(string) bool { return false }
+	}
+
 	for _, table := range tables {
-		log.Printf("checking layer %s\n", table)
-		// Probe  featuretype.
-		req, err := http.NewRequest(
-			http.MethodGet,
-			url+"/rest/workspaces/"+workspaceName+
-				"/datastores/"+datastoreName+
-				"/featuretypes/"+table+".json",
-			nil)
-		if err != nil {
-			return err
-		}
-		auth(req)
-		resp, err := http.DefaultClient.Do(req)
-		if err != nil {
-			return err
-		}
-
-		if resp.StatusCode != http.StatusNotFound {
-			log.Println("info: featuretype " + table + " already exists.")
+		if hasFeature(table) {
+			log.Printf("info: featuretype %s already exists.\n", table)
 			continue
 		}
 
 		// Create featuretype.
-		log.Printf("info: creating featuretype %s\n", table)
+		log.Printf("info: creating featuretype %s.\n", table)
 
 		// Create featuretype
 		ft := map[string]interface{}{
@@ -224,7 +256,7 @@
 			return err
 		}
 
-		req, err = http.NewRequest(
+		req, err := http.NewRequest(
 			http.MethodPost,
 			url+"/rest/workspaces/"+workspaceName+
 				"/datastores/"+datastoreName+
@@ -235,7 +267,7 @@
 		}
 		auth(req)
 		asJSON(req)
-		resp, err = http.DefaultClient.Do(req)
+		resp, err := http.DefaultClient.Do(req)
 		if err != nil {
 			return err
 		}