diff --git a/src/api/contexts/contexts.go b/src/api/contexts/contexts.go index b1c36f3..6cde63f 100644 --- a/src/api/contexts/contexts.go +++ b/src/api/contexts/contexts.go @@ -31,6 +31,7 @@ type ( Genotype constants.GenotypeQuery SampleIds []string Dataset uuid.UUID + DataType string PositionBounds } diff --git a/src/api/main.go b/src/api/main.go index 696ca13..87dae68 100644 --- a/src/api/main.go +++ b/src/api/main.go @@ -185,6 +185,9 @@ func main() { e.GET("/datasets/:dataset/data-types", variantsMvc.GetDatasetDataTypes, // middleware gam.MandateDatasetPathParam) + e.DELETE("/datasets/:dataset/data-types/:dataType", variantsMvc.ClearDataset, + gam.MandateDatasetPathParam, + gam.MandateDataTypePathParam) // TODO: refactor (deduplicate) -- e.GET("/variants/ingestion/run", variantsMvc.VariantsIngest, diff --git a/src/api/middleware/datasetMiddleware.go b/src/api/middleware/datasetMiddleware.go index 6025262..0a51bb7 100644 --- a/src/api/middleware/datasetMiddleware.go +++ b/src/api/middleware/datasetMiddleware.go @@ -56,6 +56,21 @@ func MandateDatasetPathParam(next echo.HandlerFunc) echo.HandlerFunc { } } +func MandateDataTypePathParam(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + dataType := c.Param("dataType") + if dataType != "variant" { + fmt.Printf("Invalid data-type provided: %s\n", dataType) + return c.JSON(http.StatusBadRequest, errors.CreateSimpleBadRequest( + fmt.Sprintf("invalid data-type %s - please provide a valid data-type (e.g. \"variant\")", dataType), + )) + } + gc := c.(*contexts.GohanContext) + gc.DataType = dataType + return next(gc) + } +} + /* Echo middleware to ensure a `dataset` HTTP query parameter is valid if provided */ diff --git a/src/api/mvc/variants/main.go b/src/api/mvc/variants/main.go index f49b9ec..0b06178 100644 --- a/src/api/mvc/variants/main.go +++ b/src/api/mvc/variants/main.go @@ -558,6 +558,41 @@ func GetDatasetSummary(c echo.Context) error { } } +func ClearDataset(c echo.Context) error { + gc := c.(*contexts.GohanContext) + cfg := gc.Config + es := gc.Es7Client + + dataset := gc.Dataset + dataType := gc.DataType + fmt.Printf("[%s] - ClearDataset hit: [%s] - [%s]!\n", time.Now(), dataset.String(), dataType) + + var ( + deletionCount = 0.0 + g = new(errgroup.Group) + ) + // request #1 + g.Go(func() error { + deleteResponse, delErr := esRepo.DeleteVariantsByDatasetId(cfg, es, dataset.String()) + + if delErr != nil { + fmt.Printf("Failed to delete dataset %s variants\n", dataset) + return delErr + } + + deletionCount = deleteResponse["deleted"].(float64) + + return nil + }) + + if err := g.Wait(); err == nil { + fmt.Printf("Deleted %f variants from dataset %s\n", deletionCount, dataset) + return c.NoContent(http.StatusNoContent) + } else { + return c.JSON(http.StatusInternalServerError, errors.CreateSimpleInternalServerError("Something went wrong.. Please try again later!")) + } +} + type DataTypeSummary struct { Id string `json:"id"` Label string `json:"label"` diff --git a/src/api/repositories/elasticsearch/variants.go b/src/api/repositories/elasticsearch/variants.go index e5dc733..32b1f96 100644 --- a/src/api/repositories/elasticsearch/variants.go +++ b/src/api/repositories/elasticsearch/variants.go @@ -668,6 +668,62 @@ func GetVariantsBucketsByKeywordAndDataset(cfg *models.Config, es *elasticsearch return result, nil } +func DeleteVariantsByDatasetId(cfg *models.Config, es *elasticsearch.Client, dataset string) (map[string]interface{}, error) { + + var buf bytes.Buffer + query := map[string]interface{}{ + "query": map[string]interface{}{ + "match": map[string]interface{}{ + "dataset": dataset, + }, + }, + } + + if err := json.NewEncoder(&buf).Encode(query); err != nil { + log.Fatalf("Error encoding query: %s\n", query) + } + + if cfg.Debug { + // view the outbound elasticsearch query + myString := string(buf.Bytes()[:]) + fmt.Println(myString) + } + + // Perform the delete request. + deleteRes, deleteErr := es.DeleteByQuery( + []string{wildcardVariantsIndex}, + bytes.NewReader(buf.Bytes()), + ) + if deleteErr != nil { + fmt.Printf("Error getting response: %s\n", deleteErr) + return nil, deleteErr + } + + defer deleteRes.Body.Close() + + resultString := deleteRes.String() + if cfg.Debug { + fmt.Println(resultString) + } + + // Prepare an empty interface + result := make(map[string]interface{}) + + // Unmarshal or Decode the JSON to the empty interface. + // Known bug: response comes back with a preceding '[200 OK] ' which needs trimming + bracketString, jsonBodyString := utils.GetLeadingStringInBetweenSquareBrackets(resultString) + if !strings.Contains(bracketString, "200") { + return nil, fmt.Errorf("failed to get documents by id : got '%s'", bracketString) + } + umErr := json.Unmarshal([]byte(jsonBodyString), &result) + if umErr != nil { + fmt.Printf("Error unmarshalling variant deletion response: %s\n", umErr) + return nil, umErr + } + + return result, nil +} + // -- internal use only -- func addAllelesToShouldMap(alleles []string, genotype c.GenotypeQuery, allelesShouldMap []map[string]interface{}) ([]map[string]interface{}, int) { minimumShouldMatch := 0