From 587724c4eb0c9659d7783fa51feda71d2dcc86fa Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Mon, 24 Oct 2022 21:39:34 +1100 Subject: [PATCH 1/7] :art: fix typo --- gubernator.go | 10 +++++----- multiregion.go | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gubernator.go b/gubernator.go index 3cbab3b8..b7147965 100644 --- a/gubernator.go +++ b/gubernator.go @@ -47,7 +47,7 @@ type V1Instance struct { UnimplementedV1Server UnimplementedPeersV1Server global *globalManager - mutliRegion *mutliRegionManager + multiRegion *multiRegionManager peerMutex sync.RWMutex log FieldLogger conf Config @@ -135,7 +135,7 @@ func NewV1Instance(conf Config) (retval *V1Instance, reterr error) { s.gubernatorPool = NewGubernatorPool(&conf, conf.PoolWorkers, 0) s.global = newGlobalManager(conf.Behaviors, &s) - s.mutliRegion = newMultiRegionManager(conf.Behaviors, &s) + s.multiRegion = newMultiRegionManager(conf.Behaviors, &s) // Register our instance with all GRPC servers for _, srv := range conf.GRPCServers { @@ -171,7 +171,7 @@ func (s *V1Instance) Close() (reterr error) { } s.global.Close() - s.mutliRegion.Close() + s.multiRegion.Close() err := s.gubernatorPool.Store(ctx) if err != nil { @@ -641,8 +641,8 @@ func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq) (retval } if HasBehavior(r.Behavior, Behavior_MULTI_REGION) { - s.mutliRegion.QueueHits(r) - span.AddEvent("s.mutliRegion.QueueHits(r)") + s.multiRegion.QueueHits(r) + span.AddEvent("s.multiRegion.QueueHits(r)") } resp, err := s.gubernatorPool.GetRateLimit(ctx, r) diff --git a/multiregion.go b/multiregion.go index de24391f..c1785cb0 100644 --- a/multiregion.go +++ b/multiregion.go @@ -20,7 +20,7 @@ import ( "github.com/mailgun/holster/v4/syncutil" ) -type mutliRegionManager struct { +type multiRegionManager struct { reqQueue chan *RateLimitReq wg syncutil.WaitGroup conf BehaviorConfig @@ -28,8 +28,8 @@ type mutliRegionManager struct { instance *V1Instance } -func newMultiRegionManager(conf BehaviorConfig, instance *V1Instance) *mutliRegionManager { - mm := mutliRegionManager{ +func newMultiRegionManager(conf BehaviorConfig, instance *V1Instance) *multiRegionManager { + mm := multiRegionManager{ conf: conf, instance: instance, log: instance.log, @@ -40,11 +40,11 @@ func newMultiRegionManager(conf BehaviorConfig, instance *V1Instance) *mutliRegi } // QueueHits writes the RateLimitReq to be asynchronously sent to other regions -func (mm *mutliRegionManager) QueueHits(r *RateLimitReq) { +func (mm *multiRegionManager) QueueHits(r *RateLimitReq) { mm.reqQueue <- r } -func (mm *mutliRegionManager) runAsyncReqs() { +func (mm *multiRegionManager) runAsyncReqs() { var interval = NewInterval(mm.conf.MultiRegionSyncWait) hits := make(map[string]*RateLimitReq) @@ -93,10 +93,10 @@ func (mm *mutliRegionManager) runAsyncReqs() { // TODO: Sending cross DC should mainly update the hits, the config should not be sent, or ignored when received // TODO: Calculation of OVERLIMIT should not occur when sending hits cross DC -func (mm *mutliRegionManager) sendHits(r map[string]*RateLimitReq, picker PeerPicker) { +func (mm *multiRegionManager) sendHits(r map[string]*RateLimitReq, picker PeerPicker) { // Does nothing for now } -func (mm *mutliRegionManager) Close() { +func (mm *multiRegionManager) Close() { mm.wg.Stop() } From 33a322ec07505d373f8e36c4659c654055f88c9d Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Fri, 11 Nov 2022 12:04:01 +1100 Subject: [PATCH 2/7] :gem: update protos for atomic chaining --- gubernator.pb.go | 292 ++++++++------ gubernator.pb.gw.go | 48 ++- gubernator_grpc.pb.go | 4 + peers.pb.go | 94 +++-- peers.pb.gw.go | 48 ++- peers_grpc.pb.go | 4 + proto/gubernator.proto | 14 + proto/peers.proto | 1 + python/gubernator/gubernator_pb2.py | 591 ++-------------------------- python/gubernator/peers_pb2.py | 288 ++------------ 10 files changed, 373 insertions(+), 1011 deletions(-) diff --git a/gubernator.pb.go b/gubernator.pb.go index 36576b74..ea94cd21 100644 --- a/gubernator.pb.go +++ b/gubernator.pb.go @@ -15,8 +15,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.15.8 +// protoc-gen-go v1.28.1 +// protoc v3.21.8 // source: gubernator.proto package gubernator @@ -195,6 +195,56 @@ func (Behavior) EnumDescriptor() ([]byte, []int) { return file_gubernator_proto_rawDescGZIP(), []int{1} } +// A set of int32 flags used to control the behavior of a chained rate limits in gubernator +type UnionBehavior int32 + +const ( + // Default behaviour to treat multiple requests as fully independent + UnionBehavior_INDEPENDENT UnionBehavior = 0 // <- here because it is mandatory for the proto + // Enables atomic chaining of rate limits to multiple limits, i.e. will only increment if all limits + // have remaining capacity, otherwise will fail. + UnionBehavior_ATOMIC_REQUESTS UnionBehavior = 1 +) + +// Enum value maps for UnionBehavior. +var ( + UnionBehavior_name = map[int32]string{ + 0: "INDEPENDENT", + 1: "ATOMIC_REQUESTS", + } + UnionBehavior_value = map[string]int32{ + "INDEPENDENT": 0, + "ATOMIC_REQUESTS": 1, + } +) + +func (x UnionBehavior) Enum() *UnionBehavior { + p := new(UnionBehavior) + *p = x + return p +} + +func (x UnionBehavior) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UnionBehavior) Descriptor() protoreflect.EnumDescriptor { + return file_gubernator_proto_enumTypes[2].Descriptor() +} + +func (UnionBehavior) Type() protoreflect.EnumType { + return &file_gubernator_proto_enumTypes[2] +} + +func (x UnionBehavior) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UnionBehavior.Descriptor instead. +func (UnionBehavior) EnumDescriptor() ([]byte, []int) { + return file_gubernator_proto_rawDescGZIP(), []int{2} +} + type Status int32 const ( @@ -225,11 +275,11 @@ func (x Status) String() string { } func (Status) Descriptor() protoreflect.EnumDescriptor { - return file_gubernator_proto_enumTypes[2].Descriptor() + return file_gubernator_proto_enumTypes[3].Descriptor() } func (Status) Type() protoreflect.EnumType { - return &file_gubernator_proto_enumTypes[2] + return &file_gubernator_proto_enumTypes[3] } func (x Status) Number() protoreflect.EnumNumber { @@ -238,7 +288,7 @@ func (x Status) Number() protoreflect.EnumNumber { // Deprecated: Use Status.Descriptor instead. func (Status) EnumDescriptor() ([]byte, []int) { - return file_gubernator_proto_rawDescGZIP(), []int{2} + return file_gubernator_proto_rawDescGZIP(), []int{3} } // Must specify at least one Request @@ -248,6 +298,7 @@ type GetRateLimitsReq struct { unknownFields protoimpl.UnknownFields Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` + Behavior UnionBehavior `protobuf:"varint,2,opt,name=Behavior,proto3,enum=pb.gubernator.UnionBehavior" json:"Behavior,omitempty"` } func (x *GetRateLimitsReq) Reset() { @@ -289,6 +340,13 @@ func (x *GetRateLimitsReq) GetRequests() []*RateLimitReq { return nil } +func (x *GetRateLimitsReq) GetBehavior() UnionBehavior { + if x != nil { + return x.Behavior + } + return UnionBehavior_INDEPENDENT +} + // RateLimits returned are in the same order as the Requests type GetRateLimitsResp struct { state protoimpl.MessageState @@ -657,89 +715,97 @@ var file_gubernator_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 0x0d, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x4b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, - 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x4f, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x3a, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x8a, 0x02, - 0x0a, 0x0c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4b, 0x65, - 0x79, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x04, 0x68, 0x69, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, - 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, - 0x33, 0x0a, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x17, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x08, 0x62, 0x65, 0x68, 0x61, - 0x76, 0x69, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x72, 0x73, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x75, 0x72, 0x73, 0x74, 0x22, 0xac, 0x02, 0x0a, 0x0d, 0x52, - 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2d, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, - 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, - 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x46, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, + 0x85, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x10, 0x0a, 0x0e, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x22, 0x62, 0x0a, 0x0f, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2a, - 0x2f, 0x0a, 0x09, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x10, 0x0a, 0x0c, - 0x54, 0x4f, 0x4b, 0x45, 0x4e, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x00, 0x12, 0x10, - 0x0a, 0x0c, 0x4c, 0x45, 0x41, 0x4b, 0x59, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, - 0x2a, 0x77, 0x0a, 0x08, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x08, - 0x42, 0x41, 0x54, 0x43, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, - 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x47, - 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x55, 0x52, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x53, 0x5f, 0x47, 0x52, 0x45, 0x47, 0x4f, 0x52, 0x49, 0x41, 0x4e, - 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x41, - 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x55, 0x4c, 0x54, 0x49, - 0x5f, 0x52, 0x45, 0x47, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x2a, 0x29, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x4c, 0x49, 0x4d, - 0x49, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4c, 0x49, 0x4d, - 0x49, 0x54, 0x10, 0x01, 0x32, 0xdd, 0x01, 0x0a, 0x02, 0x56, 0x31, 0x12, 0x70, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x70, - 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x20, 0x2e, - 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, - 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x47, 0x65, 0x74, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x65, 0x0a, - 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x70, - 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x70, 0x62, - 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0x17, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, 0x75, 0x62, 0x65, 0x72, - 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x38, 0x0a, + 0x08, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x08, 0x42, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x22, 0x4f, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x09, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x0c, 0x52, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, + 0x68, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x69, 0x74, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, + 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x33, 0x0a, 0x08, 0x62, 0x65, + 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x70, + 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x42, 0x65, 0x68, + 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x62, 0x75, 0x72, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x62, 0x75, 0x72, 0x73, 0x74, 0x22, 0xac, 0x02, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, + 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x73, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x46, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x10, 0x0a, 0x0e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x22, 0x62, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x65, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x2f, 0x0a, 0x09, 0x41, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x4f, 0x4b, 0x45, 0x4e, + 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x45, 0x41, + 0x4b, 0x59, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, 0x2a, 0x77, 0x0a, 0x08, 0x42, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x41, 0x54, 0x43, 0x48, + 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x5f, 0x42, 0x41, 0x54, 0x43, + 0x48, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, + 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, + 0x53, 0x5f, 0x47, 0x52, 0x45, 0x47, 0x4f, 0x52, 0x49, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x13, 0x0a, + 0x0f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, + 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x52, 0x45, 0x47, 0x49, + 0x4f, 0x4e, 0x10, 0x10, 0x2a, 0x35, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x68, + 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x44, 0x45, 0x50, 0x45, 0x4e, + 0x44, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x54, 0x4f, 0x4d, 0x49, 0x43, + 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x53, 0x10, 0x01, 0x2a, 0x29, 0x0a, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x4c, + 0x49, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4c, + 0x49, 0x4d, 0x49, 0x54, 0x10, 0x01, 0x32, 0xdd, 0x01, 0x0a, 0x02, 0x56, 0x31, 0x12, 0x70, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1f, + 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, + 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x47, + 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x12, + 0x65, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, + 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, + 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0x17, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, 0x75, 0x62, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -754,36 +820,38 @@ func file_gubernator_proto_rawDescGZIP() []byte { return file_gubernator_proto_rawDescData } -var file_gubernator_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_gubernator_proto_enumTypes = make([]protoimpl.EnumInfo, 4) var file_gubernator_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_gubernator_proto_goTypes = []interface{}{ (Algorithm)(0), // 0: pb.gubernator.Algorithm (Behavior)(0), // 1: pb.gubernator.Behavior - (Status)(0), // 2: pb.gubernator.Status - (*GetRateLimitsReq)(nil), // 3: pb.gubernator.GetRateLimitsReq - (*GetRateLimitsResp)(nil), // 4: pb.gubernator.GetRateLimitsResp - (*RateLimitReq)(nil), // 5: pb.gubernator.RateLimitReq - (*RateLimitResp)(nil), // 6: pb.gubernator.RateLimitResp - (*HealthCheckReq)(nil), // 7: pb.gubernator.HealthCheckReq - (*HealthCheckResp)(nil), // 8: pb.gubernator.HealthCheckResp - nil, // 9: pb.gubernator.RateLimitResp.MetadataEntry + (UnionBehavior)(0), // 2: pb.gubernator.UnionBehavior + (Status)(0), // 3: pb.gubernator.Status + (*GetRateLimitsReq)(nil), // 4: pb.gubernator.GetRateLimitsReq + (*GetRateLimitsResp)(nil), // 5: pb.gubernator.GetRateLimitsResp + (*RateLimitReq)(nil), // 6: pb.gubernator.RateLimitReq + (*RateLimitResp)(nil), // 7: pb.gubernator.RateLimitResp + (*HealthCheckReq)(nil), // 8: pb.gubernator.HealthCheckReq + (*HealthCheckResp)(nil), // 9: pb.gubernator.HealthCheckResp + nil, // 10: pb.gubernator.RateLimitResp.MetadataEntry } var file_gubernator_proto_depIdxs = []int32{ - 5, // 0: pb.gubernator.GetRateLimitsReq.requests:type_name -> pb.gubernator.RateLimitReq - 6, // 1: pb.gubernator.GetRateLimitsResp.responses:type_name -> pb.gubernator.RateLimitResp - 0, // 2: pb.gubernator.RateLimitReq.algorithm:type_name -> pb.gubernator.Algorithm - 1, // 3: pb.gubernator.RateLimitReq.behavior:type_name -> pb.gubernator.Behavior - 2, // 4: pb.gubernator.RateLimitResp.status:type_name -> pb.gubernator.Status - 9, // 5: pb.gubernator.RateLimitResp.metadata:type_name -> pb.gubernator.RateLimitResp.MetadataEntry - 3, // 6: pb.gubernator.V1.GetRateLimits:input_type -> pb.gubernator.GetRateLimitsReq - 7, // 7: pb.gubernator.V1.HealthCheck:input_type -> pb.gubernator.HealthCheckReq - 4, // 8: pb.gubernator.V1.GetRateLimits:output_type -> pb.gubernator.GetRateLimitsResp - 8, // 9: pb.gubernator.V1.HealthCheck:output_type -> pb.gubernator.HealthCheckResp - 8, // [8:10] is the sub-list for method output_type - 6, // [6:8] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 6, // 0: pb.gubernator.GetRateLimitsReq.requests:type_name -> pb.gubernator.RateLimitReq + 2, // 1: pb.gubernator.GetRateLimitsReq.Behavior:type_name -> pb.gubernator.UnionBehavior + 7, // 2: pb.gubernator.GetRateLimitsResp.responses:type_name -> pb.gubernator.RateLimitResp + 0, // 3: pb.gubernator.RateLimitReq.algorithm:type_name -> pb.gubernator.Algorithm + 1, // 4: pb.gubernator.RateLimitReq.behavior:type_name -> pb.gubernator.Behavior + 3, // 5: pb.gubernator.RateLimitResp.status:type_name -> pb.gubernator.Status + 10, // 6: pb.gubernator.RateLimitResp.metadata:type_name -> pb.gubernator.RateLimitResp.MetadataEntry + 4, // 7: pb.gubernator.V1.GetRateLimits:input_type -> pb.gubernator.GetRateLimitsReq + 8, // 8: pb.gubernator.V1.HealthCheck:input_type -> pb.gubernator.HealthCheckReq + 5, // 9: pb.gubernator.V1.GetRateLimits:output_type -> pb.gubernator.GetRateLimitsResp + 9, // 10: pb.gubernator.V1.HealthCheck:output_type -> pb.gubernator.HealthCheckResp + 9, // [9:11] is the sub-list for method output_type + 7, // [7:9] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_gubernator_proto_init() } @@ -870,7 +938,7 @@ func file_gubernator_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_gubernator_proto_rawDesc, - NumEnums: 3, + NumEnums: 4, NumMessages: 7, NumExtensions: 0, NumServices: 1, diff --git a/gubernator.pb.gw.go b/gubernator.pb.gw.go index 6f421356..1c67924b 100644 --- a/gubernator.pb.gw.go +++ b/gubernator.pb.gw.go @@ -95,20 +95,22 @@ func RegisterV1HandlerServer(ctx context.Context, mux *runtime.ServeMux, server var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.V1/GetRateLimits", runtime.WithHTTPPathPattern("/v1/GetRateLimits")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.V1/GetRateLimits", runtime.WithHTTPPathPattern("/v1/GetRateLimits")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_V1_GetRateLimits_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_V1_GetRateLimits_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_V1_GetRateLimits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_V1_GetRateLimits_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -118,20 +120,22 @@ func RegisterV1HandlerServer(ctx context.Context, mux *runtime.ServeMux, server var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.V1/HealthCheck", runtime.WithHTTPPathPattern("/v1/HealthCheck")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.V1/HealthCheck", runtime.WithHTTPPathPattern("/v1/HealthCheck")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_V1_HealthCheck_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_V1_HealthCheck_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_V1_HealthCheck_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_V1_HealthCheck_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -180,19 +184,21 @@ func RegisterV1HandlerClient(ctx context.Context, mux *runtime.ServeMux, client ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.V1/GetRateLimits", runtime.WithHTTPPathPattern("/v1/GetRateLimits")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.V1/GetRateLimits", runtime.WithHTTPPathPattern("/v1/GetRateLimits")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_V1_GetRateLimits_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_V1_GetRateLimits_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_V1_GetRateLimits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_V1_GetRateLimits_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -200,19 +206,21 @@ func RegisterV1HandlerClient(ctx context.Context, mux *runtime.ServeMux, client ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.V1/HealthCheck", runtime.WithHTTPPathPattern("/v1/HealthCheck")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.V1/HealthCheck", runtime.WithHTTPPathPattern("/v1/HealthCheck")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_V1_HealthCheck_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_V1_HealthCheck_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_V1_HealthCheck_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_V1_HealthCheck_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) diff --git a/gubernator_grpc.pb.go b/gubernator_grpc.pb.go index 3b86ca42..a013dd3f 100644 --- a/gubernator_grpc.pb.go +++ b/gubernator_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.8 +// source: gubernator.proto package gubernator diff --git a/peers.pb.go b/peers.pb.go index 0b85e54e..857b98c6 100644 --- a/peers.pb.go +++ b/peers.pb.go @@ -15,8 +15,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.15.8 +// protoc-gen-go v1.28.1 +// protoc v3.21.8 // source: peers.proto package gubernator @@ -42,7 +42,8 @@ type GetPeerRateLimitsReq struct { // Must specify at least one RateLimit. The peer that recives this request MUST be authoritative for // each rate_limit[x].unique_key provided, as the peer will not forward the request to any other peers - Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` + Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` + AtomicCheck bool `protobuf:"varint,2,opt,name=atomicCheck,proto3" json:"atomicCheck,omitempty"` } func (x *GetPeerRateLimitsReq) Reset() { @@ -84,6 +85,13 @@ func (x *GetPeerRateLimitsReq) GetRequests() []*RateLimitReq { return nil } +func (x *GetPeerRateLimitsReq) GetAtomicCheck() bool { + if x != nil { + return x.AtomicCheck + } + return false +} + type GetPeerRateLimitsResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -286,50 +294,52 @@ var File_peers_proto protoreflect.FileDescriptor var file_peers_proto_rawDesc = []byte{ 0x0a, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x1a, 0x10, 0x67, 0x75, - 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4f, + 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x71, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, - 0x56, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x61, 0x74, 0x65, - 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x0a, 0x72, 0x61, 0x74, - 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x12, - 0x39, 0x0a, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x52, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x10, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, - 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, - 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x32, 0xcd, 0x01, 0x0a, 0x07, 0x50, 0x65, 0x65, - 0x72, 0x73, 0x56, 0x31, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x67, - 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, - 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x24, - 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, - 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, - 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x20, 0x0a, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x22, 0x56, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x61, + 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x0a, 0x72, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, + 0x71, 0x12, 0x39, 0x0a, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x52, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x22, 0x92, 0x01, 0x0a, + 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, + 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x22, 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x32, 0xcd, 0x01, 0x0a, 0x07, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x56, 0x31, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, + 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, + 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, - 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x12, 0x23, 0x2e, + 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, + 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, + 0x2f, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/peers.pb.gw.go b/peers.pb.gw.go index 82fdaf79..41f7d6e5 100644 --- a/peers.pb.gw.go +++ b/peers.pb.gw.go @@ -111,20 +111,22 @@ func RegisterPeersV1HandlerServer(ctx context.Context, mux *runtime.ServeMux, se var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.PeersV1/GetPeerRateLimits", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/GetPeerRateLimits")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.PeersV1/GetPeerRateLimits", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/GetPeerRateLimits")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_PeersV1_GetPeerRateLimits_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_PeersV1_GetPeerRateLimits_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_PeersV1_GetPeerRateLimits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_PeersV1_GetPeerRateLimits_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -134,20 +136,22 @@ func RegisterPeersV1HandlerServer(ctx context.Context, mux *runtime.ServeMux, se var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.PeersV1/UpdatePeerGlobals", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/UpdatePeerGlobals")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.gubernator.PeersV1/UpdatePeerGlobals", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/UpdatePeerGlobals")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_PeersV1_UpdatePeerGlobals_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_PeersV1_UpdatePeerGlobals_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_PeersV1_UpdatePeerGlobals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_PeersV1_UpdatePeerGlobals_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -196,19 +200,21 @@ func RegisterPeersV1HandlerClient(ctx context.Context, mux *runtime.ServeMux, cl ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.PeersV1/GetPeerRateLimits", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/GetPeerRateLimits")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.PeersV1/GetPeerRateLimits", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/GetPeerRateLimits")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_PeersV1_GetPeerRateLimits_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_PeersV1_GetPeerRateLimits_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_PeersV1_GetPeerRateLimits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_PeersV1_GetPeerRateLimits_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -216,19 +222,21 @@ func RegisterPeersV1HandlerClient(ctx context.Context, mux *runtime.ServeMux, cl ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.PeersV1/UpdatePeerGlobals", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/UpdatePeerGlobals")) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/pb.gubernator.PeersV1/UpdatePeerGlobals", runtime.WithHTTPPathPattern("/pb.gubernator.PeersV1/UpdatePeerGlobals")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_PeersV1_UpdatePeerGlobals_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_PeersV1_UpdatePeerGlobals_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_PeersV1_UpdatePeerGlobals_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_PeersV1_UpdatePeerGlobals_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) diff --git a/peers_grpc.pb.go b/peers_grpc.pb.go index 586224c7..3854aaf4 100644 --- a/peers_grpc.pb.go +++ b/peers_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.8 +// source: peers.proto package gubernator diff --git a/proto/gubernator.proto b/proto/gubernator.proto index 5ac0c584..4166eea2 100644 --- a/proto/gubernator.proto +++ b/proto/gubernator.proto @@ -47,6 +47,8 @@ service V1 { // Must specify at least one Request message GetRateLimitsReq { repeated RateLimitReq requests = 1; + UnionBehavior Behavior = 2; + } // RateLimits returned are in the same order as the Requests @@ -127,9 +129,21 @@ enum Behavior { // least 2 instances of Gubernator. MULTI_REGION = 16; + + // TODO: Add support for LOCAL. Which would force the rate limit to be handled by the local instance } +// A set of int32 flags used to control the behavior of a chained rate limits in gubernator +enum UnionBehavior { + // Default behaviour to treat multiple requests as fully independent + INDEPENDENT = 0; // <- here because it is mandatory for the proto + + // Enables atomic chaining of rate limits to multiple limits, i.e. will only increment if all limits + // have remaining capacity, otherwise will fail. + ATOMIC_REQUESTS = 1; +} + message RateLimitReq { // The name of the rate limit IE: 'requests_per_second', 'gets_per_minute` string name = 1; diff --git a/proto/peers.proto b/proto/peers.proto index 5caefae4..38dfc26f 100644 --- a/proto/peers.proto +++ b/proto/peers.proto @@ -37,6 +37,7 @@ message GetPeerRateLimitsReq { // Must specify at least one RateLimit. The peer that recives this request MUST be authoritative for // each rate_limit[x].unique_key provided, as the peer will not forward the request to any other peers repeated RateLimitReq requests = 1; + bool atomicCheck = 2; } message GetPeerRateLimitsResp { diff --git a/python/gubernator/gubernator_pb2.py b/python/gubernator/gubernator_pb2.py index e85274bc..3081072c 100644 --- a/python/gubernator/gubernator_pb2.py +++ b/python/gubernator/gubernator_pb2.py @@ -2,10 +2,9 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: gubernator.proto """Generated protocol buffer code.""" -from google.protobuf.internal import enum_type_wrapper +from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection +from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) @@ -15,552 +14,42 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -DESCRIPTOR = _descriptor.FileDescriptor( - name='gubernator.proto', - package='pb.gubernator', - syntax='proto3', - serialized_options=b'Z\035github.com/mailgun/gubernator\200\001\001', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x10gubernator.proto\x12\rpb.gubernator\x1a\x1cgoogle/api/annotations.proto\"A\n\x10GetRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\"D\n\x11GetRateLimitsResp\x12/\n\tresponses\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"\xc6\x01\n\x0cRateLimitReq\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nunique_key\x18\x02 \x01(\t\x12\x0c\n\x04hits\x18\x03 \x01(\x03\x12\r\n\x05limit\x18\x04 \x01(\x03\x12\x10\n\x08\x64uration\x18\x05 \x01(\x03\x12+\n\talgorithm\x18\x06 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\x12)\n\x08\x62\x65havior\x18\x07 \x01(\x0e\x32\x17.pb.gubernator.Behavior\x12\r\n\x05\x62urst\x18\x08 \x01(\x03\"\xea\x01\n\rRateLimitResp\x12%\n\x06status\x18\x01 \x01(\x0e\x32\x15.pb.gubernator.Status\x12\r\n\x05limit\x18\x02 \x01(\x03\x12\x11\n\tremaining\x18\x03 \x01(\x03\x12\x12\n\nreset_time\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12<\n\x08metadata\x18\x06 \x03(\x0b\x32*.pb.gubernator.RateLimitResp.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x10\n\x0eHealthCheckReq\"F\n\x0fHealthCheckResp\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\npeer_count\x18\x03 \x01(\x05*/\n\tAlgorithm\x12\x10\n\x0cTOKEN_BUCKET\x10\x00\x12\x10\n\x0cLEAKY_BUCKET\x10\x01*w\n\x08\x42\x65havior\x12\x0c\n\x08\x42\x41TCHING\x10\x00\x12\x0f\n\x0bNO_BATCHING\x10\x01\x12\n\n\x06GLOBAL\x10\x02\x12\x19\n\x15\x44URATION_IS_GREGORIAN\x10\x04\x12\x13\n\x0fRESET_REMAINING\x10\x08\x12\x10\n\x0cMULTI_REGION\x10\x10*)\n\x06Status\x12\x0f\n\x0bUNDER_LIMIT\x10\x00\x12\x0e\n\nOVER_LIMIT\x10\x01\x32\xdd\x01\n\x02V1\x12p\n\rGetRateLimits\x12\x1f.pb.gubernator.GetRateLimitsReq\x1a .pb.gubernator.GetRateLimitsResp\"\x1c\x82\xd3\xe4\x93\x02\x16\"\x11/v1/GetRateLimits:\x01*\x12\x65\n\x0bHealthCheck\x12\x1d.pb.gubernator.HealthCheckReq\x1a\x1e.pb.gubernator.HealthCheckResp\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/v1/HealthCheckB\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3' - , - dependencies=[google_dot_api_dot_annotations__pb2.DESCRIPTOR,]) - -_ALGORITHM = _descriptor.EnumDescriptor( - name='Algorithm', - full_name='pb.gubernator.Algorithm', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='TOKEN_BUCKET', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='LEAKY_BUCKET', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=730, - serialized_end=777, -) -_sym_db.RegisterEnumDescriptor(_ALGORITHM) - -Algorithm = enum_type_wrapper.EnumTypeWrapper(_ALGORITHM) -_BEHAVIOR = _descriptor.EnumDescriptor( - name='Behavior', - full_name='pb.gubernator.Behavior', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='BATCHING', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='NO_BATCHING', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='GLOBAL', index=2, number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='DURATION_IS_GREGORIAN', index=3, number=4, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='RESET_REMAINING', index=4, number=8, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='MULTI_REGION', index=5, number=16, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=779, - serialized_end=898, -) -_sym_db.RegisterEnumDescriptor(_BEHAVIOR) - -Behavior = enum_type_wrapper.EnumTypeWrapper(_BEHAVIOR) -_STATUS = _descriptor.EnumDescriptor( - name='Status', - full_name='pb.gubernator.Status', - filename=None, - file=DESCRIPTOR, - create_key=_descriptor._internal_create_key, - values=[ - _descriptor.EnumValueDescriptor( - name='UNDER_LIMIT', index=0, number=0, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='OVER_LIMIT', index=1, number=1, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - ], - containing_type=None, - serialized_options=None, - serialized_start=900, - serialized_end=941, -) -_sym_db.RegisterEnumDescriptor(_STATUS) - -Status = enum_type_wrapper.EnumTypeWrapper(_STATUS) -TOKEN_BUCKET = 0 -LEAKY_BUCKET = 1 -BATCHING = 0 -NO_BATCHING = 1 -GLOBAL = 2 -DURATION_IS_GREGORIAN = 4 -RESET_REMAINING = 8 -MULTI_REGION = 16 -UNDER_LIMIT = 0 -OVER_LIMIT = 1 - - - -_GETRATELIMITSREQ = _descriptor.Descriptor( - name='GetRateLimitsReq', - full_name='pb.gubernator.GetRateLimitsReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='requests', full_name='pb.gubernator.GetRateLimitsReq.requests', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=65, - serialized_end=130, -) - - -_GETRATELIMITSRESP = _descriptor.Descriptor( - name='GetRateLimitsResp', - full_name='pb.gubernator.GetRateLimitsResp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='responses', full_name='pb.gubernator.GetRateLimitsResp.responses', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=132, - serialized_end=200, -) - - -_RATELIMITREQ = _descriptor.Descriptor( - name='RateLimitReq', - full_name='pb.gubernator.RateLimitReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='pb.gubernator.RateLimitReq.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='unique_key', full_name='pb.gubernator.RateLimitReq.unique_key', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='hits', full_name='pb.gubernator.RateLimitReq.hits', index=2, - number=3, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='limit', full_name='pb.gubernator.RateLimitReq.limit', index=3, - number=4, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='duration', full_name='pb.gubernator.RateLimitReq.duration', index=4, - number=5, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='algorithm', full_name='pb.gubernator.RateLimitReq.algorithm', index=5, - number=6, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='behavior', full_name='pb.gubernator.RateLimitReq.behavior', index=6, - number=7, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='burst', full_name='pb.gubernator.RateLimitReq.burst', index=7, - number=8, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=203, - serialized_end=401, -) - - -_RATELIMITRESP_METADATAENTRY = _descriptor.Descriptor( - name='MetadataEntry', - full_name='pb.gubernator.RateLimitResp.MetadataEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='pb.gubernator.RateLimitResp.MetadataEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='value', full_name='pb.gubernator.RateLimitResp.MetadataEntry.value', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=b'8\001', - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=591, - serialized_end=638, -) - -_RATELIMITRESP = _descriptor.Descriptor( - name='RateLimitResp', - full_name='pb.gubernator.RateLimitResp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='status', full_name='pb.gubernator.RateLimitResp.status', index=0, - number=1, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='limit', full_name='pb.gubernator.RateLimitResp.limit', index=1, - number=2, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='remaining', full_name='pb.gubernator.RateLimitResp.remaining', index=2, - number=3, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='reset_time', full_name='pb.gubernator.RateLimitResp.reset_time', index=3, - number=4, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='error', full_name='pb.gubernator.RateLimitResp.error', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='metadata', full_name='pb.gubernator.RateLimitResp.metadata', index=5, - number=6, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_RATELIMITRESP_METADATAENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=404, - serialized_end=638, -) - - -_HEALTHCHECKREQ = _descriptor.Descriptor( - name='HealthCheckReq', - full_name='pb.gubernator.HealthCheckReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=640, - serialized_end=656, -) - - -_HEALTHCHECKRESP = _descriptor.Descriptor( - name='HealthCheckResp', - full_name='pb.gubernator.HealthCheckResp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='status', full_name='pb.gubernator.HealthCheckResp.status', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='message', full_name='pb.gubernator.HealthCheckResp.message', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='peer_count', full_name='pb.gubernator.HealthCheckResp.peer_count', index=2, - number=3, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=658, - serialized_end=728, -) - -_GETRATELIMITSREQ.fields_by_name['requests'].message_type = _RATELIMITREQ -_GETRATELIMITSRESP.fields_by_name['responses'].message_type = _RATELIMITRESP -_RATELIMITREQ.fields_by_name['algorithm'].enum_type = _ALGORITHM -_RATELIMITREQ.fields_by_name['behavior'].enum_type = _BEHAVIOR -_RATELIMITRESP_METADATAENTRY.containing_type = _RATELIMITRESP -_RATELIMITRESP.fields_by_name['status'].enum_type = _STATUS -_RATELIMITRESP.fields_by_name['metadata'].message_type = _RATELIMITRESP_METADATAENTRY -DESCRIPTOR.message_types_by_name['GetRateLimitsReq'] = _GETRATELIMITSREQ -DESCRIPTOR.message_types_by_name['GetRateLimitsResp'] = _GETRATELIMITSRESP -DESCRIPTOR.message_types_by_name['RateLimitReq'] = _RATELIMITREQ -DESCRIPTOR.message_types_by_name['RateLimitResp'] = _RATELIMITRESP -DESCRIPTOR.message_types_by_name['HealthCheckReq'] = _HEALTHCHECKREQ -DESCRIPTOR.message_types_by_name['HealthCheckResp'] = _HEALTHCHECKRESP -DESCRIPTOR.enum_types_by_name['Algorithm'] = _ALGORITHM -DESCRIPTOR.enum_types_by_name['Behavior'] = _BEHAVIOR -DESCRIPTOR.enum_types_by_name['Status'] = _STATUS -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -GetRateLimitsReq = _reflection.GeneratedProtocolMessageType('GetRateLimitsReq', (_message.Message,), { - 'DESCRIPTOR' : _GETRATELIMITSREQ, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.GetRateLimitsReq) - }) -_sym_db.RegisterMessage(GetRateLimitsReq) - -GetRateLimitsResp = _reflection.GeneratedProtocolMessageType('GetRateLimitsResp', (_message.Message,), { - 'DESCRIPTOR' : _GETRATELIMITSRESP, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.GetRateLimitsResp) - }) -_sym_db.RegisterMessage(GetRateLimitsResp) - -RateLimitReq = _reflection.GeneratedProtocolMessageType('RateLimitReq', (_message.Message,), { - 'DESCRIPTOR' : _RATELIMITREQ, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.RateLimitReq) - }) -_sym_db.RegisterMessage(RateLimitReq) - -RateLimitResp = _reflection.GeneratedProtocolMessageType('RateLimitResp', (_message.Message,), { - - 'MetadataEntry' : _reflection.GeneratedProtocolMessageType('MetadataEntry', (_message.Message,), { - 'DESCRIPTOR' : _RATELIMITRESP_METADATAENTRY, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.RateLimitResp.MetadataEntry) - }) - , - 'DESCRIPTOR' : _RATELIMITRESP, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.RateLimitResp) - }) -_sym_db.RegisterMessage(RateLimitResp) -_sym_db.RegisterMessage(RateLimitResp.MetadataEntry) - -HealthCheckReq = _reflection.GeneratedProtocolMessageType('HealthCheckReq', (_message.Message,), { - 'DESCRIPTOR' : _HEALTHCHECKREQ, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.HealthCheckReq) - }) -_sym_db.RegisterMessage(HealthCheckReq) - -HealthCheckResp = _reflection.GeneratedProtocolMessageType('HealthCheckResp', (_message.Message,), { - 'DESCRIPTOR' : _HEALTHCHECKRESP, - '__module__' : 'gubernator_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.HealthCheckResp) - }) -_sym_db.RegisterMessage(HealthCheckResp) - - -DESCRIPTOR._options = None -_RATELIMITRESP_METADATAENTRY._options = None - -_V1 = _descriptor.ServiceDescriptor( - name='V1', - full_name='pb.gubernator.V1', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=944, - serialized_end=1165, - methods=[ - _descriptor.MethodDescriptor( - name='GetRateLimits', - full_name='pb.gubernator.V1.GetRateLimits', - index=0, - containing_service=None, - input_type=_GETRATELIMITSREQ, - output_type=_GETRATELIMITSRESP, - serialized_options=b'\202\323\344\223\002\026\"\021/v1/GetRateLimits:\001*', - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='HealthCheck', - full_name='pb.gubernator.V1.HealthCheck', - index=1, - containing_service=None, - input_type=_HEALTHCHECKREQ, - output_type=_HEALTHCHECKRESP, - serialized_options=b'\202\323\344\223\002\021\022\017/v1/HealthCheck', - create_key=_descriptor._internal_create_key, - ), -]) -_sym_db.RegisterServiceDescriptor(_V1) - -DESCRIPTOR.services_by_name['V1'] = _V1 - +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10gubernator.proto\x12\rpb.gubernator\x1a\x1cgoogle/api/annotations.proto\"q\n\x10GetRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\x12.\n\x08\x42\x65havior\x18\x02 \x01(\x0e\x32\x1c.pb.gubernator.UnionBehavior\"D\n\x11GetRateLimitsResp\x12/\n\tresponses\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"\xc6\x01\n\x0cRateLimitReq\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nunique_key\x18\x02 \x01(\t\x12\x0c\n\x04hits\x18\x03 \x01(\x03\x12\r\n\x05limit\x18\x04 \x01(\x03\x12\x10\n\x08\x64uration\x18\x05 \x01(\x03\x12+\n\talgorithm\x18\x06 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\x12)\n\x08\x62\x65havior\x18\x07 \x01(\x0e\x32\x17.pb.gubernator.Behavior\x12\r\n\x05\x62urst\x18\x08 \x01(\x03\"\xea\x01\n\rRateLimitResp\x12%\n\x06status\x18\x01 \x01(\x0e\x32\x15.pb.gubernator.Status\x12\r\n\x05limit\x18\x02 \x01(\x03\x12\x11\n\tremaining\x18\x03 \x01(\x03\x12\x12\n\nreset_time\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12<\n\x08metadata\x18\x06 \x03(\x0b\x32*.pb.gubernator.RateLimitResp.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x10\n\x0eHealthCheckReq\"F\n\x0fHealthCheckResp\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\npeer_count\x18\x03 \x01(\x05*/\n\tAlgorithm\x12\x10\n\x0cTOKEN_BUCKET\x10\x00\x12\x10\n\x0cLEAKY_BUCKET\x10\x01*w\n\x08\x42\x65havior\x12\x0c\n\x08\x42\x41TCHING\x10\x00\x12\x0f\n\x0bNO_BATCHING\x10\x01\x12\n\n\x06GLOBAL\x10\x02\x12\x19\n\x15\x44URATION_IS_GREGORIAN\x10\x04\x12\x13\n\x0fRESET_REMAINING\x10\x08\x12\x10\n\x0cMULTI_REGION\x10\x10*5\n\rUnionBehavior\x12\x0f\n\x0bINDEPENDENT\x10\x00\x12\x13\n\x0f\x41TOMIC_REQUESTS\x10\x01*)\n\x06Status\x12\x0f\n\x0bUNDER_LIMIT\x10\x00\x12\x0e\n\nOVER_LIMIT\x10\x01\x32\xdd\x01\n\x02V1\x12p\n\rGetRateLimits\x12\x1f.pb.gubernator.GetRateLimitsReq\x1a .pb.gubernator.GetRateLimitsResp\"\x1c\x82\xd3\xe4\x93\x02\x16\"\x11/v1/GetRateLimits:\x01*\x12\x65\n\x0bHealthCheck\x12\x1d.pb.gubernator.HealthCheckReq\x1a\x1e.pb.gubernator.HealthCheckResp\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/v1/HealthCheckB\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'gubernator_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'Z\035github.com/mailgun/gubernator\200\001\001' + _RATELIMITRESP_METADATAENTRY._options = None + _RATELIMITRESP_METADATAENTRY._serialized_options = b'8\001' + _V1.methods_by_name['GetRateLimits']._options = None + _V1.methods_by_name['GetRateLimits']._serialized_options = b'\202\323\344\223\002\026\"\021/v1/GetRateLimits:\001*' + _V1.methods_by_name['HealthCheck']._options = None + _V1.methods_by_name['HealthCheck']._serialized_options = b'\202\323\344\223\002\021\022\017/v1/HealthCheck' + _ALGORITHM._serialized_start=778 + _ALGORITHM._serialized_end=825 + _BEHAVIOR._serialized_start=827 + _BEHAVIOR._serialized_end=946 + _UNIONBEHAVIOR._serialized_start=948 + _UNIONBEHAVIOR._serialized_end=1001 + _STATUS._serialized_start=1003 + _STATUS._serialized_end=1044 + _GETRATELIMITSREQ._serialized_start=65 + _GETRATELIMITSREQ._serialized_end=178 + _GETRATELIMITSRESP._serialized_start=180 + _GETRATELIMITSRESP._serialized_end=248 + _RATELIMITREQ._serialized_start=251 + _RATELIMITREQ._serialized_end=449 + _RATELIMITRESP._serialized_start=452 + _RATELIMITRESP._serialized_end=686 + _RATELIMITRESP_METADATAENTRY._serialized_start=639 + _RATELIMITRESP_METADATAENTRY._serialized_end=686 + _HEALTHCHECKREQ._serialized_start=688 + _HEALTHCHECKREQ._serialized_end=704 + _HEALTHCHECKRESP._serialized_start=706 + _HEALTHCHECKRESP._serialized_end=776 + _V1._serialized_start=1047 + _V1._serialized_end=1268 # @@protoc_insertion_point(module_scope) diff --git a/python/gubernator/peers_pb2.py b/python/gubernator/peers_pb2.py index c61ffd77..00a45ec6 100644 --- a/python/gubernator/peers_pb2.py +++ b/python/gubernator/peers_pb2.py @@ -2,9 +2,9 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: peers.proto """Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection +from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database # @@protoc_insertion_point(imports) @@ -14,268 +14,24 @@ import gubernator_pb2 as gubernator__pb2 -DESCRIPTOR = _descriptor.FileDescriptor( - name='peers.proto', - package='pb.gubernator', - syntax='proto3', - serialized_options=b'Z\035github.com/mailgun/gubernator\200\001\001', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0bpeers.proto\x12\rpb.gubernator\x1a\x10gubernator.proto\"E\n\x14GetPeerRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\"J\n\x15GetPeerRateLimitsResp\x12\x31\n\x0brate_limits\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"H\n\x14UpdatePeerGlobalsReq\x12\x30\n\x07globals\x18\x01 \x03(\x0b\x32\x1f.pb.gubernator.UpdatePeerGlobal\"z\n\x10UpdatePeerGlobal\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x06status\x18\x02 \x01(\x0b\x32\x1c.pb.gubernator.RateLimitResp\x12+\n\talgorithm\x18\x03 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\"\x17\n\x15UpdatePeerGlobalsResp2\xcd\x01\n\x07PeersV1\x12`\n\x11GetPeerRateLimits\x12#.pb.gubernator.GetPeerRateLimitsReq\x1a$.pb.gubernator.GetPeerRateLimitsResp\"\x00\x12`\n\x11UpdatePeerGlobals\x12#.pb.gubernator.UpdatePeerGlobalsReq\x1a$.pb.gubernator.UpdatePeerGlobalsResp\"\x00\x42\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3' - , - dependencies=[gubernator__pb2.DESCRIPTOR,]) - - - - -_GETPEERRATELIMITSREQ = _descriptor.Descriptor( - name='GetPeerRateLimitsReq', - full_name='pb.gubernator.GetPeerRateLimitsReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='requests', full_name='pb.gubernator.GetPeerRateLimitsReq.requests', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=48, - serialized_end=117, -) - - -_GETPEERRATELIMITSRESP = _descriptor.Descriptor( - name='GetPeerRateLimitsResp', - full_name='pb.gubernator.GetPeerRateLimitsResp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='rate_limits', full_name='pb.gubernator.GetPeerRateLimitsResp.rate_limits', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=119, - serialized_end=193, -) - - -_UPDATEPEERGLOBALSREQ = _descriptor.Descriptor( - name='UpdatePeerGlobalsReq', - full_name='pb.gubernator.UpdatePeerGlobalsReq', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='globals', full_name='pb.gubernator.UpdatePeerGlobalsReq.globals', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=195, - serialized_end=267, -) - - -_UPDATEPEERGLOBAL = _descriptor.Descriptor( - name='UpdatePeerGlobal', - full_name='pb.gubernator.UpdatePeerGlobal', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='pb.gubernator.UpdatePeerGlobal.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='status', full_name='pb.gubernator.UpdatePeerGlobal.status', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='algorithm', full_name='pb.gubernator.UpdatePeerGlobal.algorithm', index=2, - number=3, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=269, - serialized_end=391, -) - - -_UPDATEPEERGLOBALSRESP = _descriptor.Descriptor( - name='UpdatePeerGlobalsResp', - full_name='pb.gubernator.UpdatePeerGlobalsResp', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=393, - serialized_end=416, -) - -_GETPEERRATELIMITSREQ.fields_by_name['requests'].message_type = gubernator__pb2._RATELIMITREQ -_GETPEERRATELIMITSRESP.fields_by_name['rate_limits'].message_type = gubernator__pb2._RATELIMITRESP -_UPDATEPEERGLOBALSREQ.fields_by_name['globals'].message_type = _UPDATEPEERGLOBAL -_UPDATEPEERGLOBAL.fields_by_name['status'].message_type = gubernator__pb2._RATELIMITRESP -_UPDATEPEERGLOBAL.fields_by_name['algorithm'].enum_type = gubernator__pb2._ALGORITHM -DESCRIPTOR.message_types_by_name['GetPeerRateLimitsReq'] = _GETPEERRATELIMITSREQ -DESCRIPTOR.message_types_by_name['GetPeerRateLimitsResp'] = _GETPEERRATELIMITSRESP -DESCRIPTOR.message_types_by_name['UpdatePeerGlobalsReq'] = _UPDATEPEERGLOBALSREQ -DESCRIPTOR.message_types_by_name['UpdatePeerGlobal'] = _UPDATEPEERGLOBAL -DESCRIPTOR.message_types_by_name['UpdatePeerGlobalsResp'] = _UPDATEPEERGLOBALSRESP -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -GetPeerRateLimitsReq = _reflection.GeneratedProtocolMessageType('GetPeerRateLimitsReq', (_message.Message,), { - 'DESCRIPTOR' : _GETPEERRATELIMITSREQ, - '__module__' : 'peers_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.GetPeerRateLimitsReq) - }) -_sym_db.RegisterMessage(GetPeerRateLimitsReq) - -GetPeerRateLimitsResp = _reflection.GeneratedProtocolMessageType('GetPeerRateLimitsResp', (_message.Message,), { - 'DESCRIPTOR' : _GETPEERRATELIMITSRESP, - '__module__' : 'peers_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.GetPeerRateLimitsResp) - }) -_sym_db.RegisterMessage(GetPeerRateLimitsResp) - -UpdatePeerGlobalsReq = _reflection.GeneratedProtocolMessageType('UpdatePeerGlobalsReq', (_message.Message,), { - 'DESCRIPTOR' : _UPDATEPEERGLOBALSREQ, - '__module__' : 'peers_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.UpdatePeerGlobalsReq) - }) -_sym_db.RegisterMessage(UpdatePeerGlobalsReq) - -UpdatePeerGlobal = _reflection.GeneratedProtocolMessageType('UpdatePeerGlobal', (_message.Message,), { - 'DESCRIPTOR' : _UPDATEPEERGLOBAL, - '__module__' : 'peers_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.UpdatePeerGlobal) - }) -_sym_db.RegisterMessage(UpdatePeerGlobal) - -UpdatePeerGlobalsResp = _reflection.GeneratedProtocolMessageType('UpdatePeerGlobalsResp', (_message.Message,), { - 'DESCRIPTOR' : _UPDATEPEERGLOBALSRESP, - '__module__' : 'peers_pb2' - # @@protoc_insertion_point(class_scope:pb.gubernator.UpdatePeerGlobalsResp) - }) -_sym_db.RegisterMessage(UpdatePeerGlobalsResp) - - -DESCRIPTOR._options = None - -_PEERSV1 = _descriptor.ServiceDescriptor( - name='PeersV1', - full_name='pb.gubernator.PeersV1', - file=DESCRIPTOR, - index=0, - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_start=419, - serialized_end=624, - methods=[ - _descriptor.MethodDescriptor( - name='GetPeerRateLimits', - full_name='pb.gubernator.PeersV1.GetPeerRateLimits', - index=0, - containing_service=None, - input_type=_GETPEERRATELIMITSREQ, - output_type=_GETPEERRATELIMITSRESP, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), - _descriptor.MethodDescriptor( - name='UpdatePeerGlobals', - full_name='pb.gubernator.PeersV1.UpdatePeerGlobals', - index=1, - containing_service=None, - input_type=_UPDATEPEERGLOBALSREQ, - output_type=_UPDATEPEERGLOBALSRESP, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), -]) -_sym_db.RegisterServiceDescriptor(_PEERSV1) - -DESCRIPTOR.services_by_name['PeersV1'] = _PEERSV1 - +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bpeers.proto\x12\rpb.gubernator\x1a\x10gubernator.proto\"Z\n\x14GetPeerRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\x12\x13\n\x0b\x61tomicCheck\x18\x02 \x01(\x08\"J\n\x15GetPeerRateLimitsResp\x12\x31\n\x0brate_limits\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"H\n\x14UpdatePeerGlobalsReq\x12\x30\n\x07globals\x18\x01 \x03(\x0b\x32\x1f.pb.gubernator.UpdatePeerGlobal\"z\n\x10UpdatePeerGlobal\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x06status\x18\x02 \x01(\x0b\x32\x1c.pb.gubernator.RateLimitResp\x12+\n\talgorithm\x18\x03 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\"\x17\n\x15UpdatePeerGlobalsResp2\xcd\x01\n\x07PeersV1\x12`\n\x11GetPeerRateLimits\x12#.pb.gubernator.GetPeerRateLimitsReq\x1a$.pb.gubernator.GetPeerRateLimitsResp\"\x00\x12`\n\x11UpdatePeerGlobals\x12#.pb.gubernator.UpdatePeerGlobalsReq\x1a$.pb.gubernator.UpdatePeerGlobalsResp\"\x00\x42\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'peers_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'Z\035github.com/mailgun/gubernator\200\001\001' + _GETPEERRATELIMITSREQ._serialized_start=48 + _GETPEERRATELIMITSREQ._serialized_end=138 + _GETPEERRATELIMITSRESP._serialized_start=140 + _GETPEERRATELIMITSRESP._serialized_end=214 + _UPDATEPEERGLOBALSREQ._serialized_start=216 + _UPDATEPEERGLOBALSREQ._serialized_end=288 + _UPDATEPEERGLOBAL._serialized_start=290 + _UPDATEPEERGLOBAL._serialized_end=412 + _UPDATEPEERGLOBALSRESP._serialized_start=414 + _UPDATEPEERGLOBALSRESP._serialized_end=437 + _PEERSV1._serialized_start=440 + _PEERSV1._serialized_end=645 # @@protoc_insertion_point(module_scope) From fd8af6452fc1d0344eb41d4805d13dc7061bcde8 Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Fri, 11 Nov 2022 12:04:25 +1100 Subject: [PATCH 3/7] :gem: atomic chainingof limiters --- algorithms.go | 82 ++++++++++++++++++++++++++++++++++------------ global.go | 3 +- go.mod | 21 ++++++++---- go.sum | 26 +++++++++++++++ gubernator.go | 78 ++++++++++++++++++++++++++++++------------- gubernator_pool.go | 13 ++++---- peer_client.go | 7 ++-- 7 files changed, 170 insertions(+), 60 deletions(-) diff --git a/algorithms.go b/algorithms.go index f554e945..27763057 100644 --- a/algorithms.go +++ b/algorithms.go @@ -28,7 +28,7 @@ import ( ) // Implements token bucket algorithm for rate limiting. https://en.wikipedia.org/wiki/Token_bucket -func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { +func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -114,7 +114,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * span.AddEvent("s.Remove()") } - return tokenBucketNewItem(ctx, s, c, r) + return tokenBucketNewItem(ctx, s, c, r, ac) } // Update the limit if it changed. @@ -178,17 +178,22 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * // If we are already at the limit. if rl.Remaining == 0 && r.Hits > 0 { span.AddEvent("Already over the limit") - overLimitCounter.Add(1) rl.Status = Status_OVER_LIMIT t.Status = rl.Status + if !ac { + overLimitCounter.Add(1) + } return rl, nil + } // If requested hits takes the remainder. if t.Remaining == r.Hits { span.AddEvent("At the limit") - t.Remaining = 0 rl.Remaining = 0 + if !ac { + t.Remaining = 0 + } return rl, nil } @@ -196,23 +201,31 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * // without updating the cache. if r.Hits > t.Remaining { span.AddEvent("Over the limit") - overLimitCounter.Add(1) rl.Status = Status_OVER_LIMIT + if !ac { + overLimitCounter.Add(1) + } return rl, nil } span.AddEvent("Under the limit") - t.Remaining -= r.Hits - rl.Remaining = t.Remaining + // if we are doing a check during atomic chaining then we only want + // to update the response and not the actual value for the rate limit + if ac { + rl.Remaining = t.Remaining - r.Hits + } else { + t.Remaining -= r.Hits + rl.Remaining = t.Remaining + } return rl, nil } // Item is not found in cache or store, create new. - return tokenBucketNewItem(ctx, s, c, r) + return tokenBucketNewItem(ctx, s, c, r, ac) } // Called by tokenBucket() when adding a new item in the store. -func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { +func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -228,6 +241,12 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) Remaining: r.Limit - r.Hits, CreatedAt: now, } + + // if we are doing a check during atomic chaining then remaining number is actually the limit + if ac { + t.Remaining = r.Limit + } + item := &CacheItem{ Algorithm: Algorithm_TOKEN_BUCKET, Key: r.HashKey(), @@ -254,7 +273,9 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) // Client could be requesting that we always return OVER_LIMIT. if r.Hits > r.Limit { span.AddEvent("Over the limit") - overLimitCounter.Add(1) + if !ac { + overLimitCounter.Add(1) + } rl.Status = Status_OVER_LIMIT rl.Remaining = r.Limit t.Remaining = r.Limit @@ -272,7 +293,7 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) } // Implements leaky bucket algorithm for rate limiting https://en.wikipedia.org/wiki/Leaky_bucket -func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { +func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -341,7 +362,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * span.AddEvent("s.Remove()") } - return leakyBucketNewItem(ctx, s, c, r) + return leakyBucketNewItem(ctx, s, c, r, ac) } if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { @@ -415,23 +436,29 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * // If we are already at the limit if int64(b.Remaining) == 0 && r.Hits > 0 { - overLimitCounter.Add(1) + if !ac { + overLimitCounter.Add(1) + } rl.Status = Status_OVER_LIMIT return rl, nil } // If requested hits takes the remainder if int64(b.Remaining) == r.Hits { - b.Remaining -= float64(r.Hits) + if !ac { + b.Remaining -= float64(r.Hits) + rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) + } rl.Remaining = 0 - rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) return rl, nil } // If requested is more than available, then return over the limit // without updating the bucket. if r.Hits > int64(b.Remaining) { - overLimitCounter.Add(1) + if !ac { + overLimitCounter.Add(1) + } rl.Status = Status_OVER_LIMIT return rl, nil } @@ -441,17 +468,23 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * return rl, nil } - b.Remaining -= float64(r.Hits) - rl.Remaining = int64(b.Remaining) + // if we are doing a check during atomic chaining then we only want + // to update the response and not the actual value for the rate limit + if ac { + rl.Remaining = int64(b.Remaining - float64(r.Hits)) + } else { + b.Remaining -= float64(r.Hits) + rl.Remaining = int64(b.Remaining) + } rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) return rl, nil } - return leakyBucketNewItem(ctx, s, c, r) + return leakyBucketNewItem(ctx, s, c, r, ac) } // Called by leakyBucket() when adding a new item in the store. -func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { +func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -481,6 +514,11 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) Burst: r.Burst, } + // if we are doing a check during atomic chaining then remaining number is actually the limit + if ac { + b.Remaining = float64(r.Limit) + } + rl := RateLimitResp{ Status: Status_UNDER_LIMIT, Limit: b.Limit, @@ -490,7 +528,9 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) // Client could be requesting that we start with the bucket OVER_LIMIT if r.Hits > r.Burst { - overLimitCounter.Add(1) + if !ac { + overLimitCounter.Add(1) + } rl.Status = Status_OVER_LIMIT rl.Remaining = 0 rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) diff --git a/global.go b/global.go index babbc197..c3d06b5f 100644 --- a/global.go +++ b/global.go @@ -214,7 +214,8 @@ func (gm *globalManager) broadcastPeers(ctx context.Context, updates map[string] SetBehavior(&rl.Behavior, Behavior_GLOBAL, false) rl.Hits = 0 - status, err := gm.instance.getRateLimit(ctx, rl) + // we can invoke with atomicCheck = false as we are just getting status by using hits = 0 + status, err := gm.instance.getRateLimit(ctx, rl, false) if err != nil { gm.log.WithError(err).Errorf("while broadcasting update to peers for: '%s'", rl.HashKey()) continue diff --git a/go.mod b/go.mod index 51e360fd..6b2ac5d9 100644 --- a/go.mod +++ b/go.mod @@ -20,10 +20,11 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0 go.opentelemetry.io/otel v1.9.0 go.opentelemetry.io/otel/trace v1.9.0 - golang.org/x/net v0.0.0-20220811182439-13a9a731de15 + golang.org/x/net v0.0.0-20221014081412-f15817d10f9b golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac - google.golang.org/genproto v0.0.0-20220812140447-cec7f5303424 - google.golang.org/grpc v1.48.0 + google.golang.org/api v0.100.0 + google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e + google.golang.org/grpc v1.50.1 google.golang.org/protobuf v1.28.1 k8s.io/api v0.23.3 k8s.io/apimachinery v0.23.3 @@ -32,6 +33,8 @@ require ( ) require ( + cloud.google.com/go/compute v1.12.1 // indirect + cloud.google.com/go/compute/metadata v0.2.1 // indirect github.com/armon/go-metrics v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -41,10 +44,14 @@ require ( github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.1.1 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.6.0 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -66,6 +73,7 @@ require ( github.com/uptrace/opentelemetry-go-extra/otelutil v0.1.15 // indirect go.etcd.io/etcd/api/v3 v3.5.5 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect + go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.9.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 // indirect @@ -76,13 +84,14 @@ require ( go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ae7d4159..78d10adc 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,10 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -160,6 +164,7 @@ github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0L github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -206,6 +211,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -226,8 +233,13 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= @@ -423,6 +435,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0 h1:z6rnla1Asjzn0FrhohzIbDi4bxbtc6EMmQ7f5ZPn+pA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.33.0/go.mod h1:y/SlJpJQPd2UzfBCj0E9Flk9FDCtTyqUmaCB41qFrWI= @@ -547,6 +560,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220811182439-13a9a731de15 h1:cik0bxZUSJVDyaHf1hZPSDsU8SZHGQZQMeueXCE7yBQ= golang.org/x/net v0.0.0-20220811182439-13a9a731de15/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -564,6 +579,8 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY= golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -720,6 +737,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -741,6 +759,8 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.100.0 h1:LGUYIrbW9pzYQQ8NWXlaIVkgnfubVBZbMFb9P8TK374= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -794,6 +814,8 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220812140447-cec7f5303424 h1:zZnTt15U44/Txe/9cN/tVbteBkPMiyXK48hPsKRmqj4= google.golang.org/genproto v0.0.0-20220812140447-cec7f5303424/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -819,6 +841,10 @@ google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzI google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= 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= diff --git a/gubernator.go b/gubernator.go index b7147965..a55ad63a 100644 --- a/gubernator.go +++ b/gubernator.go @@ -219,9 +219,33 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re Responses: make([]*RateLimitResp, len(r.Requests)), } + // get the UnionBehaviour + var atomicRequests = HasUnionBehavior(r.GetBehavior(), UnionBehavior_ATOMIC_REQUESTS) + if atomicRequests { + // run with the atomic request check + resp.Responses = s.checkLimits(ctx, span, r, &resp, true) + // return without updating any actual limits if there is an error or anything over limit + for _, v := range resp.Responses { + if v.GetError() != "" || v.GetStatus() == Status_OVER_LIMIT { + return &resp, nil + } + } + } + // if atomic check is valid then run as we normally would + resp.Responses = s.checkLimits(ctx, span, r, &resp, false) + return &resp, nil +} + +func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRateLimitsReq, resp *GetRateLimitsResp, ac bool) []*RateLimitResp { var wg sync.WaitGroup asyncCh := make(chan AsyncResp, len(r.Requests)) + // update the trace name if this is an atomic check + ts := "Iterate requests" + if ac { + ts = fmt.Sprintf("%s - atomic check", ts) + } + // For each item in the request body for i, req := range r.Requests { _ = tracing.NamedScope(ctx, "Iterate requests", func(ctx context.Context) error { @@ -263,9 +287,11 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re // If our server instance is the owner of this rate limit if peer.Info().IsOwner { // Apply our rate limit algorithm to the request - getRateLimitCounter.WithLabelValues("local").Add(1) + if !ac { + getRateLimitCounter.WithLabelValues("local").Add(1) + } funcTimer1 := prometheus.NewTimer(funcTimeMetric.WithLabelValues("V1Instance.getRateLimit (local)")) - resp.Responses[i], err = s.getRateLimit(ctx, req) + resp.Responses[i], err = s.getRateLimit(ctx, req, ac) funcTimer1.ObserveDuration() if err != nil { err = errors.Wrapf(err, "Error while apply rate limit for '%s'", key) @@ -274,7 +300,7 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re } } else { if HasBehavior(req.Behavior, Behavior_GLOBAL) { - resp.Responses[i], err = s.getGlobalRateLimit(ctx, req) + resp.Responses[i], err = s.getGlobalRateLimit(ctx, req, ac) if err != nil { err = errors.Wrap(err, "Error in getGlobalRateLimit") span.RecordError(err) @@ -290,12 +316,13 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re // Launch remote peer request in goroutine. wg.Add(1) go s.asyncRequests(ctx, &AsyncReq{ - AsyncCh: asyncCh, - Peer: peer, - Req: req, - WG: &wg, - Key: key, - Idx: i, + AsyncCh: asyncCh, + Peer: peer, + Req: req, + WG: &wg, + Key: key, + Idx: i, + atomicCheck: ac, }) } @@ -312,8 +339,7 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re for a := range asyncCh { resp.Responses[a.Idx] = a.Resp } - - return &resp, nil + return resp.Responses } type AsyncResp struct { @@ -322,12 +348,13 @@ type AsyncResp struct { } type AsyncReq struct { - WG *sync.WaitGroup - AsyncCh chan AsyncResp - Req *RateLimitReq - Peer *PeerClient - Key string - Idx int + WG *sync.WaitGroup + AsyncCh chan AsyncResp + Req *RateLimitReq + Peer *PeerClient + Key string + Idx int + atomicCheck bool } func (s *V1Instance) asyncRequests(ctx context.Context, req *AsyncReq) { @@ -368,7 +395,7 @@ func (s *V1Instance) asyncRequests(ctx context.Context, req *AsyncReq) { if attempts != 0 { if req.Peer.Info().IsOwner { getRateLimitCounter.WithLabelValues("local").Add(1) - resp.Resp, err = s.getRateLimit(ctx, req.Req) + resp.Resp, err = s.getRateLimit(ctx, req.Req, req.atomicCheck) if err != nil { s.log.WithContext(ctx). WithError(err). @@ -423,7 +450,7 @@ func (s *V1Instance) asyncRequests(ctx context.Context, req *AsyncReq) { // getGlobalRateLimit handles rate limits that are marked as `Behavior = GLOBAL`. Rate limit responses // are returned from the local cache and the hits are queued to be sent to the owning peer. -func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq) (retval *RateLimitResp, reterr error) { +func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScope(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -457,7 +484,7 @@ func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq) // Process the rate limit like we own it getRateLimitCounter.WithLabelValues("global").Add(1) - resp, err := s.getRateLimit(ctx, cpy) + resp, err := s.getRateLimit(ctx, cpy, ac) if err != nil { return nil, errors.Wrap(err, "Error in getRateLimit") } @@ -536,7 +563,7 @@ func (s *V1Instance) GetPeerRateLimits(ctx context.Context, r *GetPeerRateLimits for idx, req := range r.Requests { fan.Run(func(in interface{}) error { rin := in.(reqIn) - rl, err := s.getRateLimit(ctx, rin.req) + rl, err := s.getRateLimit(ctx, rin.req, r.AtomicCheck) if err != nil { // Return the error for this request err = errors.Wrap(err, "Error in getRateLimit") @@ -618,7 +645,7 @@ func (s *V1Instance) HealthCheck(ctx context.Context, r *HealthCheckReq) (retval return &health, nil } -func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq) (retval *RateLimitResp, reterr error) { +func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -645,7 +672,7 @@ func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq) (retval span.AddEvent("s.multiRegion.QueueHits(r)") } - resp, err := s.gubernatorPool.GetRateLimit(ctx, r) + resp, err := s.gubernatorPool.GetRateLimit(ctx, r, ac) if isDeadlineExceeded(err) { checkErrorCounter.WithLabelValues("Timeout").Add(1) } @@ -808,6 +835,11 @@ func (s *V1Instance) Collect(ch chan<- prometheus.Metric) { batchSendDurationMetric.Collect(ch) } +// HasUnionBehavior returns true if the provided behavior is set on a collection of requests +func HasUnionBehavior(b UnionBehavior, flag UnionBehavior) bool { + return b&flag != 0 +} + // HasBehavior returns true if the provided behavior is set func HasBehavior(b Behavior, flag Behavior) bool { return b&flag != 0 diff --git a/gubernator_pool.go b/gubernator_pool.go index 77d57ed9..703dcbb8 100644 --- a/gubernator_pool.go +++ b/gubernator_pool.go @@ -247,7 +247,7 @@ func (chp *GubernatorPool) worker(worker *poolWorker) { } // Send a GetRateLimit request to worker pool. -func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimitReq) (retval *RateLimitResp, reterr error) { +func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScope(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -257,9 +257,10 @@ func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimi // Delegate request to assigned channel based on request key. worker := chp.getWorker(rlRequest.UniqueKey) handlerRequest := &request{ - ctx: ctx, - resp: make(chan *response, 1), - request: rlRequest, + ctx: ctx, + atomicCheck: ac, + resp: make(chan *response, 1), + request: rlRequest, } // Send request. @@ -297,7 +298,7 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac switch handlerRequest.request.Algorithm { case Algorithm_TOKEN_BUCKET: - rlResponse, err = tokenBucket(ctx, chp.conf.Store, cache, handlerRequest.request) + rlResponse, err = tokenBucket(ctx, chp.conf.Store, cache, handlerRequest.request, handlerRequest.atomicCheck) if err != nil { msg := "Error in tokenBucket" countError(err, msg) @@ -306,7 +307,7 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac } case Algorithm_LEAKY_BUCKET: - rlResponse, err = leakyBucket(ctx, chp.conf.Store, cache, handlerRequest.request) + rlResponse, err = leakyBucket(ctx, chp.conf.Store, cache, handlerRequest.request, handlerRequest.atomicCheck) if err != nil { msg := "Error in leakyBucket" countError(err, msg) diff --git a/peer_client.go b/peer_client.go index ac812ae6..e786b1c7 100644 --- a/peer_client.go +++ b/peer_client.go @@ -71,9 +71,10 @@ type response struct { } type request struct { - request *RateLimitReq - resp chan *response - ctx context.Context + request *RateLimitReq + resp chan *response + atomicCheck bool + ctx context.Context } type PeerConfig struct { From c8bab72986429d272f1df0761805f4cd574c83a6 Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Fri, 11 Nov 2022 16:20:17 +1100 Subject: [PATCH 4/7] :recycle: request proto contains atomic check --- algorithms.go | 53 +++++------ global.go | 3 +- gubernator.go | 38 ++++---- gubernator.pb.go | 135 +++++++++++++++------------- gubernator_pool.go | 13 ++- peers.pb.go | 90 +++++++++---------- proto/gubernator.proto | 3 + proto/peers.proto | 1 - python/gubernator/gubernator_pb2.py | 40 ++++----- python/gubernator/peers_pb2.py | 24 ++--- 10 files changed, 202 insertions(+), 198 deletions(-) diff --git a/algorithms.go b/algorithms.go index 27763057..c16eb681 100644 --- a/algorithms.go +++ b/algorithms.go @@ -28,7 +28,7 @@ import ( ) // Implements token bucket algorithm for rate limiting. https://en.wikipedia.org/wiki/Token_bucket -func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { +func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -114,7 +114,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool span.AddEvent("s.Remove()") } - return tokenBucketNewItem(ctx, s, c, r, ac) + return tokenBucketNewItem(ctx, s, c, r) } // Update the limit if it changed. @@ -180,7 +180,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool span.AddEvent("Already over the limit") rl.Status = Status_OVER_LIMIT t.Status = rl.Status - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } return rl, nil @@ -191,7 +191,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool if t.Remaining == r.Hits { span.AddEvent("At the limit") rl.Remaining = 0 - if !ac { + if !r.AtomicCheck { t.Remaining = 0 } return rl, nil @@ -202,7 +202,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool if r.Hits > t.Remaining { span.AddEvent("Over the limit") rl.Status = Status_OVER_LIMIT - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } return rl, nil @@ -211,7 +211,7 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool span.AddEvent("Under the limit") // if we are doing a check during atomic chaining then we only want // to update the response and not the actual value for the rate limit - if ac { + if r.AtomicCheck { rl.Remaining = t.Remaining - r.Hits } else { t.Remaining -= r.Hits @@ -221,11 +221,11 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool } // Item is not found in cache or store, create new. - return tokenBucketNewItem(ctx, s, c, r, ac) + return tokenBucketNewItem(ctx, s, c, r) } // Called by tokenBucket() when adding a new item in the store. -func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { +func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -243,7 +243,7 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, } // if we are doing a check during atomic chaining then remaining number is actually the limit - if ac { + if r.AtomicCheck { t.Remaining = r.Limit } @@ -273,7 +273,7 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, // Client could be requesting that we always return OVER_LIMIT. if r.Hits > r.Limit { span.AddEvent("Over the limit") - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } rl.Status = Status_OVER_LIMIT @@ -293,7 +293,7 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, } // Implements leaky bucket algorithm for rate limiting https://en.wikipedia.org/wiki/Leaky_bucket -func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { +func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -362,7 +362,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool span.AddEvent("s.Remove()") } - return leakyBucketNewItem(ctx, s, c, r, ac) + return leakyBucketNewItem(ctx, s, c, r) } if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { @@ -401,7 +401,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool duration = expire - (n.UnixNano() / 1000000) } - if r.Hits != 0 { + if r.Hits != 0 && !r.AtomicCheck { c.UpdateExpiration(r.HashKey(), now+duration) } @@ -436,7 +436,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool // If we are already at the limit if int64(b.Remaining) == 0 && r.Hits > 0 { - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } rl.Status = Status_OVER_LIMIT @@ -445,9 +445,9 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool // If requested hits takes the remainder if int64(b.Remaining) == r.Hits { - if !ac { + if !r.AtomicCheck { b.Remaining -= float64(r.Hits) - rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) + rl.ResetTime = now + (rl.Limit-int64(b.Remaining))*int64(rate) } rl.Remaining = 0 return rl, nil @@ -456,7 +456,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool // If requested is more than available, then return over the limit // without updating the bucket. if r.Hits > int64(b.Remaining) { - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } rl.Status = Status_OVER_LIMIT @@ -470,7 +470,7 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool // if we are doing a check during atomic chaining then we only want // to update the response and not the actual value for the rate limit - if ac { + if r.AtomicCheck { rl.Remaining = int64(b.Remaining - float64(r.Hits)) } else { b.Remaining -= float64(r.Hits) @@ -480,11 +480,11 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool return rl, nil } - return leakyBucketNewItem(ctx, s, c, r, ac) + return leakyBucketNewItem(ctx, s, c, r) } // Called by leakyBucket() when adding a new item in the store. -func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, ac bool) (resp *RateLimitResp, err error) { +func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp *RateLimitResp, err error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, err) @@ -514,11 +514,6 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, Burst: r.Burst, } - // if we are doing a check during atomic chaining then remaining number is actually the limit - if ac { - b.Remaining = float64(r.Limit) - } - rl := RateLimitResp{ Status: Status_UNDER_LIMIT, Limit: b.Limit, @@ -526,9 +521,15 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq, ResetTime: now + (b.Limit-(r.Burst-r.Hits))*int64(rate), } + // if we are doing a check during atomic chaining then remaining number is actually the burst limit + if r.AtomicCheck { + b.Remaining = float64(r.Burst) + rl.Remaining = r.Burst + } + // Client could be requesting that we start with the bucket OVER_LIMIT if r.Hits > r.Burst { - if !ac { + if !r.AtomicCheck { overLimitCounter.Add(1) } rl.Status = Status_OVER_LIMIT diff --git a/global.go b/global.go index c3d06b5f..a546cd88 100644 --- a/global.go +++ b/global.go @@ -129,7 +129,6 @@ func (gm *globalManager) sendHits(ctx context.Context, hits map[string]*RateLimi peerRequests := make(map[string]*pair) start := clock.Now() - // Assign each request to a peer for _, r := range hits { peer, err := gm.instance.GetPeer(ctx, r.HashKey()) if err != nil { @@ -215,7 +214,7 @@ func (gm *globalManager) broadcastPeers(ctx context.Context, updates map[string] rl.Hits = 0 // we can invoke with atomicCheck = false as we are just getting status by using hits = 0 - status, err := gm.instance.getRateLimit(ctx, rl, false) + status, err := gm.instance.getRateLimit(ctx, rl) if err != nil { gm.log.WithError(err).Errorf("while broadcasting update to peers for: '%s'", rl.HashKey()) continue diff --git a/gubernator.go b/gubernator.go index a55ad63a..30bfca0c 100644 --- a/gubernator.go +++ b/gubernator.go @@ -236,13 +236,13 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re return &resp, nil } -func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRateLimitsReq, resp *GetRateLimitsResp, ac bool) []*RateLimitResp { +func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRateLimitsReq, resp *GetRateLimitsResp, atomicCheck bool) []*RateLimitResp { var wg sync.WaitGroup asyncCh := make(chan AsyncResp, len(r.Requests)) // update the trace name if this is an atomic check ts := "Iterate requests" - if ac { + if atomicCheck { ts = fmt.Sprintf("%s - atomic check", ts) } @@ -253,6 +253,9 @@ func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRat var peer *PeerClient var err error + // set the atomic check flag on the reqest object + req.AtomicCheck = atomicCheck + if len(req.UniqueKey) == 0 { checkErrorCounter.WithLabelValues("Invalid request").Add(1) resp.Responses[i] = &RateLimitResp{Error: "field 'unique_key' cannot be empty"} @@ -287,11 +290,11 @@ func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRat // If our server instance is the owner of this rate limit if peer.Info().IsOwner { // Apply our rate limit algorithm to the request - if !ac { + if !atomicCheck { getRateLimitCounter.WithLabelValues("local").Add(1) } funcTimer1 := prometheus.NewTimer(funcTimeMetric.WithLabelValues("V1Instance.getRateLimit (local)")) - resp.Responses[i], err = s.getRateLimit(ctx, req, ac) + resp.Responses[i], err = s.getRateLimit(ctx, req) funcTimer1.ObserveDuration() if err != nil { err = errors.Wrapf(err, "Error while apply rate limit for '%s'", key) @@ -300,7 +303,7 @@ func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRat } } else { if HasBehavior(req.Behavior, Behavior_GLOBAL) { - resp.Responses[i], err = s.getGlobalRateLimit(ctx, req, ac) + resp.Responses[i], err = s.getGlobalRateLimit(ctx, req) if err != nil { err = errors.Wrap(err, "Error in getGlobalRateLimit") span.RecordError(err) @@ -316,13 +319,12 @@ func (s *V1Instance) checkLimits(ctx context.Context, span trace.Span, r *GetRat // Launch remote peer request in goroutine. wg.Add(1) go s.asyncRequests(ctx, &AsyncReq{ - AsyncCh: asyncCh, - Peer: peer, - Req: req, - WG: &wg, - Key: key, - Idx: i, - atomicCheck: ac, + AsyncCh: asyncCh, + Peer: peer, + Req: req, + WG: &wg, + Key: key, + Idx: i, }) } @@ -395,7 +397,7 @@ func (s *V1Instance) asyncRequests(ctx context.Context, req *AsyncReq) { if attempts != 0 { if req.Peer.Info().IsOwner { getRateLimitCounter.WithLabelValues("local").Add(1) - resp.Resp, err = s.getRateLimit(ctx, req.Req, req.atomicCheck) + resp.Resp, err = s.getRateLimit(ctx, req.Req) if err != nil { s.log.WithContext(ctx). WithError(err). @@ -450,7 +452,7 @@ func (s *V1Instance) asyncRequests(ctx context.Context, req *AsyncReq) { // getGlobalRateLimit handles rate limits that are marked as `Behavior = GLOBAL`. Rate limit responses // are returned from the local cache and the hits are queued to be sent to the owning peer. -func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { +func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScope(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -484,7 +486,7 @@ func (s *V1Instance) getGlobalRateLimit(ctx context.Context, req *RateLimitReq, // Process the rate limit like we own it getRateLimitCounter.WithLabelValues("global").Add(1) - resp, err := s.getRateLimit(ctx, cpy, ac) + resp, err := s.getRateLimit(ctx, cpy) if err != nil { return nil, errors.Wrap(err, "Error in getRateLimit") } @@ -563,7 +565,7 @@ func (s *V1Instance) GetPeerRateLimits(ctx context.Context, r *GetPeerRateLimits for idx, req := range r.Requests { fan.Run(func(in interface{}) error { rin := in.(reqIn) - rl, err := s.getRateLimit(ctx, rin.req, r.AtomicCheck) + rl, err := s.getRateLimit(ctx, rin.req) if err != nil { // Return the error for this request err = errors.Wrap(err, "Error in getRateLimit") @@ -645,7 +647,7 @@ func (s *V1Instance) HealthCheck(ctx context.Context, r *HealthCheckReq) (retval return &health, nil } -func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { +func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScopeDebug(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -672,7 +674,7 @@ func (s *V1Instance) getRateLimit(ctx context.Context, r *RateLimitReq, ac bool) span.AddEvent("s.multiRegion.QueueHits(r)") } - resp, err := s.gubernatorPool.GetRateLimit(ctx, r, ac) + resp, err := s.gubernatorPool.GetRateLimit(ctx, r) if isDeadlineExceeded(err) { checkErrorCounter.WithLabelValues("Timeout").Add(1) } diff --git a/gubernator.pb.go b/gubernator.pb.go index ea94cd21..99bbca3c 100644 --- a/gubernator.pb.go +++ b/gubernator.pb.go @@ -421,6 +421,8 @@ type RateLimitReq struct { Behavior Behavior `protobuf:"varint,7,opt,name=behavior,proto3,enum=pb.gubernator.Behavior" json:"behavior,omitempty"` // Maximum burst size that the limit can accept. Burst int64 `protobuf:"varint,8,opt,name=burst,proto3" json:"burst,omitempty"` + // flag to determine if this request is part of an atomic chain + AtomicCheck bool `protobuf:"varint,9,opt,name=atomicCheck,proto3" json:"atomicCheck,omitempty"` } func (x *RateLimitReq) Reset() { @@ -511,6 +513,13 @@ func (x *RateLimitReq) GetBurst() int64 { return 0 } +func (x *RateLimitReq) GetAtomicCheck() bool { + if x != nil { + return x.AtomicCheck + } + return false +} + type RateLimitResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -728,7 +737,7 @@ var file_gubernator_proto_rawDesc = []byte{ 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x0c, 0x52, 0x61, 0x74, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0xac, 0x02, 0x0a, 0x0c, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -745,67 +754,69 @@ var file_gubernator_proto_rawDesc = []byte{ 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x72, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, - 0x62, 0x75, 0x72, 0x73, 0x74, 0x22, 0xac, 0x02, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, - 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, - 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x73, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x72, 0x65, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, - 0x46, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x10, 0x0a, 0x0e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x22, 0x62, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, - 0x65, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x2f, 0x0a, 0x09, 0x41, 0x6c, - 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x4f, 0x4b, 0x45, 0x4e, - 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x45, 0x41, - 0x4b, 0x59, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, 0x2a, 0x77, 0x0a, 0x08, 0x42, - 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x41, 0x54, 0x43, 0x48, - 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x5f, 0x42, 0x41, 0x54, 0x43, - 0x48, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, - 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, - 0x53, 0x5f, 0x47, 0x52, 0x45, 0x47, 0x4f, 0x52, 0x49, 0x41, 0x4e, 0x10, 0x04, 0x12, 0x13, 0x0a, - 0x0f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x41, 0x49, 0x4e, 0x49, 0x4e, 0x47, - 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x52, 0x45, 0x47, 0x49, - 0x4f, 0x4e, 0x10, 0x10, 0x2a, 0x35, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x68, - 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x44, 0x45, 0x50, 0x45, 0x4e, - 0x44, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x54, 0x4f, 0x4d, 0x49, 0x43, - 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x53, 0x10, 0x01, 0x2a, 0x29, 0x0a, 0x06, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x4c, - 0x49, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4c, - 0x49, 0x4d, 0x49, 0x54, 0x10, 0x01, 0x32, 0xdd, 0x01, 0x0a, 0x02, 0x56, 0x31, 0x12, 0x70, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x1f, - 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, - 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, - 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x47, - 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x12, - 0x65, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, - 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, - 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, 0x17, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, 0x75, 0x62, - 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x62, 0x75, 0x72, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x74, 0x6f, 0x6d, + 0x69, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0xac, 0x02, 0x0a, 0x0d, 0x52, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x62, 0x2e, 0x67, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x46, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x10, 0x0a, 0x0e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x22, 0x62, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x2f, 0x0a, 0x09, + 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x4f, 0x4b, + 0x45, 0x4e, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4c, + 0x45, 0x41, 0x4b, 0x59, 0x5f, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, 0x2a, 0x77, 0x0a, + 0x08, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x41, 0x54, + 0x43, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x5f, 0x42, 0x41, + 0x54, 0x43, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, + 0x41, 0x4c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x49, 0x53, 0x5f, 0x47, 0x52, 0x45, 0x47, 0x4f, 0x52, 0x49, 0x41, 0x4e, 0x10, 0x04, 0x12, + 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x4d, 0x41, 0x49, 0x4e, 0x49, + 0x4e, 0x47, 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x52, 0x45, + 0x47, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x2a, 0x35, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x42, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e, 0x44, 0x45, 0x50, + 0x45, 0x4e, 0x44, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x54, 0x4f, 0x4d, + 0x49, 0x43, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x53, 0x10, 0x01, 0x2a, 0x29, 0x0a, + 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x44, 0x45, 0x52, + 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x01, 0x32, 0xdd, 0x01, 0x0a, 0x02, 0x56, 0x31, 0x12, + 0x70, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x12, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x1a, 0x20, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, + 0x2f, 0x47, 0x65, 0x74, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x3a, 0x01, + 0x2a, 0x12, 0x65, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x12, 0x1d, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, + 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gubernator_pool.go b/gubernator_pool.go index 703dcbb8..77d57ed9 100644 --- a/gubernator_pool.go +++ b/gubernator_pool.go @@ -247,7 +247,7 @@ func (chp *GubernatorPool) worker(worker *poolWorker) { } // Send a GetRateLimit request to worker pool. -func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimitReq, ac bool) (retval *RateLimitResp, reterr error) { +func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimitReq) (retval *RateLimitResp, reterr error) { ctx = tracing.StartScope(ctx) defer func() { tracing.EndScope(ctx, reterr) @@ -257,10 +257,9 @@ func (chp *GubernatorPool) GetRateLimit(ctx context.Context, rlRequest *RateLimi // Delegate request to assigned channel based on request key. worker := chp.getWorker(rlRequest.UniqueKey) handlerRequest := &request{ - ctx: ctx, - atomicCheck: ac, - resp: make(chan *response, 1), - request: rlRequest, + ctx: ctx, + resp: make(chan *response, 1), + request: rlRequest, } // Send request. @@ -298,7 +297,7 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac switch handlerRequest.request.Algorithm { case Algorithm_TOKEN_BUCKET: - rlResponse, err = tokenBucket(ctx, chp.conf.Store, cache, handlerRequest.request, handlerRequest.atomicCheck) + rlResponse, err = tokenBucket(ctx, chp.conf.Store, cache, handlerRequest.request) if err != nil { msg := "Error in tokenBucket" countError(err, msg) @@ -307,7 +306,7 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac } case Algorithm_LEAKY_BUCKET: - rlResponse, err = leakyBucket(ctx, chp.conf.Store, cache, handlerRequest.request, handlerRequest.atomicCheck) + rlResponse, err = leakyBucket(ctx, chp.conf.Store, cache, handlerRequest.request) if err != nil { msg := "Error in leakyBucket" countError(err, msg) diff --git a/peers.pb.go b/peers.pb.go index 857b98c6..1a7204b0 100644 --- a/peers.pb.go +++ b/peers.pb.go @@ -42,8 +42,7 @@ type GetPeerRateLimitsReq struct { // Must specify at least one RateLimit. The peer that recives this request MUST be authoritative for // each rate_limit[x].unique_key provided, as the peer will not forward the request to any other peers - Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` - AtomicCheck bool `protobuf:"varint,2,opt,name=atomicCheck,proto3" json:"atomicCheck,omitempty"` + Requests []*RateLimitReq `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests,omitempty"` } func (x *GetPeerRateLimitsReq) Reset() { @@ -85,13 +84,6 @@ func (x *GetPeerRateLimitsReq) GetRequests() []*RateLimitReq { return nil } -func (x *GetPeerRateLimitsReq) GetAtomicCheck() bool { - if x != nil { - return x.AtomicCheck - } - return false -} - type GetPeerRateLimitsResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -294,52 +286,50 @@ var File_peers_proto protoreflect.FileDescriptor var file_peers_proto_rawDesc = []byte{ 0x0a, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x1a, 0x10, 0x67, 0x75, - 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x71, + 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, - 0x20, 0x0a, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x22, 0x56, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x61, - 0x74, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, - 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x0a, 0x72, - 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, - 0x71, 0x12, 0x39, 0x0a, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x52, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x22, 0x92, 0x01, 0x0a, - 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, - 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, - 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x22, 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x32, 0xcd, 0x01, 0x0a, 0x07, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x56, 0x31, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, - 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, - 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, - 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, + 0x56, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3d, 0x0a, 0x0b, 0x72, 0x61, 0x74, 0x65, + 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, 0x0a, 0x72, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x22, 0x51, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x12, + 0x39, 0x0a, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x52, 0x07, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x10, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x62, 0x2e, + 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, + 0x17, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x32, 0xcd, 0x01, 0x0a, 0x07, 0x50, 0x65, 0x65, + 0x72, 0x73, 0x56, 0x31, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, 0x2e, 0x67, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, + 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x24, + 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x62, + 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, - 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x12, 0x23, 0x2e, - 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x52, - 0x65, 0x71, 0x1a, 0x24, 0x2e, 0x70, 0x62, 0x2e, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, - 0x2f, 0x67, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x22, 0x5a, 0x1d, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x61, 0x69, 0x6c, 0x67, 0x75, 0x6e, 0x2f, 0x67, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/gubernator.proto b/proto/gubernator.proto index 4166eea2..6428659d 100644 --- a/proto/gubernator.proto +++ b/proto/gubernator.proto @@ -173,6 +173,9 @@ message RateLimitReq { // Maximum burst size that the limit can accept. int64 burst = 8; + + // flag to determine if this request is part of an atomic chain + bool atomicCheck = 9; } enum Status { diff --git a/proto/peers.proto b/proto/peers.proto index 38dfc26f..5caefae4 100644 --- a/proto/peers.proto +++ b/proto/peers.proto @@ -37,7 +37,6 @@ message GetPeerRateLimitsReq { // Must specify at least one RateLimit. The peer that recives this request MUST be authoritative for // each rate_limit[x].unique_key provided, as the peer will not forward the request to any other peers repeated RateLimitReq requests = 1; - bool atomicCheck = 2; } message GetPeerRateLimitsResp { diff --git a/python/gubernator/gubernator_pb2.py b/python/gubernator/gubernator_pb2.py index 3081072c..cc7f0d1b 100644 --- a/python/gubernator/gubernator_pb2.py +++ b/python/gubernator/gubernator_pb2.py @@ -14,7 +14,7 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10gubernator.proto\x12\rpb.gubernator\x1a\x1cgoogle/api/annotations.proto\"q\n\x10GetRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\x12.\n\x08\x42\x65havior\x18\x02 \x01(\x0e\x32\x1c.pb.gubernator.UnionBehavior\"D\n\x11GetRateLimitsResp\x12/\n\tresponses\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"\xc6\x01\n\x0cRateLimitReq\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nunique_key\x18\x02 \x01(\t\x12\x0c\n\x04hits\x18\x03 \x01(\x03\x12\r\n\x05limit\x18\x04 \x01(\x03\x12\x10\n\x08\x64uration\x18\x05 \x01(\x03\x12+\n\talgorithm\x18\x06 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\x12)\n\x08\x62\x65havior\x18\x07 \x01(\x0e\x32\x17.pb.gubernator.Behavior\x12\r\n\x05\x62urst\x18\x08 \x01(\x03\"\xea\x01\n\rRateLimitResp\x12%\n\x06status\x18\x01 \x01(\x0e\x32\x15.pb.gubernator.Status\x12\r\n\x05limit\x18\x02 \x01(\x03\x12\x11\n\tremaining\x18\x03 \x01(\x03\x12\x12\n\nreset_time\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12<\n\x08metadata\x18\x06 \x03(\x0b\x32*.pb.gubernator.RateLimitResp.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x10\n\x0eHealthCheckReq\"F\n\x0fHealthCheckResp\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\npeer_count\x18\x03 \x01(\x05*/\n\tAlgorithm\x12\x10\n\x0cTOKEN_BUCKET\x10\x00\x12\x10\n\x0cLEAKY_BUCKET\x10\x01*w\n\x08\x42\x65havior\x12\x0c\n\x08\x42\x41TCHING\x10\x00\x12\x0f\n\x0bNO_BATCHING\x10\x01\x12\n\n\x06GLOBAL\x10\x02\x12\x19\n\x15\x44URATION_IS_GREGORIAN\x10\x04\x12\x13\n\x0fRESET_REMAINING\x10\x08\x12\x10\n\x0cMULTI_REGION\x10\x10*5\n\rUnionBehavior\x12\x0f\n\x0bINDEPENDENT\x10\x00\x12\x13\n\x0f\x41TOMIC_REQUESTS\x10\x01*)\n\x06Status\x12\x0f\n\x0bUNDER_LIMIT\x10\x00\x12\x0e\n\nOVER_LIMIT\x10\x01\x32\xdd\x01\n\x02V1\x12p\n\rGetRateLimits\x12\x1f.pb.gubernator.GetRateLimitsReq\x1a .pb.gubernator.GetRateLimitsResp\"\x1c\x82\xd3\xe4\x93\x02\x16\"\x11/v1/GetRateLimits:\x01*\x12\x65\n\x0bHealthCheck\x12\x1d.pb.gubernator.HealthCheckReq\x1a\x1e.pb.gubernator.HealthCheckResp\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/v1/HealthCheckB\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10gubernator.proto\x12\rpb.gubernator\x1a\x1cgoogle/api/annotations.proto\"q\n\x10GetRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\x12.\n\x08\x42\x65havior\x18\x02 \x01(\x0e\x32\x1c.pb.gubernator.UnionBehavior\"D\n\x11GetRateLimitsResp\x12/\n\tresponses\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"\xdb\x01\n\x0cRateLimitReq\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nunique_key\x18\x02 \x01(\t\x12\x0c\n\x04hits\x18\x03 \x01(\x03\x12\r\n\x05limit\x18\x04 \x01(\x03\x12\x10\n\x08\x64uration\x18\x05 \x01(\x03\x12+\n\talgorithm\x18\x06 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\x12)\n\x08\x62\x65havior\x18\x07 \x01(\x0e\x32\x17.pb.gubernator.Behavior\x12\r\n\x05\x62urst\x18\x08 \x01(\x03\x12\x13\n\x0b\x61tomicCheck\x18\t \x01(\x08\"\xea\x01\n\rRateLimitResp\x12%\n\x06status\x18\x01 \x01(\x0e\x32\x15.pb.gubernator.Status\x12\r\n\x05limit\x18\x02 \x01(\x03\x12\x11\n\tremaining\x18\x03 \x01(\x03\x12\x12\n\nreset_time\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12<\n\x08metadata\x18\x06 \x03(\x0b\x32*.pb.gubernator.RateLimitResp.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x10\n\x0eHealthCheckReq\"F\n\x0fHealthCheckResp\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\npeer_count\x18\x03 \x01(\x05*/\n\tAlgorithm\x12\x10\n\x0cTOKEN_BUCKET\x10\x00\x12\x10\n\x0cLEAKY_BUCKET\x10\x01*w\n\x08\x42\x65havior\x12\x0c\n\x08\x42\x41TCHING\x10\x00\x12\x0f\n\x0bNO_BATCHING\x10\x01\x12\n\n\x06GLOBAL\x10\x02\x12\x19\n\x15\x44URATION_IS_GREGORIAN\x10\x04\x12\x13\n\x0fRESET_REMAINING\x10\x08\x12\x10\n\x0cMULTI_REGION\x10\x10*5\n\rUnionBehavior\x12\x0f\n\x0bINDEPENDENT\x10\x00\x12\x13\n\x0f\x41TOMIC_REQUESTS\x10\x01*)\n\x06Status\x12\x0f\n\x0bUNDER_LIMIT\x10\x00\x12\x0e\n\nOVER_LIMIT\x10\x01\x32\xdd\x01\n\x02V1\x12p\n\rGetRateLimits\x12\x1f.pb.gubernator.GetRateLimitsReq\x1a .pb.gubernator.GetRateLimitsResp\"\x1c\x82\xd3\xe4\x93\x02\x16\"\x11/v1/GetRateLimits:\x01*\x12\x65\n\x0bHealthCheck\x12\x1d.pb.gubernator.HealthCheckReq\x1a\x1e.pb.gubernator.HealthCheckResp\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/v1/HealthCheckB\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'gubernator_pb2', globals()) @@ -28,28 +28,28 @@ _V1.methods_by_name['GetRateLimits']._serialized_options = b'\202\323\344\223\002\026\"\021/v1/GetRateLimits:\001*' _V1.methods_by_name['HealthCheck']._options = None _V1.methods_by_name['HealthCheck']._serialized_options = b'\202\323\344\223\002\021\022\017/v1/HealthCheck' - _ALGORITHM._serialized_start=778 - _ALGORITHM._serialized_end=825 - _BEHAVIOR._serialized_start=827 - _BEHAVIOR._serialized_end=946 - _UNIONBEHAVIOR._serialized_start=948 - _UNIONBEHAVIOR._serialized_end=1001 - _STATUS._serialized_start=1003 - _STATUS._serialized_end=1044 + _ALGORITHM._serialized_start=799 + _ALGORITHM._serialized_end=846 + _BEHAVIOR._serialized_start=848 + _BEHAVIOR._serialized_end=967 + _UNIONBEHAVIOR._serialized_start=969 + _UNIONBEHAVIOR._serialized_end=1022 + _STATUS._serialized_start=1024 + _STATUS._serialized_end=1065 _GETRATELIMITSREQ._serialized_start=65 _GETRATELIMITSREQ._serialized_end=178 _GETRATELIMITSRESP._serialized_start=180 _GETRATELIMITSRESP._serialized_end=248 _RATELIMITREQ._serialized_start=251 - _RATELIMITREQ._serialized_end=449 - _RATELIMITRESP._serialized_start=452 - _RATELIMITRESP._serialized_end=686 - _RATELIMITRESP_METADATAENTRY._serialized_start=639 - _RATELIMITRESP_METADATAENTRY._serialized_end=686 - _HEALTHCHECKREQ._serialized_start=688 - _HEALTHCHECKREQ._serialized_end=704 - _HEALTHCHECKRESP._serialized_start=706 - _HEALTHCHECKRESP._serialized_end=776 - _V1._serialized_start=1047 - _V1._serialized_end=1268 + _RATELIMITREQ._serialized_end=470 + _RATELIMITRESP._serialized_start=473 + _RATELIMITRESP._serialized_end=707 + _RATELIMITRESP_METADATAENTRY._serialized_start=660 + _RATELIMITRESP_METADATAENTRY._serialized_end=707 + _HEALTHCHECKREQ._serialized_start=709 + _HEALTHCHECKREQ._serialized_end=725 + _HEALTHCHECKRESP._serialized_start=727 + _HEALTHCHECKRESP._serialized_end=797 + _V1._serialized_start=1068 + _V1._serialized_end=1289 # @@protoc_insertion_point(module_scope) diff --git a/python/gubernator/peers_pb2.py b/python/gubernator/peers_pb2.py index 00a45ec6..98ade704 100644 --- a/python/gubernator/peers_pb2.py +++ b/python/gubernator/peers_pb2.py @@ -14,7 +14,7 @@ import gubernator_pb2 as gubernator__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bpeers.proto\x12\rpb.gubernator\x1a\x10gubernator.proto\"Z\n\x14GetPeerRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\x12\x13\n\x0b\x61tomicCheck\x18\x02 \x01(\x08\"J\n\x15GetPeerRateLimitsResp\x12\x31\n\x0brate_limits\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"H\n\x14UpdatePeerGlobalsReq\x12\x30\n\x07globals\x18\x01 \x03(\x0b\x32\x1f.pb.gubernator.UpdatePeerGlobal\"z\n\x10UpdatePeerGlobal\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x06status\x18\x02 \x01(\x0b\x32\x1c.pb.gubernator.RateLimitResp\x12+\n\talgorithm\x18\x03 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\"\x17\n\x15UpdatePeerGlobalsResp2\xcd\x01\n\x07PeersV1\x12`\n\x11GetPeerRateLimits\x12#.pb.gubernator.GetPeerRateLimitsReq\x1a$.pb.gubernator.GetPeerRateLimitsResp\"\x00\x12`\n\x11UpdatePeerGlobals\x12#.pb.gubernator.UpdatePeerGlobalsReq\x1a$.pb.gubernator.UpdatePeerGlobalsResp\"\x00\x42\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bpeers.proto\x12\rpb.gubernator\x1a\x10gubernator.proto\"E\n\x14GetPeerRateLimitsReq\x12-\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReq\"J\n\x15GetPeerRateLimitsResp\x12\x31\n\x0brate_limits\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitResp\"H\n\x14UpdatePeerGlobalsReq\x12\x30\n\x07globals\x18\x01 \x03(\x0b\x32\x1f.pb.gubernator.UpdatePeerGlobal\"z\n\x10UpdatePeerGlobal\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x06status\x18\x02 \x01(\x0b\x32\x1c.pb.gubernator.RateLimitResp\x12+\n\talgorithm\x18\x03 \x01(\x0e\x32\x18.pb.gubernator.Algorithm\"\x17\n\x15UpdatePeerGlobalsResp2\xcd\x01\n\x07PeersV1\x12`\n\x11GetPeerRateLimits\x12#.pb.gubernator.GetPeerRateLimitsReq\x1a$.pb.gubernator.GetPeerRateLimitsResp\"\x00\x12`\n\x11UpdatePeerGlobals\x12#.pb.gubernator.UpdatePeerGlobalsReq\x1a$.pb.gubernator.UpdatePeerGlobalsResp\"\x00\x42\"Z\x1dgithub.com/mailgun/gubernator\x80\x01\x01\x62\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'peers_pb2', globals()) @@ -23,15 +23,15 @@ DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'Z\035github.com/mailgun/gubernator\200\001\001' _GETPEERRATELIMITSREQ._serialized_start=48 - _GETPEERRATELIMITSREQ._serialized_end=138 - _GETPEERRATELIMITSRESP._serialized_start=140 - _GETPEERRATELIMITSRESP._serialized_end=214 - _UPDATEPEERGLOBALSREQ._serialized_start=216 - _UPDATEPEERGLOBALSREQ._serialized_end=288 - _UPDATEPEERGLOBAL._serialized_start=290 - _UPDATEPEERGLOBAL._serialized_end=412 - _UPDATEPEERGLOBALSRESP._serialized_start=414 - _UPDATEPEERGLOBALSRESP._serialized_end=437 - _PEERSV1._serialized_start=440 - _PEERSV1._serialized_end=645 + _GETPEERRATELIMITSREQ._serialized_end=117 + _GETPEERRATELIMITSRESP._serialized_start=119 + _GETPEERRATELIMITSRESP._serialized_end=193 + _UPDATEPEERGLOBALSREQ._serialized_start=195 + _UPDATEPEERGLOBALSREQ._serialized_end=267 + _UPDATEPEERGLOBAL._serialized_start=269 + _UPDATEPEERGLOBAL._serialized_end=391 + _UPDATEPEERGLOBALSRESP._serialized_start=393 + _UPDATEPEERGLOBALSRESP._serialized_end=416 + _PEERSV1._serialized_start=419 + _PEERSV1._serialized_end=624 # @@protoc_insertion_point(module_scope) From 2e3f5e454092cdc79a84ba1c87c4b3ba6257d017 Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Fri, 11 Nov 2022 17:08:21 +1100 Subject: [PATCH 5/7] :white_check_mark: atomic chaining integration test --- algorithms.go | 22 +++--- functional_test.go | 163 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 11 deletions(-) diff --git a/algorithms.go b/algorithms.go index c16eb681..2845435b 100644 --- a/algorithms.go +++ b/algorithms.go @@ -242,11 +242,6 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) CreatedAt: now, } - // if we are doing a check during atomic chaining then remaining number is actually the limit - if r.AtomicCheck { - t.Remaining = r.Limit - } - item := &CacheItem{ Algorithm: Algorithm_TOKEN_BUCKET, Key: r.HashKey(), @@ -270,15 +265,22 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) ResetTime: expire, } + // if we are doing a check during atomic chaining then remaining number is actually the limit + // but we should respond with what the value would be as if it had been applied + if r.AtomicCheck { + t.Remaining = r.Limit + rl.Remaining = r.Limit - r.Hits + } + // Client could be requesting that we always return OVER_LIMIT. + if r.Hits > r.Limit { span.AddEvent("Over the limit") if !r.AtomicCheck { overLimitCounter.Add(1) + t.Remaining = r.Limit } rl.Status = Status_OVER_LIMIT - rl.Remaining = r.Limit - t.Remaining = r.Limit } c.Add(item) @@ -522,20 +524,20 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) } // if we are doing a check during atomic chaining then remaining number is actually the burst limit + // but we should respond with what the value would be as if it had been applied if r.AtomicCheck { b.Remaining = float64(r.Burst) - rl.Remaining = r.Burst + rl.Remaining = r.Burst - r.Hits } // Client could be requesting that we start with the bucket OVER_LIMIT if r.Hits > r.Burst { if !r.AtomicCheck { overLimitCounter.Add(1) + b.Remaining = 0 } rl.Status = Status_OVER_LIMIT - rl.Remaining = 0 rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) - b.Remaining = 0 } item := &CacheItem{ diff --git a/functional_test.go b/functional_test.go index f319dff1..b711427f 100644 --- a/functional_test.go +++ b/functional_test.go @@ -1218,7 +1218,168 @@ func TestGetPeerRateLimits(t *testing.T) { }) } -// TODO: Add a test for sending no rate limits RateLimitReqList.RateLimits = nil +// Test multiple rate limits with atomic chaining enabled: +// should behave as normal if a rate limit is not exceeded +// should fail without incrementing rate limits if +func TestAtomicChainingMultipleLimits(t *testing.T) { + // If the consistent hash changes or the number of peers changes, this might + // need to be changed. We want the test to forward both rate limits to other + // nodes in the cluster. + + t.Logf("Asking Peer: %s", cluster.GetPeers()[0].GRPCAddress) + client, errs := guber.DialV1Server(cluster.GetPeers()[0].GRPCAddress, nil) + require.Nil(t, errs) + + // send 2 different requests with atomic chaining on configured, second one starts over limit + resp, err := client.GetRateLimits(context.Background(), &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{ + { + Name: "test_atomic_chaining", + UniqueKey: "account:9234", + Algorithm: guber.Algorithm_TOKEN_BUCKET, + Duration: guber.Second * 9, + Limit: 2, + Hits: 1, + Behavior: 0, + }, + { + Name: "test_atomic_chaining", + UniqueKey: "account:5678", + Algorithm: guber.Algorithm_LEAKY_BUCKET, + Duration: guber.Second * 9, + Limit: 10, + Hits: 11, + Behavior: 0, + }, + }, + Behavior: guber.UnionBehavior_ATOMIC_REQUESTS, + }) + require.Nil(t, err) + + require.Len(t, resp.Responses, 2) + + rl := resp.Responses[0] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(1), rl.Remaining) + assert.Equal(t, int64(2), rl.Limit) + + rl = resp.Responses[1] + assert.Equal(t, guber.Status_OVER_LIMIT, rl.Status) + assert.Equal(t, int64(10), rl.Limit) + + // fire requests again but with a lower limit and all should increment their respective limits + resp, err = client.GetRateLimits(context.Background(), &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{ + { + Name: "test_atomic_chaining", + UniqueKey: "account:9234", + Algorithm: guber.Algorithm_TOKEN_BUCKET, + Duration: guber.Second * 9, + Limit: 2, + Hits: 1, + Behavior: 0, + }, + { + Name: "test_atomic_chaining", + UniqueKey: "account:5678", + Algorithm: guber.Algorithm_LEAKY_BUCKET, + Duration: guber.Second * 9, + Limit: 10, + Hits: 5, + Behavior: 0, + }, + }, + Behavior: guber.UnionBehavior_ATOMIC_REQUESTS, + }) + require.Nil(t, err) + + require.Len(t, resp.Responses, 2) + + rl = resp.Responses[0] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(1), rl.Remaining) + assert.Equal(t, int64(2), rl.Limit) + + rl = resp.Responses[1] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(5), rl.Remaining) + assert.Equal(t, int64(10), rl.Limit) + + // Exceed the first rate limit, second should not be impacted + resp, err = client.GetRateLimits(context.Background(), &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{ + { + Name: "test_atomic_chaining", + UniqueKey: "account:9234", + Algorithm: guber.Algorithm_TOKEN_BUCKET, + Duration: guber.Second * 9, + Limit: 2, + Hits: 2, + Behavior: 0, + }, + { + Name: "test_atomic_chaining", + UniqueKey: "account:5678", + Algorithm: guber.Algorithm_LEAKY_BUCKET, + Duration: guber.Second * 9, + Limit: 10, + Hits: 1, + Behavior: 0, + }, + }, + Behavior: guber.UnionBehavior_ATOMIC_REQUESTS, + }) + require.Nil(t, err) + + require.Len(t, resp.Responses, 2) + + rl = resp.Responses[0] + assert.Equal(t, guber.Status_OVER_LIMIT, rl.Status) + assert.Equal(t, int64(2), rl.Limit) + + rl = resp.Responses[1] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(4), rl.Remaining) + assert.Equal(t, int64(10), rl.Limit) + + // Send another atomic pair, the second won't have been modified by the previous request as one of the limits was exceeded. + resp, err = client.GetRateLimits(context.Background(), &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{ + { + Name: "test_atomic_chaining", + UniqueKey: "account:9234", + Algorithm: guber.Algorithm_TOKEN_BUCKET, + Duration: guber.Second * 9, + Limit: 2, + Hits: 1, + Behavior: 0, + }, + { + Name: "test_atomic_chaining", + UniqueKey: "account:5678", + Algorithm: guber.Algorithm_LEAKY_BUCKET, + Duration: guber.Second * 9, + Limit: 10, + Hits: 1, + Behavior: 0, + }, + }, + Behavior: guber.UnionBehavior_ATOMIC_REQUESTS, + }) + require.Nil(t, err) + + require.Len(t, resp.Responses, 2) + + rl = resp.Responses[0] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(0), rl.Remaining) + assert.Equal(t, int64(2), rl.Limit) + + rl = resp.Responses[1] + assert.Equal(t, guber.Status_UNDER_LIMIT, rl.Status) + assert.Equal(t, int64(4), rl.Remaining) + assert.Equal(t, int64(10), rl.Limit) +} func getMetric(t testutil.TestingT, in io.Reader, name string) *model.Sample { dec := expfmt.SampleDecoder{ From e35a4fd57596634587000616619632450167bfe4 Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Fri, 11 Nov 2022 17:17:37 +1100 Subject: [PATCH 6/7] :white_check_mark: add missing test for nil requests --- functional_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/functional_test.go b/functional_test.go index b711427f..1c499f14 100644 --- a/functional_test.go +++ b/functional_test.go @@ -1381,6 +1381,17 @@ func TestAtomicChainingMultipleLimits(t *testing.T) { assert.Equal(t, int64(10), rl.Limit) } +func TestRequestNoRateLimits(t *testing.T) { + // test for sending no rate limits RateLimitReqList.RateLimits = nil + client, errs := guber.DialV1Server(cluster.GetPeers()[0].GRPCAddress, nil) + require.Nil(t, errs) + resp, err := client.GetRateLimits(context.Background(), &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{}, + }) + require.Nil(t, err) + assert.Equal(t, 0, len(resp.Responses)) +} + func getMetric(t testutil.TestingT, in io.Reader, name string) *model.Sample { dec := expfmt.SampleDecoder{ Dec: expfmt.NewDecoder(in, expfmt.FmtText), From f73f99742f4f17975b63dc9fabcf852f39b22ac3 Mon Sep 17 00:00:00 2001 From: "tasman.mayers@protonmail.com" Date: Sun, 13 Nov 2022 12:58:47 +1100 Subject: [PATCH 7/7] :recycle: refactor alorithms update logic + cleanup --- algorithms.go | 638 ++++++++++++++++++++--------------------- gubernator.go | 5 +- gubernator_pool.go | 12 + peer_client.go | 7 +- proto/gubernator.proto | 3 - 5 files changed, 325 insertions(+), 340 deletions(-) diff --git a/algorithms.go b/algorithms.go index 2845435b..27164b0a 100644 --- a/algorithms.go +++ b/algorithms.go @@ -21,6 +21,7 @@ import ( "github.com/mailgun/holster/v4/clock" "github.com/mailgun/holster/v4/tracing" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" "go.opentelemetry.io/otel/attribute" @@ -38,190 +39,139 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * tokenBucketTimer := prometheus.NewTimer(funcTimeMetric.WithLabelValues("tokenBucket")) defer tokenBucketTimer.ObserveDuration() - // Get rate limit from cache. - hashKey := r.HashKey() - item, ok := c.GetItem(hashKey) - span.AddEvent("c.GetItem()") - - if s != nil && !ok { - // Cache miss. - // Check our store for the item. - if item, ok = s.Get(ctx, r); ok { - span.AddEvent("Check store for rate limit") - c.Add(item) - span.AddEvent("c.Add()") - } - } - - // Sanity checks. - if ok { - if item.Value == nil { - msgPart := "tokenBucket: Invalid cache item; Value is nil" - span.AddEvent(msgPart, trace.WithAttributes( - attribute.String("hashKey", hashKey), - attribute.String("key", r.UniqueKey), - attribute.String("name", r.Name), - )) - logrus.Error(msgPart) - ok = false - } else if item.Key != hashKey { - msgPart := "tokenBucket: Invalid cache item; key mismatch" - span.AddEvent(msgPart, trace.WithAttributes( - attribute.String("itemKey", item.Key), - attribute.String("hashKey", hashKey), - attribute.String("name", r.Name), - )) - logrus.Error(msgPart) - ok = false - } + // load value from cache or store + item, err := loadAndCheckBucket(ctx, s, c, r) + if err != nil { + // Item is not found in cache or store, create new. + return tokenBucketNewItem(ctx, s, c, r) } - if ok { - // Item found in cache or store. - span.AddEvent("Update existing rate limit") + // Item found in cache or store. + span.AddEvent("Check existing rate limit") - if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { - c.Remove(hashKey) - span.AddEvent("c.Remove()") + if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { + hashKey := r.HashKey() + c.Remove(hashKey) + span.AddEvent("c.Remove()") - if s != nil { - s.Remove(ctx, hashKey) - span.AddEvent("s.Remove()") - } - return &RateLimitResp{ - Status: Status_UNDER_LIMIT, - Limit: r.Limit, - Remaining: r.Limit, - ResetTime: 0, - }, nil + if s != nil { + s.Remove(ctx, hashKey) + span.AddEvent("s.Remove()") } + return &RateLimitResp{ + Status: Status_UNDER_LIMIT, + Limit: r.Limit, + Remaining: r.Limit, + ResetTime: 0, + }, nil + } - // The following semantic allows for requests of more than the limit to be rejected, but subsequent - // requests within the same duration that are under the limit to succeed. IE: client attempts to - // send 1000 emails but 100 is their limit. The request is rejected as over the limit, but since we - // don't store OVER_LIMIT in the cache the client can retry within the same rate limit duration with - // 100 emails and the request will succeed. - t, ok := item.Value.(*TokenBucketItem) - if !ok { - // Client switched algorithms; perhaps due to a migration? - span.AddEvent("Client switched algorithms; perhaps due to a migration?") - - c.Remove(hashKey) - span.AddEvent("c.Remove()") - - if s != nil { - s.Remove(ctx, hashKey) - span.AddEvent("s.Remove()") - } + // The following semantic allows for requests of more than the limit to be rejected, but subsequent + // requests within the same duration that are under the limit to succeed. IE: client attempts to + // send 1000 emails but 100 is their limit. The request is rejected as over the limit, but since we + // don't store OVER_LIMIT in the cache the client can retry within the same rate limit duration with + // 100 emails and the request will succeed. + t, ok := item.Value.(*TokenBucketItem) + if !ok { + // Client switched algorithms; perhaps due to a migration? + span.AddEvent("Client switched algorithms; perhaps due to a migration?") - return tokenBucketNewItem(ctx, s, c, r) - } + hashKey := r.HashKey() + c.Remove(hashKey) + span.AddEvent("c.Remove()") - // Update the limit if it changed. - span.AddEvent("Update the limit if changed") - if t.Limit != r.Limit { - // Add difference to remaining. - t.Remaining += r.Limit - t.Limit - if t.Remaining < 0 { - t.Remaining = 0 - } - t.Limit = r.Limit + if s != nil { + s.Remove(ctx, hashKey) + span.AddEvent("s.Remove()") } - rl := &RateLimitResp{ - Status: t.Status, - Limit: r.Limit, - Remaining: t.Remaining, - ResetTime: item.ExpireAt, + return tokenBucketNewItem(ctx, s, c, r) + } + + // Update the limit if it changed. + span.AddEvent("Update the limit if changed") + if t.Limit != r.Limit { + // Add difference to remaining. + t.Remaining += r.Limit - t.Limit + if t.Remaining < 0 { + t.Remaining = 0 } + t.Limit = r.Limit + } - // If the duration config changed, update the new ExpireAt. - if t.Duration != r.Duration { - span.AddEvent("Duration changed") - expire := t.CreatedAt + r.Duration - if HasBehavior(r.Behavior, Behavior_DURATION_IS_GREGORIAN) { - expire, err = GregorianExpiration(clock.Now(), r.Duration) - if err != nil { - return nil, err - } - } + rl := &RateLimitResp{ + Status: t.Status, + Limit: r.Limit, + Remaining: t.Remaining, + ResetTime: item.ExpireAt, + } - // If our new duration means we are currently expired. - now := MillisecondNow() - if expire <= now { - // Renew item. - span.AddEvent("Limit has expired") - expire = now + r.Duration - t.CreatedAt = now - t.Remaining = t.Limit + // If the duration config changed, update the new ExpireAt. + if t.Duration != r.Duration { + span.AddEvent("Duration changed") + expire := t.CreatedAt + r.Duration + if HasBehavior(r.Behavior, Behavior_DURATION_IS_GREGORIAN) { + expire, err = GregorianExpiration(clock.Now(), r.Duration) + if err != nil { + return nil, err } - - item.ExpireAt = expire - t.Duration = r.Duration - rl.ResetTime = expire } - if s != nil { - defer func() { - s.OnChange(ctx, r, item) - span.AddEvent("defer s.OnChange()") - }() + // If our new duration means we are currently expired. + now := MillisecondNow() + if expire <= now { + // Renew item. + span.AddEvent("Limit has expired") + expire = now + r.Duration + t.CreatedAt = now + t.Remaining = t.Limit } - // Client is only interested in retrieving the current status or - // updating the rate limit config. - if r.Hits == 0 { - span.AddEvent("Return current status, apply no change") - return rl, nil - } + item.ExpireAt = expire + t.Duration = r.Duration + rl.ResetTime = expire + } - // If we are already at the limit. - if rl.Remaining == 0 && r.Hits > 0 { - span.AddEvent("Already over the limit") - rl.Status = Status_OVER_LIMIT - t.Status = rl.Status - if !r.AtomicCheck { - overLimitCounter.Add(1) - } - return rl, nil + if s != nil { + defer func() { + s.OnChange(ctx, r, item) + span.AddEvent("defer s.OnChange()") + }() + } - } + // Client is only interested in retrieving the current status or + // updating the rate limit config. + if r.Hits == 0 { + span.AddEvent("Return current status, apply no change") + return rl, nil + } - // If requested hits takes the remainder. - if t.Remaining == r.Hits { - span.AddEvent("At the limit") - rl.Remaining = 0 - if !r.AtomicCheck { - t.Remaining = 0 - } - return rl, nil - } + // If we are already at the limit. + if rl.Remaining == 0 && r.Hits > 0 { + span.AddEvent("Already over the limit") + rl.Status = Status_OVER_LIMIT + t.Status = rl.Status + return rl, nil + } - // If requested is more than available, then return over the limit - // without updating the cache. - if r.Hits > t.Remaining { - span.AddEvent("Over the limit") - rl.Status = Status_OVER_LIMIT - if !r.AtomicCheck { - overLimitCounter.Add(1) - } - return rl, nil - } + // If requested hits takes the remainder. + if t.Remaining == r.Hits { + span.AddEvent("At the limit") + rl.Remaining = 0 + return rl, nil + } - span.AddEvent("Under the limit") - // if we are doing a check during atomic chaining then we only want - // to update the response and not the actual value for the rate limit - if r.AtomicCheck { - rl.Remaining = t.Remaining - r.Hits - } else { - t.Remaining -= r.Hits - rl.Remaining = t.Remaining - } + // If requested is more than available, then return over the limit + // without updating the cache. + if r.Hits > t.Remaining { + span.AddEvent("Over the limit") + rl.Status = Status_OVER_LIMIT return rl, nil } - // Item is not found in cache or store, create new. - return tokenBucketNewItem(ctx, s, c, r) + span.AddEvent("Under the limit") + rl.Remaining = t.Remaining - r.Hits + return rl, nil } // Called by tokenBucket() when adding a new item in the store. @@ -238,10 +188,9 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) t := &TokenBucketItem{ Limit: r.Limit, Duration: r.Duration, - Remaining: r.Limit - r.Hits, + Remaining: r.Limit, CreatedAt: now, } - item := &CacheItem{ Algorithm: Algorithm_TOKEN_BUCKET, Key: r.HashKey(), @@ -261,26 +210,16 @@ func tokenBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) rl := &RateLimitResp{ Status: Status_UNDER_LIMIT, Limit: r.Limit, - Remaining: t.Remaining, + Remaining: r.Limit - r.Hits, ResetTime: expire, } - // if we are doing a check during atomic chaining then remaining number is actually the limit - // but we should respond with what the value would be as if it had been applied - if r.AtomicCheck { - t.Remaining = r.Limit - rl.Remaining = r.Limit - r.Hits - } - // Client could be requesting that we always return OVER_LIMIT. - if r.Hits > r.Limit { span.AddEvent("Over the limit") - if !r.AtomicCheck { - overLimitCounter.Add(1) - t.Remaining = r.Limit - } rl.Status = Status_OVER_LIMIT + rl.Remaining = r.Limit + t.Remaining = r.Limit } c.Add(item) @@ -311,178 +250,129 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * now := MillisecondNow() - // Get rate limit from cache. - hashKey := r.HashKey() - item, ok := c.GetItem(hashKey) - span.AddEvent("c.GetItem()") - - if s != nil && !ok { - // Cache miss. - // Check our store for the item. - if item, ok = s.Get(ctx, r); ok { - span.AddEvent("Check store for rate limit") - c.Add(item) - span.AddEvent("c.Add()") - } - } - - // Sanity checks. - if ok { - if item.Value == nil { - msgPart := "leakyBucket: Invalid cache item; Value is nil" - span.AddEvent(msgPart, trace.WithAttributes( - attribute.String("hashKey", hashKey), - attribute.String("key", r.UniqueKey), - attribute.String("name", r.Name), - )) - logrus.Error(msgPart) - ok = false - } else if item.Key != hashKey { - msgPart := "leakyBucket: Invalid cache item; key mismatch" - span.AddEvent(msgPart, trace.WithAttributes( - attribute.String("itemKey", item.Key), - attribute.String("hashKey", hashKey), - attribute.String("name", r.Name), - )) - logrus.Error(msgPart) - ok = false - } + // load value from cache or store + item, err := loadAndCheckBucket(ctx, s, c, r) + if err != nil { + // Item is not found in cache or store, create new. + return leakyBucketNewItem(ctx, s, c, r) } - if ok { - // Item found in cache or store. - span.AddEvent("Update existing rate limit") + // Item found in cache or store. + span.AddEvent("Check existing rate limit") - b, ok := item.Value.(*LeakyBucketItem) - if !ok { - // Client switched algorithms; perhaps due to a migration? - c.Remove(hashKey) - span.AddEvent("c.Remove()") - - if s != nil { - s.Remove(ctx, hashKey) - span.AddEvent("s.Remove()") - } + b, ok := item.Value.(*LeakyBucketItem) + if !ok { + // Client switched algorithms; perhaps due to a migration? + hashKey := r.HashKey() + c.Remove(hashKey) + span.AddEvent("c.Remove()") - return leakyBucketNewItem(ctx, s, c, r) + if s != nil { + s.Remove(ctx, hashKey) + span.AddEvent("s.Remove()") } - if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { - b.Remaining = float64(r.Burst) - } + return leakyBucketNewItem(ctx, s, c, r) + } - // Update burst, limit and duration if they changed - if b.Burst != r.Burst { - if r.Burst > int64(b.Remaining) { - b.Remaining = float64(r.Burst) - } - b.Burst = r.Burst - } + if HasBehavior(r.Behavior, Behavior_RESET_REMAINING) { + b.Remaining = float64(r.Burst) + } - b.Limit = r.Limit - b.Duration = r.Duration + // Update burst, limit and duration if they changed + if b.Burst != r.Burst { + if r.Burst > int64(b.Remaining) { + b.Remaining = float64(r.Burst) + } + b.Burst = r.Burst + } - duration := r.Duration - rate := float64(duration) / float64(r.Limit) + b.Limit = r.Limit + b.Duration = r.Duration - if HasBehavior(r.Behavior, Behavior_DURATION_IS_GREGORIAN) { - d, err := GregorianDuration(clock.Now(), r.Duration) - if err != nil { - return nil, err - } - n := clock.Now() - expire, err := GregorianExpiration(n, r.Duration) - if err != nil { - return nil, err - } + duration := r.Duration + rate := float64(duration) / float64(r.Limit) - // Calculate the rate using the entire duration of the gregorian interval - // IE: Minute = 60,000 milliseconds, etc.. etc.. - rate = float64(d) / float64(r.Limit) - // Update the duration to be the end of the gregorian interval - duration = expire - (n.UnixNano() / 1000000) + if HasBehavior(r.Behavior, Behavior_DURATION_IS_GREGORIAN) { + d, err := GregorianDuration(clock.Now(), r.Duration) + if err != nil { + return nil, err } - - if r.Hits != 0 && !r.AtomicCheck { - c.UpdateExpiration(r.HashKey(), now+duration) + n := clock.Now() + expire, err := GregorianExpiration(n, r.Duration) + if err != nil { + return nil, err } - // Calculate how much leaked out of the bucket since the last time we leaked a hit - elapsed := now - b.UpdatedAt - leak := float64(elapsed) / rate - - if int64(leak) > 0 { - b.Remaining += leak - b.UpdatedAt = now - } + // Calculate the rate using the entire duration of the gregorian interval + // IE: Minute = 60,000 milliseconds, etc.. etc.. + rate = float64(d) / float64(r.Limit) + // Update the duration to be the end of the gregorian interval + duration = expire - (n.UnixNano() / 1000000) + } - if int64(b.Remaining) > b.Burst { - b.Remaining = float64(b.Burst) - } + if r.Hits != 0 { + c.UpdateExpiration(r.HashKey(), now+duration) + } - rl := &RateLimitResp{ - Limit: b.Limit, - Remaining: int64(b.Remaining), - Status: Status_UNDER_LIMIT, - ResetTime: now + (b.Limit-int64(b.Remaining))*int64(rate), - } + // Calculate how much leaked out of the bucket since the last time we leaked a hit + elapsed := now - b.UpdatedAt + leak := float64(elapsed) / rate - // TODO: Feature missing: check for Duration change between item/request. + if int64(leak) > 0 { + b.Remaining += leak + b.UpdatedAt = now + } - if s != nil { - defer func() { - s.OnChange(ctx, r, item) - span.AddEvent("s.OnChange()") - }() - } + if int64(b.Remaining) > b.Burst { + b.Remaining = float64(b.Burst) + } - // If we are already at the limit - if int64(b.Remaining) == 0 && r.Hits > 0 { - if !r.AtomicCheck { - overLimitCounter.Add(1) - } - rl.Status = Status_OVER_LIMIT - return rl, nil - } + rl := &RateLimitResp{ + Limit: b.Limit, + Remaining: int64(b.Remaining), + Status: Status_UNDER_LIMIT, + ResetTime: now + (b.Limit-int64(b.Remaining))*int64(rate), + } - // If requested hits takes the remainder - if int64(b.Remaining) == r.Hits { - if !r.AtomicCheck { - b.Remaining -= float64(r.Hits) - rl.ResetTime = now + (rl.Limit-int64(b.Remaining))*int64(rate) - } - rl.Remaining = 0 - return rl, nil - } + // TODO: Feature missing: check for Duration change between item/request. - // If requested is more than available, then return over the limit - // without updating the bucket. - if r.Hits > int64(b.Remaining) { - if !r.AtomicCheck { - overLimitCounter.Add(1) - } - rl.Status = Status_OVER_LIMIT - return rl, nil - } + if s != nil { + defer func() { + s.OnChange(ctx, r, item) + span.AddEvent("s.OnChange()") + }() + } - // Client is only interested in retrieving the current status - if r.Hits == 0 { - return rl, nil - } + // If we are already at the limit + if int64(b.Remaining) == 0 && r.Hits > 0 { + rl.Status = Status_OVER_LIMIT + return rl, nil + } - // if we are doing a check during atomic chaining then we only want - // to update the response and not the actual value for the rate limit - if r.AtomicCheck { - rl.Remaining = int64(b.Remaining - float64(r.Hits)) - } else { - b.Remaining -= float64(r.Hits) - rl.Remaining = int64(b.Remaining) - } + // If requested hits takes the remainder + if int64(b.Remaining) == r.Hits { + b.Remaining -= float64(r.Hits) + rl.Remaining = 0 rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) return rl, nil } - return leakyBucketNewItem(ctx, s, c, r) + // If requested is more than available, then return over the limit + // without updating the bucket. + if r.Hits > int64(b.Remaining) { + rl.Status = Status_OVER_LIMIT + return rl, nil + } + + // Client is only interested in retrieving the current status + if r.Hits == 0 { + return rl, nil + } + + rl.Remaining = int64(b.Remaining - float64(r.Hits)) + rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) + return rl, nil } // Called by leakyBucket() when adding a new item in the store. @@ -509,7 +399,7 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) // Create a new leaky bucket b := LeakyBucketItem{ - Remaining: float64(r.Burst - r.Hits), + Remaining: float64(r.Burst), Limit: r.Limit, Duration: duration, UpdatedAt: now, @@ -523,20 +413,10 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) ResetTime: now + (b.Limit-(r.Burst-r.Hits))*int64(rate), } - // if we are doing a check during atomic chaining then remaining number is actually the burst limit - // but we should respond with what the value would be as if it had been applied - if r.AtomicCheck { - b.Remaining = float64(r.Burst) - rl.Remaining = r.Burst - r.Hits - } - // Client could be requesting that we start with the bucket OVER_LIMIT if r.Hits > r.Burst { - if !r.AtomicCheck { - overLimitCounter.Add(1) - b.Remaining = 0 - } rl.Status = Status_OVER_LIMIT + rl.Remaining = 0 rl.ResetTime = now + (rl.Limit-rl.Remaining)*int64(rate) } @@ -557,3 +437,101 @@ func leakyBucketNewItem(ctx context.Context, s Store, c Cache, r *RateLimitReq) return &rl, nil } + +// bucket has been checked and response generated using the algorithms, persist the hits only +func persistBucketHits(ctx context.Context, s Store, c Cache, r *RateLimitReq, status int32) error { + var err error + ctx = tracing.StartScopeDebug(ctx) + defer func() { + tracing.EndScope(ctx, err) + }() + span := trace.SpanFromContext(ctx) + + // load value from cache or store + item, err := loadAndCheckBucket(ctx, s, c, r) + if err != nil { + return err + } + + span.AddEvent("Updating rate limit") + + // for leaky bucket we update remaining as it will need to be zero if over limit + if r.Algorithm == Algorithm_LEAKY_BUCKET { + b, ok := item.Value.(*LeakyBucketItem) + if ok { + // for leaky bucket the remaining will need to be zero as a minumum + b.Remaining -= float64(r.Hits) + if b.Remaining < 0 { + b.Remaining = 0 + } + } else { + return errors.New("unexpected cache value on update, expected LeakyBucketItem") + } + } + // handle over limit response, otherwise apply update if it is token bucket + if status == int32(Status_OVER_LIMIT) { + overLimitCounter.Add(1) + } else { + // handle a token bucket update + if r.Algorithm == Algorithm_TOKEN_BUCKET { + t, ok := item.Value.(*TokenBucketItem) + if ok { + t.Remaining -= r.Hits + } else { + return errors.New("unexpected cache value on update, expected TokenBucketItem") + } + } + } + return nil +} + +func loadAndCheckBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (*CacheItem, error) { + var err error + ctx = tracing.StartScopeDebug(ctx) + defer func() { + tracing.EndScope(ctx, err) + }() + span := trace.SpanFromContext(ctx) + + // read cache otherwise get from store + // Get rate limit from cache. + hashKey := r.HashKey() + item, ok := c.GetItem(hashKey) + span.AddEvent("c.GetItem()") + + if s != nil && !ok { + // Cache miss. + // Check our store for the item. + if item, ok = s.Get(ctx, r); ok { + span.AddEvent("Check store for rate limit") + c.Add(item) + span.AddEvent("c.Add()") + } + } + + // Sanity checks. + if ok { + if item.Value == nil { + msgPart := "Invalid cache item; Value is nil" + span.AddEvent(msgPart, trace.WithAttributes( + attribute.String("hashKey", hashKey), + attribute.String("key", r.UniqueKey), + attribute.String("name", r.Name), + )) + logrus.Error(msgPart) + return nil, errors.New("cache item integrity check failed") + } else if item.Key != hashKey { + msgPart := "Invalid cache item; key mismatch" + span.AddEvent(msgPart, trace.WithAttributes( + attribute.String("itemKey", item.Key), + attribute.String("hashKey", hashKey), + attribute.String("name", r.Name), + )) + logrus.Error(msgPart) + return nil, errors.New("cache item integrity check failed") + } + } else { + return nil, errors.New("no item in store") + } + return item, nil +} diff --git a/gubernator.go b/gubernator.go index 30bfca0c..0a950993 100644 --- a/gubernator.go +++ b/gubernator.go @@ -219,9 +219,8 @@ func (s *V1Instance) GetRateLimits(ctx context.Context, r *GetRateLimitsReq) (re Responses: make([]*RateLimitResp, len(r.Requests)), } - // get the UnionBehaviour - var atomicRequests = HasUnionBehavior(r.GetBehavior(), UnionBehavior_ATOMIC_REQUESTS) - if atomicRequests { + // perform a check first if the request is for union behaviour + if HasUnionBehavior(r.GetBehavior(), UnionBehavior_ATOMIC_REQUESTS) { // run with the atomic request check resp.Responses = s.checkLimits(ctx, span, r, &resp, true) // return without updating any actual limits if there is an error or anything over limit diff --git a/gubernator_pool.go b/gubernator_pool.go index 77d57ed9..750a094b 100644 --- a/gubernator_pool.go +++ b/gubernator_pool.go @@ -294,10 +294,14 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac var rlResponse *RateLimitResp var err error + shouldUpdate := true switch handlerRequest.request.Algorithm { case Algorithm_TOKEN_BUCKET: rlResponse, err = tokenBucket(ctx, chp.conf.Store, cache, handlerRequest.request) + if HasBehavior(handlerRequest.request.Behavior, Behavior_RESET_REMAINING) { + shouldUpdate = false + } if err != nil { msg := "Error in tokenBucket" countError(err, msg) @@ -320,6 +324,14 @@ func (chp *GubernatorPool) handleGetRateLimit(handlerRequest *request, cache Cac checkErrorCounter.WithLabelValues("Invalid algorithm").Add(1) } + // persist the hits to bucket if request is not a check only and it wasn't a token bucket reset + if !handlerRequest.request.AtomicCheck && shouldUpdate { + err = persistBucketHits(ctx, chp.conf.Store, cache, handlerRequest.request, int32(rlResponse.Status)) + if err != nil { + logrus.Error("failed to persist hits to bucket") + } + } + handlerResponse := &response{ rl: rlResponse, err: err, diff --git a/peer_client.go b/peer_client.go index e786b1c7..ac812ae6 100644 --- a/peer_client.go +++ b/peer_client.go @@ -71,10 +71,9 @@ type response struct { } type request struct { - request *RateLimitReq - resp chan *response - atomicCheck bool - ctx context.Context + request *RateLimitReq + resp chan *response + ctx context.Context } type PeerConfig struct { diff --git a/proto/gubernator.proto b/proto/gubernator.proto index 6428659d..ddc6badb 100644 --- a/proto/gubernator.proto +++ b/proto/gubernator.proto @@ -48,7 +48,6 @@ service V1 { message GetRateLimitsReq { repeated RateLimitReq requests = 1; UnionBehavior Behavior = 2; - } // RateLimits returned are in the same order as the Requests @@ -129,8 +128,6 @@ enum Behavior { // least 2 instances of Gubernator. MULTI_REGION = 16; - - // TODO: Add support for LOCAL. Which would force the rate limit to be handled by the local instance }