From 2e392db1da94f2f05f990d97cbe1292e3e5faff3 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 6 Nov 2023 17:32:40 -0500 Subject: [PATCH] Fix handling of recursive calls via singleflight dispatch Fixes the singleflight dispatcher so that if it sees the same key, for the same request ID, singleflight is bypassed to ensure that a recursion error is properly raised. Note that this doesn't just directly raise an error in case the request ID is somehow overlapping. --- .../dispatch/singleflight/singleflight.go | 40 +++- ...legflight_test.go => singleflight_test.go} | 78 ++++-- internal/graph/computed/computecheck.go | 4 + internal/graph/graph.go | 1 + internal/graph/lookupsubjects.go | 2 + internal/graph/reachableresources.go | 1 + .../integrationtesting/consistency_test.go | 1 + .../consistencytestutil/accessibilityset.go | 2 + internal/services/v1/permissions.go | 12 +- pkg/development/validation.go | 1 + pkg/genutil/mapz/countingmap.go | 50 ++++ pkg/genutil/mapz/countingmap_test.go | 22 ++ pkg/middleware/requestid/requestid.go | 36 ++- pkg/proto/dispatch/v1/dispatch.pb.go | 224 +++++++++--------- pkg/proto/dispatch/v1/dispatch.pb.validate.go | 11 + pkg/proto/dispatch/v1/dispatch_vtproto.pb.go | 47 ++++ proto/internal/dispatch/v1/dispatch.proto | 1 + 17 files changed, 394 insertions(+), 139 deletions(-) rename internal/dispatch/singleflight/{singlegflight_test.go => singleflight_test.go} (59%) create mode 100644 pkg/genutil/mapz/countingmap.go create mode 100644 pkg/genutil/mapz/countingmap_test.go diff --git a/internal/dispatch/singleflight/singleflight.go b/internal/dispatch/singleflight/singleflight.go index e1b3fba963..a81b9e820e 100644 --- a/internal/dispatch/singleflight/singleflight.go +++ b/internal/dispatch/singleflight/singleflight.go @@ -13,6 +13,7 @@ import ( "github.com/authzed/spicedb/internal/dispatch" "github.com/authzed/spicedb/internal/dispatch/keys" + "github.com/authzed/spicedb/pkg/genutil/mapz" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" ) @@ -24,14 +25,23 @@ var singleFlightCount = promauto.NewCounterVec(prometheus.CounterOpts{ }, []string{"method", "shared"}) func New(delegate dispatch.Dispatcher, handler keys.Handler) dispatch.Dispatcher { - return &Dispatcher{delegate: delegate, keyHandler: handler} + return &Dispatcher{ + delegate: delegate, + keyHandler: handler, + checkByDispatchKey: mapz.NewCountingMultiMap[string, string](), + expandByDispatchKey: mapz.NewCountingMultiMap[string, string](), + } } type Dispatcher struct { - delegate dispatch.Dispatcher - keyHandler keys.Handler + delegate dispatch.Dispatcher + keyHandler keys.Handler + checkGroup singleflight.Group[string, *v1.DispatchCheckResponse] expandGroup singleflight.Group[string, *v1.DispatchExpandResponse] + + checkByDispatchKey *mapz.CountingMultiMap[string, string] + expandByDispatchKey *mapz.CountingMultiMap[string, string] } func (d *Dispatcher) DispatchCheck(ctx context.Context, req *v1.DispatchCheckRequest) (*v1.DispatchCheckResponse, error) { @@ -42,6 +52,18 @@ func (d *Dispatcher) DispatchCheck(ctx context.Context, req *v1.DispatchCheckReq } keyString := hex.EncodeToString(key) + + // Check if the key has already been part of a dispatch, for the *same* request ID. If so, this represents a + // likely recursive call, so we dispatch it to the delegate to avoid the singleflight from blocking it. + requestID := req.Metadata.RequestId + existed := d.checkByDispatchKey.Add(keyString, requestID) + defer d.checkByDispatchKey.Remove(keyString, requestID) + + if existed { + // Likely a recursive call. + return d.delegate.DispatchCheck(ctx, req) + } + v, isShared, err := d.checkGroup.Do(ctx, keyString, func(innerCtx context.Context) (*v1.DispatchCheckResponse, error) { return d.delegate.DispatchCheck(innerCtx, req) }) @@ -62,6 +84,18 @@ func (d *Dispatcher) DispatchExpand(ctx context.Context, req *v1.DispatchExpandR } keyString := hex.EncodeToString(key) + + // Check if the key has already been part of a dispatch, for the *same* request ID. If so, this represents a + // likely recursive call, so we dispatch it to the delegate to avoid the singleflight from blocking it. + requestID := req.Metadata.RequestId + existed := d.expandByDispatchKey.Add(keyString, requestID) + defer d.expandByDispatchKey.Remove(keyString, requestID) + + if existed { + // Likely a recursive call. + return d.delegate.DispatchExpand(ctx, req) + } + v, isShared, err := d.expandGroup.Do(ctx, keyString, func(ictx context.Context) (*v1.DispatchExpandResponse, error) { return d.delegate.DispatchExpand(ictx, req) }) diff --git a/internal/dispatch/singleflight/singlegflight_test.go b/internal/dispatch/singleflight/singleflight_test.go similarity index 59% rename from internal/dispatch/singleflight/singlegflight_test.go rename to internal/dispatch/singleflight/singleflight_test.go index 6405fba2e2..afa12528e4 100644 --- a/internal/dispatch/singleflight/singlegflight_test.go +++ b/internal/dispatch/singleflight/singleflight_test.go @@ -23,27 +23,42 @@ func TestSingleFlightDispatcher(t *testing.T) { } disp := New(mockDispatcher{f: f}, &keys.DirectKeyHandler{}) - req := &v1.DispatchCheckRequest{ - ResourceRelation: tuple.RelationReference("document", "view"), - ResourceIds: []string{"foo", "bar"}, - Subject: tuple.ObjectAndRelation("user", "tom", "..."), - Metadata: &v1.ResolverMeta{ - AtRevision: "1234", - }, - } - wg := sync.WaitGroup{} wg.Add(4) go func() { - _, _ = disp.DispatchCheck(context.Background(), req) + _, _ = disp.DispatchCheck(context.Background(), &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "first", + }, + }) wg.Done() }() go func() { - _, _ = disp.DispatchCheck(context.Background(), req) + _, _ = disp.DispatchCheck(context.Background(), &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "second", + }, + }) wg.Done() }() go func() { - _, _ = disp.DispatchCheck(context.Background(), req) + _, _ = disp.DispatchCheck(context.Background(), &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "third", + }, + }) wg.Done() }() @@ -74,35 +89,50 @@ func TestSingleFlightDispatcherCancelation(t *testing.T) { } disp := New(mockDispatcher{f: f}, &keys.DirectKeyHandler{}) - req := &v1.DispatchCheckRequest{ - ResourceRelation: tuple.RelationReference("document", "view"), - ResourceIds: []string{"foo", "bar"}, - Subject: tuple.ObjectAndRelation("user", "tom", "..."), - Metadata: &v1.ResolverMeta{ - AtRevision: "1234", - }, - } - wg := sync.WaitGroup{} wg.Add(3) go func() { ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50) defer cancel() - _, err := disp.DispatchCheck(ctx, req) + _, err := disp.DispatchCheck(ctx, &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "first", + }, + }) wg.Done() require.ErrorIs(t, err, context.DeadlineExceeded) }() go func() { ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50) defer cancel() - _, err := disp.DispatchCheck(ctx, req) + _, err := disp.DispatchCheck(ctx, &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "second", + }, + }) wg.Done() require.ErrorIs(t, err, context.DeadlineExceeded) }() go func() { ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50) defer cancel() - _, err := disp.DispatchCheck(ctx, req) + _, err := disp.DispatchCheck(ctx, &v1.DispatchCheckRequest{ + ResourceRelation: tuple.RelationReference("document", "view"), + ResourceIds: []string{"foo", "bar"}, + Subject: tuple.ObjectAndRelation("user", "tom", "..."), + Metadata: &v1.ResolverMeta{ + AtRevision: "1234", + RequestId: "third", + }, + }) wg.Done() require.ErrorIs(t, err, context.DeadlineExceeded) }() diff --git a/internal/graph/computed/computecheck.go b/internal/graph/computed/computecheck.go index 0b1505ddf2..0b7151491c 100644 --- a/internal/graph/computed/computecheck.go +++ b/internal/graph/computed/computecheck.go @@ -8,6 +8,7 @@ import ( datastoremw "github.com/authzed/spicedb/internal/middleware/datastore" "github.com/authzed/spicedb/pkg/datastore" "github.com/authzed/spicedb/pkg/genutil/slicez" + "github.com/authzed/spicedb/pkg/middleware/requestid" core "github.com/authzed/spicedb/pkg/proto/core/v1" v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" "github.com/authzed/spicedb/pkg/spiceerrors" @@ -102,6 +103,8 @@ func computeCheck(ctx context.Context, metadata := &v1.ResponseMeta{} // TODO(jschorr): Should we make this run in parallel via the preloadedTaskRunner? + requestID, ctx := requestid.GetOrGenerateRequestID(ctx) + _, err := slicez.ForEachChunkUntil(resourceIDs, datastore.FilterMaximumIDCount, func(resourceIDsToCheck []string) (bool, error) { checkResult, err := d.DispatchCheck(ctx, &v1.DispatchCheckRequest{ ResourceRelation: params.ResourceType, @@ -111,6 +114,7 @@ func computeCheck(ctx context.Context, Metadata: &v1.ResolverMeta{ AtRevision: params.AtRevision.String(), DepthRemaining: params.MaximumDepth, + RequestId: requestID, }, Debug: debugging, }) diff --git a/internal/graph/graph.go b/internal/graph/graph.go index dbc89e6aaa..3fc6a6c8ca 100644 --- a/internal/graph/graph.go +++ b/internal/graph/graph.go @@ -63,6 +63,7 @@ func decrementDepth(md *v1.ResolverMeta) *v1.ResolverMeta { return &v1.ResolverMeta{ AtRevision: md.AtRevision, DepthRemaining: md.DepthRemaining - 1, + RequestId: md.RequestId, } } diff --git a/internal/graph/lookupsubjects.go b/internal/graph/lookupsubjects.go index e2c03ddd84..1a2dac25c1 100644 --- a/internal/graph/lookupsubjects.go +++ b/internal/graph/lookupsubjects.go @@ -184,6 +184,7 @@ func (cl *ConcurrentLookupSubjects) lookupViaComputed( Metadata: &v1.ResolverMeta{ AtRevision: parentRequest.Revision.String(), DepthRemaining: parentRequest.Metadata.DepthRemaining - 1, + RequestId: parentRequest.Metadata.RequestId, }, }, stream) } @@ -426,6 +427,7 @@ func (cl *ConcurrentLookupSubjects) dispatchTo( Metadata: &v1.ResolverMeta{ AtRevision: parentRequest.Revision.String(), DepthRemaining: parentRequest.Metadata.DepthRemaining - 1, + RequestId: parentRequest.Metadata.RequestId, }, }, stream) }) diff --git a/internal/graph/reachableresources.go b/internal/graph/reachableresources.go index b0c0aec149..25439cd751 100644 --- a/internal/graph/reachableresources.go +++ b/internal/graph/reachableresources.go @@ -549,6 +549,7 @@ func (crr *CursoredReachableResources) redispatchOrReport( Metadata: &v1.ResolverMeta{ AtRevision: parentRequest.Revision.String(), DepthRemaining: parentRequest.Metadata.DepthRemaining - 1, + RequestId: parentRequest.Metadata.RequestId, }, OptionalCursor: ci.currentCursor, OptionalLimit: ci.limits.currentLimit, diff --git a/internal/services/integrationtesting/consistency_test.go b/internal/services/integrationtesting/consistency_test.go index a3e85487b7..bfe7234861 100644 --- a/internal/services/integrationtesting/consistency_test.go +++ b/internal/services/integrationtesting/consistency_test.go @@ -284,6 +284,7 @@ func validateExpansionSubjects(t *testing.T, vctx validationContext) { Metadata: &dispatchv1.ResolverMeta{ AtRevision: vctx.revision.String(), DepthRemaining: 100, + RequestId: "somerequestid", }, ExpansionMode: dispatchv1.DispatchExpandRequest_RECURSIVE, }) diff --git a/internal/services/integrationtesting/consistencytestutil/accessibilityset.go b/internal/services/integrationtesting/consistencytestutil/accessibilityset.go index 41791a87a1..7fe72bd5ff 100644 --- a/internal/services/integrationtesting/consistencytestutil/accessibilityset.go +++ b/internal/services/integrationtesting/consistencytestutil/accessibilityset.go @@ -133,6 +133,7 @@ func BuildAccessibilitySet(t *testing.T, ccd ConsistencyClusterAndData) *Accessi Metadata: &dispatchv1.ResolverMeta{ AtRevision: headRevision.String(), DepthRemaining: 50, + RequestId: "somerequestid", }, }) require.NoError(t, err) @@ -359,6 +360,7 @@ func isAccessibleViaWildcardOnly( Metadata: &dispatchv1.ResolverMeta{ AtRevision: revision.String(), DepthRemaining: 100, + RequestId: "somerequestid", }, ExpansionMode: dispatchv1.DispatchExpandRequest_RECURSIVE, }) diff --git a/internal/services/v1/permissions.go b/internal/services/v1/permissions.go index 6c69cfb67c..6bb950f059 100644 --- a/internal/services/v1/permissions.go +++ b/internal/services/v1/permissions.go @@ -26,6 +26,7 @@ import ( "github.com/authzed/spicedb/pkg/cursor" "github.com/authzed/spicedb/pkg/datastore" "github.com/authzed/spicedb/pkg/middleware/consistency" + "github.com/authzed/spicedb/pkg/middleware/requestid" core "github.com/authzed/spicedb/pkg/proto/core/v1" dispatch "github.com/authzed/spicedb/pkg/proto/dispatch/v1" "github.com/authzed/spicedb/pkg/tuple" @@ -155,10 +156,13 @@ func (ps *permissionServer) ExpandPermissionTree(ctx context.Context, req *v1.Ex return nil, ps.rewriteError(ctx, err) } + requestID, ctx := requestid.GetOrGenerateRequestID(ctx) + resp, err := ps.dispatch.DispatchExpand(ctx, &dispatch.DispatchExpandRequest{ Metadata: &dispatch.ResolverMeta{ AtRevision: atRevision.String(), DepthRemaining: ps.config.MaximumAPIDepth, + RequestId: requestID, }, ResourceAndRelation: &core.ObjectAndRelation{ Namespace: req.Resource.ObjectType, @@ -326,7 +330,8 @@ func TranslateExpansionTree(node *core.RelationTupleTreeNode) *v1.PermissionRela } func (ps *permissionServer) LookupResources(req *v1.LookupResourcesRequest, resp v1.PermissionsService_LookupResourcesServer) error { - ctx := resp.Context() + requestID, ctx := requestid.GetOrGenerateRequestID(resp.Context()) + atRevision, revisionReadAt, err := consistency.RevisionFromContext(ctx) if err != nil { return ps.rewriteError(ctx, err) @@ -420,6 +425,7 @@ func (ps *permissionServer) LookupResources(req *v1.LookupResourcesRequest, resp Metadata: &dispatch.ResolverMeta{ AtRevision: atRevision.String(), DepthRemaining: ps.config.MaximumAPIDepth, + RequestId: requestID, }, ObjectRelation: &core.RelationReference{ Namespace: req.ResourceObjectType, @@ -444,7 +450,8 @@ func (ps *permissionServer) LookupResources(req *v1.LookupResourcesRequest, resp } func (ps *permissionServer) LookupSubjects(req *v1.LookupSubjectsRequest, resp v1.PermissionsService_LookupSubjectsServer) error { - ctx := resp.Context() + requestID, ctx := requestid.GetOrGenerateRequestID(resp.Context()) + atRevision, revisionReadAt, err := consistency.RevisionFromContext(ctx) if err != nil { return ps.rewriteError(ctx, err) @@ -538,6 +545,7 @@ func (ps *permissionServer) LookupSubjects(req *v1.LookupSubjectsRequest, resp v Metadata: &dispatch.ResolverMeta{ AtRevision: atRevision.String(), DepthRemaining: ps.config.MaximumAPIDepth, + RequestId: requestID, }, ResourceRelation: &core.RelationReference{ Namespace: req.Resource.ObjectType, diff --git a/pkg/development/validation.go b/pkg/development/validation.go index 7f77c6778d..d70361538b 100644 --- a/pkg/development/validation.go +++ b/pkg/development/validation.go @@ -32,6 +32,7 @@ func RunValidation(devContext *DevContext, validation *blocks.ParsedExpectedRela Metadata: &v1.ResolverMeta{ AtRevision: devContext.Revision.String(), DepthRemaining: maxDispatchDepth, + RequestId: "validation", }, ExpansionMode: v1.DispatchExpandRequest_RECURSIVE, }) diff --git a/pkg/genutil/mapz/countingmap.go b/pkg/genutil/mapz/countingmap.go new file mode 100644 index 0000000000..f8ca2b4268 --- /dev/null +++ b/pkg/genutil/mapz/countingmap.go @@ -0,0 +1,50 @@ +package mapz + +import "sync" + +// CountingMultiMap is a multimap that counts the number of distinct values for each +// key, removing the key from the map when the count reaches zero. Safe for concurrent +// use. +type CountingMultiMap[T comparable, Q comparable] struct { + valuesByKey map[T]*Set[Q] + lock sync.Mutex +} + +// NewCountingMultiMap constructs a new counting multimap. +func NewCountingMultiMap[T comparable, Q comparable]() *CountingMultiMap[T, Q] { + return &CountingMultiMap[T, Q]{ + valuesByKey: map[T]*Set[Q]{}, + lock: sync.Mutex{}, + } +} + +// Add adds the given value to the map at the given key. Returns true if the value +// already existed in the map for the given key. +func (cmm *CountingMultiMap[T, Q]) Add(key T, value Q) bool { + cmm.lock.Lock() + defer cmm.lock.Unlock() + + values, ok := cmm.valuesByKey[key] + if !ok { + values = NewSet[Q]() + cmm.valuesByKey[key] = values + } + return !values.Add(value) +} + +// Remove removes the given value for the given key from the map. If, after this removal, +// the key has no additional values, it is removed entirely from the map. +func (cmm *CountingMultiMap[T, Q]) Remove(key T, value Q) { + cmm.lock.Lock() + defer cmm.lock.Unlock() + + values, ok := cmm.valuesByKey[key] + if !ok { + return + } + + values.Remove(value) + if values.IsEmpty() { + delete(cmm.valuesByKey, key) + } +} diff --git a/pkg/genutil/mapz/countingmap_test.go b/pkg/genutil/mapz/countingmap_test.go new file mode 100644 index 0000000000..080b06acfc --- /dev/null +++ b/pkg/genutil/mapz/countingmap_test.go @@ -0,0 +1,22 @@ +package mapz + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBasicCountingMap(t *testing.T) { + cmap := NewCountingMultiMap[string, string]() + + require.False(t, cmap.Add("foo", "1")) + require.False(t, cmap.Add("foo", "2")) + require.False(t, cmap.Add("bar", "1")) + + require.True(t, cmap.Add("foo", "1")) + + cmap.Remove("foo", "1") + + require.False(t, cmap.Add("foo", "1")) + require.True(t, cmap.Add("foo", "2")) +} diff --git a/pkg/middleware/requestid/requestid.go b/pkg/middleware/requestid/requestid.go index d90b7145a5..7ca2f85633 100644 --- a/pkg/middleware/requestid/requestid.go +++ b/pkg/middleware/requestid/requestid.go @@ -40,6 +40,34 @@ func WithIDGenerator(genFunc IDGenerator) Option { } } +// GenerateRequestID generates a new request ID. +func GenerateRequestID() string { + return randSeq(32) +} + +// GetOrGenerateRequestID returns the request ID found in the given context. If not, a new request ID +// is generated and added to the returned context. +func GetOrGenerateRequestID(ctx context.Context) (string, context.Context) { + var haveRequestID bool + md, ok := metadata.FromIncomingContext(ctx) + if ok { + var requestIDs []string + requestIDs, haveRequestID = md[RequestIDMetadataKey] + if haveRequestID { + return requestIDs[0], ctx + } + } + + if md == nil { + md = metadata.New(nil) + } + + requestID := GenerateRequestID() + md.Set(RequestIDMetadataKey, requestID) + ctx = metadata.NewIncomingContext(ctx, md) + return requestID, ctx +} + type handleRequestID struct { generateIfMissing bool requestIDGenerator IDGenerator @@ -61,6 +89,10 @@ func (r *handleRequestID) ServerReporter(ctx context.Context, _ interceptors.Cal requestID, haveRequestID = r.requestIDGenerator(), true // Inject the newly generated request ID into the metadata + if md == nil { + md = metadata.New(nil) + } + md.Set(RequestIDMetadataKey, requestID) ctx = metadata.NewIncomingContext(ctx, md) } @@ -97,9 +129,7 @@ func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor { func createReporter(opts []Option) *handleRequestID { reporter := &handleRequestID{ - requestIDGenerator: func() string { - return randSeq(32) - }, + requestIDGenerator: GenerateRequestID, } for _, opt := range opts { diff --git a/pkg/proto/dispatch/v1/dispatch.pb.go b/pkg/proto/dispatch/v1/dispatch.pb.go index 8aabe51bd5..178422de9a 100644 --- a/pkg/proto/dispatch/v1/dispatch.pb.go +++ b/pkg/proto/dispatch/v1/dispatch.pb.go @@ -1420,6 +1420,7 @@ type ResolverMeta struct { AtRevision string `protobuf:"bytes,1,opt,name=at_revision,json=atRevision,proto3" json:"at_revision,omitempty"` DepthRemaining uint32 `protobuf:"varint,2,opt,name=depth_remaining,json=depthRemaining,proto3" json:"depth_remaining,omitempty"` + RequestId string `protobuf:"bytes,3,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` } func (x *ResolverMeta) Reset() { @@ -1468,6 +1469,13 @@ func (x *ResolverMeta) GetDepthRemaining() uint32 { return 0 } +func (x *ResolverMeta) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + type ResponseMeta struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1960,115 +1968,117 @@ var file_dispatch_v1_dispatch_proto_rawDesc = []byte{ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6b, 0x0a, 0x0c, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x29, 0x0a, 0x0b, - 0x61, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x28, 0x80, 0x08, 0x52, 0x0a, 0x61, 0x74, 0x52, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x0f, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x5f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x20, 0x00, 0x52, 0x0e, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0xda, 0x01, 0x0a, 0x0c, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, - 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x70, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x44, - 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0a, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, - 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x46, 0x0a, 0x10, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, - 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x64, 0x69, 0x73, 0x70, + 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x94, 0x01, 0x0a, + 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x29, 0x0a, + 0x0b, 0x61, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x28, 0x80, 0x08, 0x52, 0x0a, 0x61, 0x74, + 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x0f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x5f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x2a, 0x02, 0x20, 0x00, 0x52, 0x0e, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x27, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, + 0xfa, 0x42, 0x05, 0x72, 0x03, 0x28, 0x80, 0x08, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x22, 0xda, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x70, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x13, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x65, 0x62, 0x75, 0x67, + 0x49, 0x6e, 0x66, 0x6f, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, + 0x22, 0x46, 0x0a, 0x10, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, + 0x65, 0x52, 0x05, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xaf, 0x04, 0x0a, 0x0f, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x07, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5f, 0x0a, 0x16, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, - 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x05, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xaf, - 0x04, 0x0a, 0x0f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x5f, 0x0a, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x29, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x43, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x69, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, - 0x3f, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, - 0x61, 0x63, 0x65, 0x52, 0x0b, 0x73, 0x75, 0x62, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, - 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x5c, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, - 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x39, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, - 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x02, - 0x32, 0xbd, 0x04, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x21, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, - 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, - 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, - 0x12, 0x22, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x81, 0x01, 0x0a, 0x1a, - 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x64, 0x69, 0x73, - 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x64, 0x69, 0x73, + 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x64, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, + 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3f, 0x0a, 0x0c, 0x73, 0x75, 0x62, + 0x5f, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x0b, 0x73, + 0x75, 0x62, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x1a, 0x5c, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x39, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, + 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, + 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x32, 0xbd, 0x04, 0x0a, 0x0f, 0x44, + 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, + 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x21, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x78, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x64, 0x69, 0x73, - 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, - 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, - 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x75, 0x0a, 0x16, 0x44, 0x69, 0x73, - 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, - 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, - 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x42, 0xaa, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, - 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x69, 0x73, 0x70, - 0x61, 0x74, 0x63, 0x68, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, - 0x76, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x44, 0x69, 0x73, 0x70, 0x61, - 0x74, 0x63, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0b, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x17, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5c, - 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x0c, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, + 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x81, 0x01, 0x0a, 0x1a, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, + 0x63, 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x63, 0x68, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x78, 0x0a, 0x17, 0x44, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2c, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x75, 0x0a, 0x16, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2a, 0x2e, + 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x64, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0xaa, 0x01, 0x0a, 0x0f, 0x63, + 0x6f, 0x6d, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x76, 0x31, 0x42, 0x0d, + 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, 0x68, + 0x7a, 0x65, 0x64, 0x2f, 0x73, 0x70, 0x69, 0x63, 0x65, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2f, 0x76, + 0x31, 0x3b, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x44, + 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x56, 0x31, + 0xca, 0x02, 0x0b, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5c, 0x56, 0x31, 0xe2, 0x02, + 0x17, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x44, 0x69, 0x73, 0x70, 0x61, + 0x74, 0x63, 0x68, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/proto/dispatch/v1/dispatch.pb.validate.go b/pkg/proto/dispatch/v1/dispatch.pb.validate.go index 837a9352e5..4a13ea8811 100644 --- a/pkg/proto/dispatch/v1/dispatch.pb.validate.go +++ b/pkg/proto/dispatch/v1/dispatch.pb.validate.go @@ -2889,6 +2889,17 @@ func (m *ResolverMeta) validate(all bool) error { errors = append(errors, err) } + if len(m.GetRequestId()) > 1024 { + err := ResolverMetaValidationError{ + field: "RequestId", + reason: "value length must be at most 1024 bytes", + } + if !all { + return err + } + errors = append(errors, err) + } + if len(errors) > 0 { return ResolverMetaMultiError(errors) } diff --git a/pkg/proto/dispatch/v1/dispatch_vtproto.pb.go b/pkg/proto/dispatch/v1/dispatch_vtproto.pb.go index 6a0d876410..c1371244c3 100644 --- a/pkg/proto/dispatch/v1/dispatch_vtproto.pb.go +++ b/pkg/proto/dispatch/v1/dispatch_vtproto.pb.go @@ -484,6 +484,7 @@ func (m *ResolverMeta) CloneVT() *ResolverMeta { r := &ResolverMeta{ AtRevision: m.AtRevision, DepthRemaining: m.DepthRemaining, + RequestId: m.RequestId, } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -1180,6 +1181,9 @@ func (this *ResolverMeta) EqualVT(that *ResolverMeta) bool { if this.DepthRemaining != that.DepthRemaining { return false } + if this.RequestId != that.RequestId { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -2509,6 +2513,13 @@ func (m *ResolverMeta) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.RequestId) > 0 { + i -= len(m.RequestId) + copy(dAtA[i:], m.RequestId) + i = encodeVarint(dAtA, i, uint64(len(m.RequestId))) + i-- + dAtA[i] = 0x1a + } if m.DepthRemaining != 0 { i = encodeVarint(dAtA, i, uint64(m.DepthRemaining)) i-- @@ -3236,6 +3247,10 @@ func (m *ResolverMeta) SizeVT() (n int) { if m.DepthRemaining != 0 { n += 1 + sov(uint64(m.DepthRemaining)) } + l = len(m.RequestId) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -6193,6 +6208,38 @@ func (m *ResolverMeta) UnmarshalVT(dAtA []byte) error { break } } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RequestId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skip(dAtA[iNdEx:]) diff --git a/proto/internal/dispatch/v1/dispatch.proto b/proto/internal/dispatch/v1/dispatch.proto index 32eb492c9e..40d35710e9 100644 --- a/proto/internal/dispatch/v1/dispatch.proto +++ b/proto/internal/dispatch/v1/dispatch.proto @@ -184,6 +184,7 @@ message DispatchLookupSubjectsResponse { message ResolverMeta { string at_revision = 1 [(validate.rules).string = {max_bytes: 1024}]; uint32 depth_remaining = 2 [(validate.rules).uint32.gt = 0]; + string request_id = 3 [(validate.rules).string = {max_bytes: 1024}]; } message ResponseMeta {