File size: 2,036 Bytes
fea99b3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | package entutils
import (
"errors"
"fmt"
"github.com/samber/lo"
"github.com/openmeterio/openmeter/pkg/models"
)
type InIDOrderAccessor interface {
IDMixinGetter
NamespaceMixinGetter
}
var (
ErrNamespaceRequired = errors.New("namespace is required")
ErrIDRequired = errors.New("id is required")
ErrDuplicateID = errors.New("duplicate id")
ErrNotFound = errors.New("not found")
)
func InIDOrder[T InIDOrderAccessor](namespace string, targetOrderIDs []string, results []T) ([]T, error) {
// Input validation (let's make sure that namespace/id is set for all entities)
if namespace == "" {
return nil, ErrNamespaceRequired
}
for _, id := range targetOrderIDs {
if id == "" {
return nil, ErrIDRequired
}
}
for _, result := range results {
namespacedID := models.NamespacedID{
Namespace: result.GetNamespace(),
ID: result.GetID(),
}
if err := namespacedID.Validate(); err != nil {
return nil, err
}
}
// Logic implementation
if len(targetOrderIDs) == 0 && len(results) == 0 {
return results, nil
}
entitiesByID := lo.GroupBy(results, func(result T) models.NamespacedID {
return models.NamespacedID{
Namespace: result.GetNamespace(),
ID: result.GetID(),
}
})
// Check for duplicate results
for id, entities := range entitiesByID {
if len(entities) > 1 {
return nil, fmt.Errorf("%w [id=%s, count=%d]", ErrDuplicateID, id, len(entities))
}
}
// We allow for more entities being present in the results set, as we are not filtering for namespace for the query to allow
// multi-namespace listing as needed.
var errs []error
out := make([]T, 0, len(targetOrderIDs))
for _, id := range targetOrderIDs {
entities, ok := entitiesByID[models.NamespacedID{Namespace: namespace, ID: id}]
if !ok {
errs = append(errs, fmt.Errorf("%w [id=%s]", ErrNotFound, id))
continue
}
out = append(out, entities...)
}
if len(errs) > 0 {
return nil, models.NewGenericNotFoundError(errors.Join(errs...))
}
return out, nil
}
|