From 9a8459d48b41393defc53cb02b47ce9706e0c8bb Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 30 Sep 2022 15:41:57 -0400 Subject: [PATCH] chore: Optimize Filter() for small lists --- coderd/rbac/authz.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/coderd/rbac/authz.go b/coderd/rbac/authz.go index 3bc37d056400a..ab35be9081652 100644 --- a/coderd/rbac/authz.go +++ b/coderd/rbac/authz.go @@ -39,8 +39,26 @@ func Filter[O Objecter](ctx context.Context, auth Authorizer, subjID string, sub return objects, nil } objectType := objects[0].RBACObject().Type - filtered := make([]O, 0) + + // Running benchmarks on this function, it is **always** faster to call + // auth.ByRoleName on <10 objects. This is because the overhead of + // 'PrepareByRoleName'. Once we cross 10 objects, then it starts to become + // faster + if len(objects) < 10 { + for _, o := range objects { + rbacObj := o.RBACObject() + if rbacObj.Type != objectType { + return nil, xerrors.Errorf("object types must be uniform across the set (%s), found %s", objectType, rbacObj) + } + err := auth.ByRoleName(ctx, subjID, subjRoles, scope, action, o.RBACObject()) + if err == nil { + filtered = append(filtered, o) + } + } + return filtered, nil + } + prepared, err := auth.PrepareByRoleName(ctx, subjID, subjRoles, scope, action, objectType) if err != nil { return nil, xerrors.Errorf("prepare: %w", err)