Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change jsonb search operator so hopefully the existing index will get used #345

Merged
merged 3 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions internal/api/controllers/public/runHostsList.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ func (this *controllers) ApiRunHostsList(ctx echo.Context, params ApiRunHostsLis
}

if labelFilters := middleware.GetDeepObject(ctx, "filter", "run", "labels"); len(labelFilters) > 0 {
for key, values := range labelFilters {
for _, value := range values {
queryBuilder.Where("runs.labels ->> ? = ?", key, value)
}
queryBuilder, err = addLabelFilterToQueryAsWhereClause(queryBuilder, labelFilters)
if err != nil {
instrumentation.PlaybookApiRequestError(ctx, err)
return echo.NewHTTPError(http.StatusInternalServerError, "Unable to handle labels query!")
}
}

Expand Down
39 changes: 35 additions & 4 deletions internal/api/controllers/public/runsList.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package public

import (
"encoding/json"
"fmt"
"net/http"
"playbook-dispatcher/internal/api/instrumentation"
Expand All @@ -12,6 +13,7 @@ import (

"github.com/labstack/echo/v4"
identityMiddleware "github.com/redhatinsights/platform-go-middlewares/identity"
"gorm.io/gorm"
)

func getOrderBy(params ApiRunsListParams) string {
Expand Down Expand Up @@ -88,10 +90,10 @@ func (this *controllers) ApiRunsList(ctx echo.Context, params ApiRunsListParams)
}

if labelFilters := middleware.GetDeepObject(ctx, "filter", "labels"); len(labelFilters) > 0 {
for key, values := range labelFilters {
for _, value := range values {
queryBuilder.Where("runs.labels ->> ? = ?", key, value)
}
queryBuilder, err = addLabelFilterToQueryAsWhereClause(queryBuilder, labelFilters)
if err != nil {
instrumentation.PlaybookApiRequestError(ctx, err)
return echo.NewHTTPError(http.StatusInternalServerError, "Unable to handle labels query!")
}
}

Expand Down Expand Up @@ -133,3 +135,32 @@ func (this *controllers) ApiRunsList(ctx echo.Context, params ApiRunsListParams)
Links: createLinks("/api/playbook-dispatcher/v1/runs", middleware.GetQueryString(ctx), getLimit(params.Limit), getOffset(params.Offset), int(total)),
})
}

func addLabelFilterToQueryAsWhereClause(queryBuilder *gorm.DB, labelFilters map[string][]string) (*gorm.DB, error) {
labels := make(map[string]string)

for key, values := range labelFilters {
// The inner for loop seems kind of odd. The labels are basically a
// hash map. As a result, you cannot have duplicate keys. However, it
// seems to be possible to pass in multiple values for the same key in
// the web request url. With the approach below, we will take the last
// value for duplicate keys that are passed in on the url.
// example: api/playbook-dispatcher/v1/runs?filter[labels][bar]=5678&filter[labels][bar]=1234"
for _, value := range values {
labels[key] = value
}
}

if len(labels) == 0 {
return queryBuilder, nil
}

labelsJson, err := json.Marshal(labels)
if err != nil {
return queryBuilder, fmt.Errorf("unable to marshal labels into json: %w", err)
}

queryBuilder.Where("runs.labels @> ?", string(labelsJson))

return queryBuilder, nil
}
4 changes: 4 additions & 0 deletions internal/api/instrumentation/probes.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ func PlaybookRunHostCreateError(ctx context.Context, err error, data []dbModel.R
errorTotal.WithLabelValues(labelDb, labelPlaybookRunHostCreate, requestType, api.GetApiVersion(ctx)).Inc()
}

func PlaybookApiRequestError(ctx echo.Context, err error) {
utils.GetLogFromEcho(ctx).Errorw("Unable to process api request", "error", err)
}

func PlaybookRunCancelError(ctx context.Context, err error) {
utils.GetLogFromContext(ctx).Errorw("Error canceling run", "error", err)
runCanceledErrorTotal.Inc()
Expand Down
Loading