diff --git a/.gitignore b/.gitignore index 976cfb4f..1e85679c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,8 @@ .vscode/ __pycache__ *.pyc -gubernator.egg-info/ .DS_Store *.iml -googleapis/ coverage.out coverage.html /gubernator diff --git a/Makefile b/Makefile index f6f265ae..7c77cca8 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,8 @@ clean: .PHONY: proto proto: - scripts/proto.sh + # Install buf: https://buf.build/docs/installation + buf generate .PHONY: certs certs: diff --git a/README.md b/README.md index e60b5a9d..8c457727 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ rate_limits: limit: 100 # The duration of the rate limit in milliseconds duration: 1000 - # The algorithm used to calculate the rate limit + # The algorithm used to calculate the rate limit # 0 = Token Bucket # 1 = Leaky Bucket algorithm: 0 @@ -166,7 +166,7 @@ Given the following `Duration` values * 3 = Weeks * 4 = Months * 5 = Years - + Examples when using `Behavior = DURATION_IS_GREGORIAN` * If `Duration = 2` (Days) then the rate limit will reset to `Current = 0` at the end of the current day the rate limit was created. * If `Duration = 0` (Minutes) then the rate limit will reset to `Current = 0` at the end of the minute the rate limit was created. @@ -178,6 +178,31 @@ This will reset the rate limit as if created new on first use. When using Reset Remaining, the `Hits` field should be 0. +## Drain Over Limit Behavior +Users may add behavior `Behavior_DRAIN_OVER_LIMIT` to the rate check request. +A `GetRateLimits` call drains the remaining counter on first over limit event. +Then, successive `GetRateLimits` calls will return zero remaining counter and +not any residual value. This behavior works best with token bucket algorithm +because the `Remaining` counter will stay zero after an over limit until reset +time, whereas leaky bucket algorithm will immediately update `Remaining` to a +non-zero value. + +This facilitates scenarios that require an over limit event to stay over limit +until the rate limit resets. This approach is necessary if a process must make +two rate checks, before and after a process, and the `Hit` amount is not known +until after the process. + +- Before process: Call `GetRateLimits` with `Hits=0` to check the value of + `Remaining` counter. If `Remaining` is zero, it's known + that the rate limit is depleted and the process can be aborted. +- After process: Call `GetRateLimits` with a user specified `Hits` value. If + the call returns over limit, the process cannot be aborted because it had + already completed. Using `DRAIN_OVER_LIMIT` behavior, the `Remaining` count + will be drained to zero. + +Once an over limit occurs in the "After" step, successive processes will detect +the over limit state in the "Before" step. + ## Gubernator as a library If you are using golang, you can use Gubernator as a library. This is useful if you wish to implement a rate limit service with your own company specific model @@ -346,4 +371,4 @@ Gubernator publishes Prometheus metrics for realtime monitoring. See [prometheus.md](docs/prometheus.md) for details. ## OpenTelemetry Tracing (OTEL) -Gubernator supports OpenTelemetry. See [tracing.md](docs/tracing.md) for details. \ No newline at end of file +Gubernator supports OpenTelemetry. See [tracing.md](docs/tracing.md) for details. diff --git a/algorithms.go b/algorithms.go index c7e6315c..1fb8f9dd 100644 --- a/algorithms.go +++ b/algorithms.go @@ -181,6 +181,11 @@ func tokenBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * trace.SpanFromContext(ctx).AddEvent("Over the limit") metricOverLimitCounter.Add(1) rl.Status = Status_OVER_LIMIT + if HasBehavior(r.Behavior, Behavior_DRAIN_OVER_LIMIT) { + // DRAIN_OVER_LIMIT behavior drains the remaining counter. + t.Remaining = 0 + rl.Remaining = 0 + } return rl, nil } @@ -394,6 +399,11 @@ func leakyBucket(ctx context.Context, s Store, c Cache, r *RateLimitReq) (resp * if r.Hits > int64(b.Remaining) { metricOverLimitCounter.Add(1) rl.Status = Status_OVER_LIMIT + if HasBehavior(r.Behavior, Behavior_DRAIN_OVER_LIMIT) { + // DRAIN_OVER_LIMIT behavior drains the remaining counter. + b.Remaining = 0 + rl.Remaining = 0 + } return rl, nil } diff --git a/config.go b/config.go index c46e2fa3..14c9b592 100644 --- a/config.go +++ b/config.go @@ -62,7 +62,7 @@ type BehaviorConfig struct { GlobalTimeout time.Duration // The max number of global updates we can batch into a single peer request GlobalBatchLimit int - // ForceGlobal forces global mode on all rate limit checks. + // ForceGlobal forces global behavior on all rate limit checks. ForceGlobal bool // Number of concurrent requests that will be made to peers. Defaults to 100 diff --git a/contrib/charts/gubernator/Chart.yaml b/contrib/charts/gubernator/Chart.yaml index c1fbe823..27692748 100644 --- a/contrib/charts/gubernator/Chart.yaml +++ b/contrib/charts/gubernator/Chart.yaml @@ -4,6 +4,6 @@ description: A Helm Chart for gubernator type: application -version: 2.2.1 +version: 2.3.2 -appVersion: 2.2.1 +appVersion: 2.3.2 diff --git a/functional_test.go b/functional_test.go index 6225fc3e..4abd2e25 100644 --- a/functional_test.go +++ b/functional_test.go @@ -37,6 +37,14 @@ import ( json "google.golang.org/protobuf/encoding/protojson" ) +var algos = []struct { + Name string + Algorithm guber.Algorithm +}{ + {Name: "Token bucket", Algorithm: guber.Algorithm_TOKEN_BUCKET}, + {Name: "Leaky bucket", Algorithm: guber.Algorithm_LEAKY_BUCKET}, +} + // Setup and shutdown the mock gubernator cluster for the entire test suite func TestMain(m *testing.M) { if err := cluster.StartWith([]guber.PeerInfo{ @@ -363,6 +371,72 @@ func TestTokenBucketNegativeHits(t *testing.T) { } } +func TestDrainOverLimit(t *testing.T) { + defer clock.Freeze(clock.Now()).Unfreeze() + client, errs := guber.DialV1Server(cluster.PeerAt(0).GRPCAddress, nil) + require.Nil(t, errs) + + tests := []struct { + Name string + Hits int64 + Remaining int64 + Status guber.Status + }{ + { + Name: "check remaining before hit", + Hits: 0, + Remaining: 10, + Status: guber.Status_UNDER_LIMIT, + }, { + Name: "first hit", + Hits: 1, + Remaining: 9, + Status: guber.Status_UNDER_LIMIT, + }, { + Name: "over limit hit", + Hits: 100, + Remaining: 0, + Status: guber.Status_OVER_LIMIT, + }, { + Name: "check remaining", + Hits: 0, + Remaining: 0, + Status: guber.Status_UNDER_LIMIT, + }, + } + + for idx, algoCase := range algos { + t.Run(algoCase.Name, func(t *testing.T) { + for _, test := range tests { + ctx := context.Background() + t.Run(test.Name, func(t *testing.T) { + resp, err := client.GetRateLimits(ctx, &guber.GetRateLimitsReq{ + Requests: []*guber.RateLimitReq{ + { + Name: "test_drain_over_limit", + UniqueKey: fmt.Sprintf("account:1234:%d", idx), + Algorithm: algoCase.Algorithm, + Behavior: guber.Behavior_DRAIN_OVER_LIMIT, + Duration: guber.Second * 30, + Hits: test.Hits, + Limit: 10, + }, + }, + }) + require.NoError(t, err) + require.Len(t, resp.Responses, 1) + + rl := resp.Responses[0] + assert.Equal(t, test.Status, rl.Status) + assert.Equal(t, test.Remaining, rl.Remaining) + assert.Equal(t, int64(10), rl.Limit) + assert.NotZero(t, rl.ResetTime) + }) + } + }) + } +} + func TestLeakyBucket(t *testing.T) { defer clock.Freeze(clock.Now()).Unfreeze() diff --git a/go.mod b/go.mod index 0f5275c6..e32b4cd3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 github.com/hashicorp/memberlist v0.5.0 github.com/mailgun/errors v0.1.5 - github.com/mailgun/holster/v4 v4.16.2-0.20231121154636-69040cb71a3b + github.com/mailgun/holster/v4 v4.16.3 github.com/miekg/dns v1.1.50 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.13.0 @@ -26,7 +26,7 @@ require ( golang.org/x/time v0.3.0 google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 k8s.io/api v0.23.3 k8s.io/apimachinery v0.23.3 k8s.io/client-go v0.23.3 diff --git a/go.sum b/go.sum index 3ff2e93e..9b2e3287 100644 --- a/go.sum +++ b/go.sum @@ -291,8 +291,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailgun/errors v0.1.5 h1:riRpZqfUKTdc8saXvoEg2tYkbRyZESU1KvQ3UxPbdus= github.com/mailgun/errors v0.1.5/go.mod h1:lw+Nh4r/aoUTz6uK915FdfZJo3yq60gPiflFHNpK4NQ= -github.com/mailgun/holster/v4 v4.16.2-0.20231121154636-69040cb71a3b h1:ohMhrwmmA4JbXNukFpriztFWEVLlMuL90Cssg2Vl2TU= -github.com/mailgun/holster/v4 v4.16.2-0.20231121154636-69040cb71a3b/go.mod h1:phAg61z7LZ1PBfedyt2GXkGSlHhuVKK9AcVJO+Cm0/U= +github.com/mailgun/holster/v4 v4.16.3 h1:YMTkDoaFV83ViSaFuAfiyIvzrHJD1UNw7RjNv6J3Kfg= +github.com/mailgun/holster/v4 v4.16.3/go.mod h1:phAg61z7LZ1PBfedyt2GXkGSlHhuVKK9AcVJO+Cm0/U= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -839,8 +839,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/gubernator.pb.go b/gubernator.pb.go index 1e902315..1ae28afa 100644 --- a/gubernator.pb.go +++ b/gubernator.pb.go @@ -15,19 +15,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.7 +// protoc-gen-go v1.32.0 +// protoc (unknown) // source: gubernator.proto package gubernator import ( - reflect "reflect" - sync "sync" - _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( @@ -148,6 +147,10 @@ const ( // 'member-list' peer discovery. Also requires GUBER_DATA_CENTER to be set to different values on at // least 2 instances of Gubernator. Behavior_MULTI_REGION Behavior = 16 + // A GetRateLimits call drains the remaining counter on first over limit + // event. Then, successive GetRateLimits calls will return zero remaining + // counter and not any residual value. + Behavior_DRAIN_OVER_LIMIT Behavior = 32 ) // Enum value maps for Behavior. @@ -159,6 +162,7 @@ var ( 4: "DURATION_IS_GREGORIAN", 8: "RESET_REMAINING", 16: "MULTI_REGION", + 32: "DRAIN_OVER_LIMIT", } Behavior_value = map[string]int32{ "BATCHING": 0, @@ -167,6 +171,7 @@ var ( "DURATION_IS_GREGORIAN": 4, "RESET_REMAINING": 8, "MULTI_REGION": 16, + "DRAIN_OVER_LIMIT": 32, } ) @@ -734,34 +739,35 @@ var file_gubernator_proto_rawDesc = []byte{ 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, + 0x45, 0x54, 0x10, 0x01, 0x2a, 0x8d, 0x01, 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, 0x12, 0x14, + 0x0a, 0x10, 0x44, 0x52, 0x41, 0x49, 0x4e, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x4c, 0x49, 0x4d, + 0x49, 0x54, 0x10, 0x20, 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, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x47, 0x65, 0x74, 0x52, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 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.proto b/gubernator.proto index c8f237e8..5fd040df 100644 --- a/gubernator.proto +++ b/gubernator.proto @@ -34,7 +34,6 @@ service V1 { }; } - // This method is for round trip benchmarking and can be used by // the client to determine connectivity to the server rpc HealthCheck (HealthCheckReq) returns (HealthCheckResp) { @@ -127,6 +126,11 @@ enum Behavior { // least 2 instances of Gubernator. MULTI_REGION = 16; + // A GetRateLimits call drains the remaining counter on first over limit + // event. Then, successive GetRateLimits calls will return zero remaining + // counter and not any residual value. + DRAIN_OVER_LIMIT = 32; + // TODO: Add support for LOCAL. Which would force the rate limit to be handled by the local instance } diff --git a/gubernator_grpc.pb.go b/gubernator_grpc.pb.go index 20b4c442..209b75aa 100644 --- a/gubernator_grpc.pb.go +++ b/gubernator_grpc.pb.go @@ -16,14 +16,13 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v3.21.7 +// - protoc (unknown) // source: gubernator.proto package gubernator import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -77,7 +76,7 @@ func (c *v1Client) HealthCheck(ctx context.Context, in *HealthCheckReq, opts ... } // V1Server is the server API for V1 service. -// All implementations must embed UnimplementedV1Server +// All implementations should embed UnimplementedV1Server // for forward compatibility type V1Server interface { // Given a list of rate limit requests, return the rate limits of each. @@ -85,10 +84,9 @@ type V1Server interface { // This method is for round trip benchmarking and can be used by // the client to determine connectivity to the server HealthCheck(context.Context, *HealthCheckReq) (*HealthCheckResp, error) - mustEmbedUnimplementedV1Server() } -// UnimplementedV1Server must be embedded to have forward compatible implementations. +// UnimplementedV1Server should be embedded to have forward compatible implementations. type UnimplementedV1Server struct { } @@ -98,7 +96,6 @@ func (UnimplementedV1Server) GetRateLimits(context.Context, *GetRateLimitsReq) ( func (UnimplementedV1Server) HealthCheck(context.Context, *HealthCheckReq) (*HealthCheckResp, error) { return nil, status.Errorf(codes.Unimplemented, "method HealthCheck not implemented") } -func (UnimplementedV1Server) mustEmbedUnimplementedV1Server() {} // UnsafeV1Server may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to V1Server will diff --git a/peers.pb.go b/peers.pb.go index 597cd02a..a805b29a 100644 --- a/peers.pb.go +++ b/peers.pb.go @@ -15,18 +15,17 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.7 +// protoc-gen-go v1.32.0 +// protoc (unknown) // source: peers.proto package gubernator import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/peers_grpc.pb.go b/peers_grpc.pb.go index 355c43d6..33db74af 100644 --- a/peers_grpc.pb.go +++ b/peers_grpc.pb.go @@ -16,14 +16,13 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v3.21.7 +// - protoc (unknown) // source: peers.proto package gubernator import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -76,17 +75,16 @@ func (c *peersV1Client) UpdatePeerGlobals(ctx context.Context, in *UpdatePeerGlo } // PeersV1Server is the server API for PeersV1 service. -// All implementations must embed UnimplementedPeersV1Server +// All implementations should embed UnimplementedPeersV1Server // for forward compatibility type PeersV1Server interface { // Used by peers to relay batches of requests to an authoritative peer GetPeerRateLimits(context.Context, *GetPeerRateLimitsReq) (*GetPeerRateLimitsResp, error) // Used by peers send global rate limit updates to other peers UpdatePeerGlobals(context.Context, *UpdatePeerGlobalsReq) (*UpdatePeerGlobalsResp, error) - mustEmbedUnimplementedPeersV1Server() } -// UnimplementedPeersV1Server must be embedded to have forward compatible implementations. +// UnimplementedPeersV1Server should be embedded to have forward compatible implementations. type UnimplementedPeersV1Server struct { } @@ -96,7 +94,6 @@ func (UnimplementedPeersV1Server) GetPeerRateLimits(context.Context, *GetPeerRat func (UnimplementedPeersV1Server) UpdatePeerGlobals(context.Context, *UpdatePeerGlobalsReq) (*UpdatePeerGlobalsResp, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdatePeerGlobals not implemented") } -func (UnimplementedPeersV1Server) mustEmbedUnimplementedPeersV1Server() {} // UnsafePeersV1Server may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to PeersV1Server will diff --git a/python/gubernator/gubernator_pb2.py b/python/gubernator/gubernator_pb2.py index ed3b2695..cefa90ce 100644 --- a/python/gubernator/gubernator_pb2.py +++ b/python/gubernator/gubernator_pb2.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: gubernator.proto +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -14,44 +15,44 @@ 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\"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\"\xb4\x02\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;\n\x08metadata\x18\t \x03(\x0b\x32).pb.gubernator.RateLimitReq.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\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') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10gubernator.proto\x12\rpb.gubernator\x1a\x1cgoogle/api/annotations.proto\"K\n\x10GetRateLimitsReq\x12\x37\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReqR\x08requests\"O\n\x11GetRateLimitsResp\x12:\n\tresponses\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitRespR\tresponses\"\x8e\x03\n\x0cRateLimitReq\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\x1d\n\nunique_key\x18\x02 \x01(\tR\tuniqueKey\x12\x12\n\x04hits\x18\x03 \x01(\x03R\x04hits\x12\x14\n\x05limit\x18\x04 \x01(\x03R\x05limit\x12\x1a\n\x08\x64uration\x18\x05 \x01(\x03R\x08\x64uration\x12\x36\n\talgorithm\x18\x06 \x01(\x0e\x32\x18.pb.gubernator.AlgorithmR\talgorithm\x12\x33\n\x08\x62\x65havior\x18\x07 \x01(\x0e\x32\x17.pb.gubernator.BehaviorR\x08\x62\x65havior\x12\x14\n\x05\x62urst\x18\x08 \x01(\x03R\x05\x62urst\x12\x45\n\x08metadata\x18\t \x03(\x0b\x32).pb.gubernator.RateLimitReq.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xac\x02\n\rRateLimitResp\x12-\n\x06status\x18\x01 \x01(\x0e\x32\x15.pb.gubernator.StatusR\x06status\x12\x14\n\x05limit\x18\x02 \x01(\x03R\x05limit\x12\x1c\n\tremaining\x18\x03 \x01(\x03R\tremaining\x12\x1d\n\nreset_time\x18\x04 \x01(\x03R\tresetTime\x12\x14\n\x05\x65rror\x18\x05 \x01(\tR\x05\x65rror\x12\x46\n\x08metadata\x18\x06 \x03(\x0b\x32*.pb.gubernator.RateLimitResp.MetadataEntryR\x08metadata\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x10\n\x0eHealthCheckReq\"b\n\x0fHealthCheckResp\x12\x16\n\x06status\x18\x01 \x01(\tR\x06status\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\x12\x1d\n\npeer_count\x18\x03 \x01(\x05R\tpeerCount*/\n\tAlgorithm\x12\x10\n\x0cTOKEN_BUCKET\x10\x00\x12\x10\n\x0cLEAKY_BUCKET\x10\x01*\x8d\x01\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\x12\x14\n\x10\x44RAIN_OVER_LIMIT\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') -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'gubernator_pb2', globals()) +_globals = globals() +_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' - _RATELIMITREQ_METADATAENTRY._options = None - _RATELIMITREQ_METADATAENTRY._serialized_options = b'8\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=840 - _ALGORITHM._serialized_end=887 - _BEHAVIOR._serialized_start=889 - _BEHAVIOR._serialized_end=1008 - _STATUS._serialized_start=1010 - _STATUS._serialized_end=1051 - _GETRATELIMITSREQ._serialized_start=65 - _GETRATELIMITSREQ._serialized_end=130 - _GETRATELIMITSRESP._serialized_start=132 - _GETRATELIMITSRESP._serialized_end=200 - _RATELIMITREQ._serialized_start=203 - _RATELIMITREQ._serialized_end=511 - _RATELIMITREQ_METADATAENTRY._serialized_start=464 - _RATELIMITREQ_METADATAENTRY._serialized_end=511 - _RATELIMITRESP._serialized_start=514 - _RATELIMITRESP._serialized_end=748 - _RATELIMITRESP_METADATAENTRY._serialized_start=464 - _RATELIMITRESP_METADATAENTRY._serialized_end=511 - _HEALTHCHECKREQ._serialized_start=750 - _HEALTHCHECKREQ._serialized_end=766 - _HEALTHCHECKRESP._serialized_start=768 - _HEALTHCHECKRESP._serialized_end=838 - _V1._serialized_start=1054 - _V1._serialized_end=1275 + _globals['DESCRIPTOR']._options = None + _globals['DESCRIPTOR']._serialized_options = b'Z\035github.com/mailgun/gubernator\200\001\001' + _globals['_RATELIMITREQ_METADATAENTRY']._options = None + _globals['_RATELIMITREQ_METADATAENTRY']._serialized_options = b'8\001' + _globals['_RATELIMITRESP_METADATAENTRY']._options = None + _globals['_RATELIMITRESP_METADATAENTRY']._serialized_options = b'8\001' + _globals['_V1'].methods_by_name['GetRateLimits']._options = None + _globals['_V1'].methods_by_name['GetRateLimits']._serialized_options = b'\202\323\344\223\002\026\"\021/v1/GetRateLimits:\001*' + _globals['_V1'].methods_by_name['HealthCheck']._options = None + _globals['_V1'].methods_by_name['HealthCheck']._serialized_options = b'\202\323\344\223\002\021\022\017/v1/HealthCheck' + _globals['_ALGORITHM']._serialized_start=1045 + _globals['_ALGORITHM']._serialized_end=1092 + _globals['_BEHAVIOR']._serialized_start=1095 + _globals['_BEHAVIOR']._serialized_end=1236 + _globals['_STATUS']._serialized_start=1238 + _globals['_STATUS']._serialized_end=1279 + _globals['_GETRATELIMITSREQ']._serialized_start=65 + _globals['_GETRATELIMITSREQ']._serialized_end=140 + _globals['_GETRATELIMITSRESP']._serialized_start=142 + _globals['_GETRATELIMITSRESP']._serialized_end=221 + _globals['_RATELIMITREQ']._serialized_start=224 + _globals['_RATELIMITREQ']._serialized_end=622 + _globals['_RATELIMITREQ_METADATAENTRY']._serialized_start=563 + _globals['_RATELIMITREQ_METADATAENTRY']._serialized_end=622 + _globals['_RATELIMITRESP']._serialized_start=625 + _globals['_RATELIMITRESP']._serialized_end=925 + _globals['_RATELIMITRESP_METADATAENTRY']._serialized_start=563 + _globals['_RATELIMITRESP_METADATAENTRY']._serialized_end=622 + _globals['_HEALTHCHECKREQ']._serialized_start=927 + _globals['_HEALTHCHECKREQ']._serialized_end=943 + _globals['_HEALTHCHECKRESP']._serialized_start=945 + _globals['_HEALTHCHECKRESP']._serialized_end=1043 + _globals['_V1']._serialized_start=1282 + _globals['_V1']._serialized_end=1503 # @@protoc_insertion_point(module_scope) diff --git a/python/gubernator/peers_pb2.py b/python/gubernator/peers_pb2.py index 98ade704..53b40758 100644 --- a/python/gubernator/peers_pb2.py +++ b/python/gubernator/peers_pb2.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: peers.proto +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -14,24 +15,24 @@ import gubernator_pb2 as gubernator__pb2 -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') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bpeers.proto\x12\rpb.gubernator\x1a\x10gubernator.proto\"O\n\x14GetPeerRateLimitsReq\x12\x37\n\x08requests\x18\x01 \x03(\x0b\x32\x1b.pb.gubernator.RateLimitReqR\x08requests\"V\n\x15GetPeerRateLimitsResp\x12=\n\x0brate_limits\x18\x01 \x03(\x0b\x32\x1c.pb.gubernator.RateLimitRespR\nrateLimits\"Q\n\x14UpdatePeerGlobalsReq\x12\x39\n\x07globals\x18\x01 \x03(\x0b\x32\x1f.pb.gubernator.UpdatePeerGlobalR\x07globals\"\x92\x01\n\x10UpdatePeerGlobal\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x34\n\x06status\x18\x02 \x01(\x0b\x32\x1c.pb.gubernator.RateLimitRespR\x06status\x12\x36\n\talgorithm\x18\x03 \x01(\x0e\x32\x18.pb.gubernator.AlgorithmR\talgorithm\"\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()) +_globals = globals() +_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=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 + _globals['DESCRIPTOR']._options = None + _globals['DESCRIPTOR']._serialized_options = b'Z\035github.com/mailgun/gubernator\200\001\001' + _globals['_GETPEERRATELIMITSREQ']._serialized_start=48 + _globals['_GETPEERRATELIMITSREQ']._serialized_end=127 + _globals['_GETPEERRATELIMITSRESP']._serialized_start=129 + _globals['_GETPEERRATELIMITSRESP']._serialized_end=215 + _globals['_UPDATEPEERGLOBALSREQ']._serialized_start=217 + _globals['_UPDATEPEERGLOBALSREQ']._serialized_end=298 + _globals['_UPDATEPEERGLOBAL']._serialized_start=301 + _globals['_UPDATEPEERGLOBAL']._serialized_end=447 + _globals['_UPDATEPEERGLOBALSRESP']._serialized_start=449 + _globals['_UPDATEPEERGLOBALSRESP']._serialized_end=472 + _globals['_PEERSV1']._serialized_start=475 + _globals['_PEERSV1']._serialized_end=680 # @@protoc_insertion_point(module_scope) diff --git a/python/requirements-py2.txt b/python/requirements-py2.txt index 7beae473..bd761a72 100644 --- a/python/requirements-py2.txt +++ b/python/requirements-py2.txt @@ -4,7 +4,7 @@ enum34==1.1.6 funcsigs==1.0.2 futures==3.2.0 googleapis-common-protos==1.5.8 -grpcio==1.53.0 +grpcio==1.53.2 more-itertools==5.0.0 pathlib2==2.3.3 pluggy==0.8.1 diff --git a/python/requirements-py3.txt b/python/requirements-py3.txt index 03e84cbf..00d54ada 100644 --- a/python/requirements-py3.txt +++ b/python/requirements-py3.txt @@ -1,7 +1,7 @@ atomicwrites==1.3.0 attrs==18.2.0 googleapis-common-protos==1.5.8 -grpcio==1.53.0 +grpcio==1.53.2 grpcio-tools==1.19.0 more-itertools==6.0.0 pluggy==0.8.1 diff --git a/version b/version index 7fe52d36..f706a60d 100644 --- a/version +++ b/version @@ -1 +1 @@ -v2.2.1 +v2.3.2