Skip to content

Commit

Permalink
Add dispatch and cached dispatch counts to response trailer metadata
Browse files Browse the repository at this point in the history
All dispatched API operations will now contain the count of dispatched calls and cached dispatched calls, for complexity tracking via the new responsemeta package
  • Loading branch information
josephschorr authored and ecordell committed Dec 6, 2021
1 parent 6e6fb58 commit c7d6b03
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 29 deletions.
6 changes: 3 additions & 3 deletions go.mod
Expand Up @@ -5,7 +5,7 @@ go 1.16
require (
github.com/Masterminds/squirrel v1.5.1
github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a
github.com/authzed/authzed-go v0.3.1-0.20211109190421-0b30d667df2e
github.com/authzed/authzed-go v0.3.1-0.20211130221323-9d59da6e55da
github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6
github.com/aws/aws-sdk-go v1.41.15
github.com/benbjohnson/clock v1.2.0
Expand All @@ -22,8 +22,8 @@ require (
github.com/google/go-cmp v0.5.6
github.com/google/uuid v1.3.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
Expand Down
19 changes: 12 additions & 7 deletions go.sum
Expand Up @@ -73,8 +73,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/authzed/authzed-go v0.3.1-0.20211109190421-0b30d667df2e h1:UmsD/3lWJ3BXOGGvRTbLkrNOcaR4X+GIQldcX7e0Oyg=
github.com/authzed/authzed-go v0.3.1-0.20211109190421-0b30d667df2e/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y=
github.com/authzed/authzed-go v0.3.1-0.20211130221323-9d59da6e55da h1:dcjIyi2Om9CDAmEKiwQZsF7bV0x4PXuJeoN11BbbXXI=
github.com/authzed/authzed-go v0.3.1-0.20211130221323-9d59da6e55da/go.mod h1:bsUniBRroq4l5WZMYLO+T9osQa/P2qMwZ+Af8zoJK8Y=
github.com/authzed/grpcutil v0.0.0-20210913124023-cad23ae5a9e8/go.mod h1:HwO/KbRU3fWXEYHE96kvXnwxzi97tkXD1hfi5UaZ71Y=
github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6 h1:izP/rEris51ZmomXb5J0ShyJKqsxTfVKDRnJz0QGbgg=
github.com/authzed/grpcutil v0.0.0-20211020204402-aba1876830e6/go.mod h1:rqjY3zyK/YP7NID9+B2BdIRRkvnK+cdf9/qya/zaFZE=
Expand Down Expand Up @@ -286,11 +286,11 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2 h1:uxUHSMwWDJ/9jVPHNumRC8WZOi3hrBL22ObVOoLg4ww=
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2/go.mod h1:BL7w7qd2l/j9jgY6WMhYutfOFQc0I8RTVwtjpnAMoTM=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-20200501113911-9a95f0fdbfea/go.mod h1:GugMBs30ZSAkckqXEAIEGyYdDH6EgqowG8ppA3Zt+AY=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2 h1:1aeRCnE2CkKYqyzBu0+B2lgTcZPc3ea2lGpijeHbI1c=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k=
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252 h1:CuS+fcV/k5xwYRkldUXG3pwjO+1j5r+Yg2q3tLRC8Vg=
github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252/go.mod h1:54asssGY3Bohr5FRbew+bjfuQTT2WS9V7hW7gPqmcKM=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201002093600-73cf2ae9d891/go.mod h1:GhphxcdlaRyAuBSvo6rV71BvQcvB/vuX8ugCyybuS2k=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252 h1:lZkQBC6+/moYFaKaMDUuYot/8uwZePmJVZLLaaOrnl0=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20210831071041-dd1540ef8252/go.mod h1:Cv6t7kukbxd9Mh/mkHC2cqQ4utDtMRXWTugC64Y7qjA=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
Expand Down Expand Up @@ -513,6 +513,7 @@ github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04s
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/ory/dockertest/v3 v3.8.0 h1:i5b0cJCd801qw0cVQUOH6dSpI9fT3j5tdWu0jKu90ks=
github.com/ory/dockertest/v3 v3.8.0/go.mod h1:9zPATATlWQru+ynXP+DytBQrsXV7Tmlx7K86H6fQaDo=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
Expand Down Expand Up @@ -810,6 +811,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
Expand All @@ -830,6 +832,7 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
Expand Down Expand Up @@ -1087,6 +1090,7 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
Expand Down Expand Up @@ -1144,6 +1148,7 @@ google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzI
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand Down
138 changes: 138 additions & 0 deletions internal/middleware/usagemetrics/usagemetrics.go
@@ -0,0 +1,138 @@
package usagemetrics

import (
"context"
"strconv"
"time"

"github.com/authzed/authzed-go/pkg/responsemeta"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors"
prometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/rs/zerolog/log"
"google.golang.org/grpc"

dispatch "github.com/authzed/spicedb/internal/proto/dispatch/v1"
)

var dispatchBuckets = []float64{1, 5, 10, 25, 50, 100, 250}

var dispatchedCountHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "spicedb",
Subsystem: "services",
Name: "dispatched_count_histogram",
Help: "dispatch count per api call distribution in seconds.",
Buckets: dispatchBuckets,
}, []string{"method"})

var cachedCountHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "spicedb",
Subsystem: "services",
Name: "cached_count_histogram",
Help: "dispatches avoid by caching per api call in seconds.",
Buckets: dispatchBuckets,
}, []string{"method"})

var dispatchedCounter = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "spicedb",
Subsystem: "services",
Name: "dispatched_counter",
Help: "dispatch counts.",
}, []string{"method"})

var cachedCounter = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "spicedb",
Subsystem: "services",
Name: "cached_counter",
Help: "dispatches avoid by caching.",
}, []string{"method"})

type reporter struct{}

func (r *reporter) ServerReporter(ctx context.Context, callMeta interceptors.CallMeta) (interceptors.Reporter, context.Context) {
_, methodName := interceptors.SplitMethodName(callMeta.FullMethod())
ctx = ContextWithHandle(ctx)
return &serverReporter{ctx: ctx, methodName: methodName}, ctx
}

type serverReporter struct {
interceptors.NoopReporter
ctx context.Context
methodName string
}

func (r *serverReporter) PostCall(err error, rpcDuration time.Duration) {
responseMeta := FromContext(r.ctx)
if responseMeta != nil {
err := annotateAndReportForMetadata(r.ctx, r.methodName, responseMeta)
if err != nil {
log.Ctx(r.ctx).Err(err).Msg("could not report metadata")
}
}
}

// UnaryServerInterceptor implements a gRPC Middleware for reporting usage metrics
// in both the trailer of the request, as well as to the registered prometheus
// metrics.
func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
return interceptors.UnaryServerInterceptor(&reporter{})
}

// StreamServerInterceptor implements a gRPC Middleware for reporting usage metrics
// in both the trailer of the request, as well as to the registered prometheus
// metrics
func StreamServerInterceptor() grpc.StreamServerInterceptor {
return interceptors.StreamServerInterceptor(&reporter{})
}

func annotateAndReportForMetadata(ctx context.Context, methodName string, metadata *dispatch.ResponseMeta) error {
dispatchedCountHistogram.WithLabelValues(methodName).Observe(float64(metadata.DispatchCount))
cachedCountHistogram.WithLabelValues(methodName).Observe(float64(metadata.CachedDispatchCount))

dispatchedCounter.WithLabelValues(methodName).Add(float64(metadata.DispatchCount))
cachedCounter.WithLabelValues(methodName).Add(float64(metadata.CachedDispatchCount))

return responsemeta.SetResponseTrailerMetadata(ctx, map[responsemeta.ResponseMetadataTrailerKey]string{
responsemeta.DispatchedOperationsCount: strconv.Itoa(int(metadata.DispatchCount)),
responsemeta.CachedOperationsCount: strconv.Itoa(int(metadata.CachedDispatchCount)),
})
}

// Create a new type to prevent context collisions
type responseMetaKey string

var metadataCtxKey responseMetaKey = "dispatched-response-meta"

type metaHandle struct{ metadata *dispatch.ResponseMeta }

// SetInContext should be called in a gRPC handler to correctly set the response metadata
// for the dispatched request.
func SetInContext(ctx context.Context, metadata *dispatch.ResponseMeta) {
possibleHandle := ctx.Value(metadataCtxKey)
if possibleHandle == nil {
return
}

handle := possibleHandle.(*metaHandle)
handle.metadata = metadata
}

// FromContext returns any metadata that was stored in the context.
//
// This is useful for testing that a handler is properly setting the context.
func FromContext(ctx context.Context) *dispatch.ResponseMeta {
possibleHandle := ctx.Value(metadataCtxKey)
if possibleHandle == nil {
return nil
}
return possibleHandle.(*metaHandle).metadata
}

// ContextWithHandle creates a new context with a location to store metadata
// returned from a dispatched request.
//
// This should only be called in middleware or testing functions.
func ContextWithHandle(ctx context.Context) context.Context {
var handle metaHandle
return context.WithValue(ctx, metadataCtxKey, &handle)
}
14 changes: 13 additions & 1 deletion internal/services/v0/acl.go
Expand Up @@ -11,12 +11,14 @@ import (
grpcmw "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/rs/zerolog/log"
"github.com/shopspring/decimal"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/authzed/spicedb/internal/datastore"
"github.com/authzed/spicedb/internal/dispatch"
"github.com/authzed/spicedb/internal/graph"
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
"github.com/authzed/spicedb/internal/namespace"
v1 "github.com/authzed/spicedb/internal/proto/dispatch/v1"
"github.com/authzed/spicedb/internal/services/serviceerrors"
Expand Down Expand Up @@ -45,13 +47,19 @@ var errInvalidZookie = errors.New("invalid revision requested")

// NewACLServer creates an instance of the ACL server.
func NewACLServer(ds datastore.Datastore, nsm namespace.Manager, dispatch dispatch.Dispatcher, defaultDepth uint32) v0.ACLServiceServer {
middleware := []grpc.UnaryServerInterceptor{
usagemetrics.UnaryServerInterceptor(),
}

middleware = append(middleware, grpcutil.DefaultUnaryMiddleware...)

s := &aclServer{
ds: ds,
nsm: nsm,
dispatch: dispatch,
defaultDepth: defaultDepth,
WithUnaryServiceSpecificInterceptor: shared.WithUnaryServiceSpecificInterceptor{
Unary: grpcmw.ChainUnaryServer(grpcutil.DefaultUnaryMiddleware...),
Unary: grpcmw.ChainUnaryServer(middleware...),
},
}
return s
Expand Down Expand Up @@ -258,6 +266,8 @@ func (as *aclServer) commonCheck(
ObjectAndRelation: start,
Subject: goal,
})

usagemetrics.SetInContext(ctx, cr.Metadata)
if err != nil {
return nil, rewriteACLError(ctx, err)
}
Expand Down Expand Up @@ -298,6 +308,7 @@ func (as *aclServer) Expand(ctx context.Context, req *v0.ExpandRequest) (*v0.Exp
ObjectAndRelation: req.Userset,
ExpansionMode: v1.DispatchExpandRequest_SHALLOW,
})
usagemetrics.SetInContext(ctx, resp.Metadata)
if err != nil {
return nil, rewriteACLError(ctx, err)
}
Expand Down Expand Up @@ -342,6 +353,7 @@ func (as *aclServer) Lookup(ctx context.Context, req *v0.LookupRequest) (*v0.Loo
DirectStack: nil,
TtuStack: nil,
})
usagemetrics.SetInContext(ctx, resp.Metadata)
if err != nil {
return nil, rewriteACLError(ctx, err)
}
Expand Down
23 changes: 20 additions & 3 deletions internal/services/v0/acl_test.go
Expand Up @@ -9,6 +9,7 @@ import (
"testing"
"time"

"github.com/authzed/authzed-go/pkg/responsemeta"
v0 "github.com/authzed/authzed-go/proto/authzed/api/v0"
"github.com/authzed/grpcutil"
"github.com/rs/zerolog"
Expand All @@ -17,6 +18,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/test/bufconn"

"github.com/authzed/spicedb/internal/datastore"
Expand Down Expand Up @@ -527,14 +529,15 @@ func TestCheck(t *testing.T) {
AtRevision: zookie.NewFromRevision(revision),
})

var trailer metadata.MD
ccResp, ccErr := client.ContentChangeCheck(context.Background(), &v0.ContentChangeCheckRequest{
TestUserset: tc.start,
User: &v0.User{
UserOneof: &v0.User_Userset{
Userset: checkTest.user,
},
},
})
}, grpc.Trailer(&trailer))

if tc.expectedErrorCode == codes.OK {
require.NoError(err)
Expand All @@ -552,6 +555,10 @@ func TestCheck(t *testing.T) {
require.Equal(v0.CheckResponse_NOT_MEMBER, resp.Membership)
require.Equal(v0.CheckResponse_NOT_MEMBER, ccResp.Membership)
}

dispatchCount, err := responsemeta.GetIntResponseTrailerMetadata(trailer, responsemeta.DispatchedOperationsCount)
require.NoError(err)
require.GreaterOrEqual(dispatchCount, 0)
} else {
grpcutil.RequireStatus(t, tc.expectedErrorCode, err)
grpcutil.RequireStatus(t, tc.expectedErrorCode, ccErr)
Expand Down Expand Up @@ -607,16 +614,21 @@ func TestExpand(t *testing.T) {
client, stop, revision, _ := newACLServicer(require, delta, memdb.DisableGC, 0)
defer stop()

var trailer metadata.MD
expanded, err := client.Expand(context.Background(), &v0.ExpandRequest{
Userset: tc.start,
AtRevision: zookie.NewFromRevision(revision),
})
}, grpc.Trailer(&trailer))
if tc.expectedErrorCode == codes.OK {
require.NoError(err)
require.NotNil(expanded.Revision)
require.NotEmpty(expanded.Revision.Token)

require.Equal(tc.expandRelatedCount, len(g.Simplify(expanded.TreeNode)))

dispatchCount, err := responsemeta.GetIntResponseTrailerMetadata(trailer, responsemeta.DispatchedOperationsCount)
require.NoError(err)
require.GreaterOrEqual(dispatchCount, 0)
} else {
grpcutil.RequireStatus(t, tc.expectedErrorCode, err)
}
Expand Down Expand Up @@ -752,12 +764,13 @@ func TestLookup(t *testing.T) {
client, stop, revision, _ := newACLServicer(require, delta, memdb.DisableGC, 0)
defer stop()

var trailer metadata.MD
result, err := client.Lookup(context.Background(), &v0.LookupRequest{
User: tc.user,
ObjectRelation: tc.relation,
Limit: 100,
AtRevision: zookie.NewFromRevision(revision),
})
}, grpc.Trailer(&trailer))
if tc.expectedErrorCode == codes.OK {
require.NoError(err)
require.NotNil(result.Revision)
Expand Down Expand Up @@ -786,6 +799,10 @@ func TestLookup(t *testing.T) {
require.NoError(err)
require.Equal(true, checkResp.IsMember, "Object ID %s is not a member", objID)
}

dispatchCount, err := responsemeta.GetIntResponseTrailerMetadata(trailer, responsemeta.DispatchedOperationsCount)
require.NoError(err)
require.GreaterOrEqual(dispatchCount, 0)
} else {
grpcutil.RequireStatus(t, tc.expectedErrorCode, err)
}
Expand Down

0 comments on commit c7d6b03

Please sign in to comment.