diff --git a/Makefile b/Makefile index 83ee453023..04e143fae1 100644 --- a/Makefile +++ b/Makefile @@ -615,10 +615,10 @@ check-doc-validator: ## Check documentation using doc-validator tool .PHONY: reference-help reference-help: ## Generates the reference help documentation. -reference-help: cmd/mimir/mimir +reference-help: cmd/mimir/mimir tools/config-inspector/config-inspector @(./cmd/mimir/mimir -h || true) > cmd/mimir/help.txt.tmpl @(./cmd/mimir/mimir -help-all || true) > cmd/mimir/help-all.txt.tmpl - @(go run ./tools/config-inspector || true) > cmd/mimir/config-descriptor.json + @(./tools/config-inspector/config-inspector || true) > cmd/mimir/config-descriptor.json clean-white-noise: ## Clean the white noise in the markdown files. @find . -path ./.pkg -prune -o -path ./.cache -prune -o -path "*/vendor/*" -prune -or -type f -name "*.md" -print | \ diff --git a/pkg/api/api.go b/pkg/api/api.go index 8349897524..393e1eab32 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -6,7 +6,6 @@ package api import ( - "context" "flag" "net/http" "path" @@ -32,7 +31,6 @@ import ( frontendv2 "github.com/grafana/mimir/pkg/frontend/v2" "github.com/grafana/mimir/pkg/frontend/v2/frontendv2pb" "github.com/grafana/mimir/pkg/ingester/client" - "github.com/grafana/mimir/pkg/mimirpb" "github.com/grafana/mimir/pkg/querier" querierapi "github.com/grafana/mimir/pkg/querier/api" "github.com/grafana/mimir/pkg/querier/tenantfederation" @@ -281,7 +279,6 @@ type Ingester interface { ShutdownHandler(http.ResponseWriter, *http.Request) PrepareShutdownHandler(http.ResponseWriter, *http.Request) PreparePartitionDownscaleHandler(http.ResponseWriter, *http.Request) - PushWithCleanup(context.Context, *mimirpb.WriteRequest, func()) error UserRegistryHandler(http.ResponseWriter, *http.Request) TenantsHandler(http.ResponseWriter, *http.Request) TenantTSDBHandler(http.ResponseWriter, *http.Request) diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index 52d96b5db4..df0b866d0c 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -6293,9 +6293,10 @@ func newMockIngesterPusherAdapter(ingester *mockIngester) *mockIngesterPusherAda } } -// Push implements ingest.Pusher. -func (c *mockIngesterPusherAdapter) Push(ctx context.Context, req *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) { - return c.ingester.Push(ctx, req) +// PushToStorage implements ingest.Pusher. +func (c *mockIngesterPusherAdapter) PushToStorage(ctx context.Context, req *mimirpb.WriteRequest) error { + _, err := c.ingester.Push(ctx, req) + return err } // noopIngester is a mocked ingester which does nothing. diff --git a/pkg/ingester/errors.go b/pkg/ingester/errors.go index b4199bfb37..a9deccf785 100644 --- a/pkg/ingester/errors.go +++ b/pkg/ingester/errors.go @@ -28,11 +28,13 @@ import ( const ( integerUnavailableMsgFormat = "ingester is unavailable (current state: %s)" - tooBusyErrorMsg = "the ingester is currently too busy to process queries, try again later" + ingesterTooBusyMsg = "ingester is currently too busy to process queries, try again later" + ingesterPushGrpcDisabledMsg = "ingester is configured with Push gRPC method disabled" ) var ( - tooBusyError = ingesterTooBusyError{} + errTooBusy = ingesterTooBusyError{} + errPushGrpcDisabled = newErrorWithStatus(ingesterPushGrpcDisabledError{}, codes.Unimplemented) ) // errorWithStatus is used for wrapping errors returned by ingester. @@ -515,7 +517,7 @@ var _ ingesterError = tsdbUnavailableError{} type ingesterTooBusyError struct{} func (e ingesterTooBusyError) Error() string { - return tooBusyErrorMsg + return ingesterTooBusyMsg } func (e ingesterTooBusyError) errorCause() mimirpb.ErrorCause { @@ -525,6 +527,19 @@ func (e ingesterTooBusyError) errorCause() mimirpb.ErrorCause { // Ensure that ingesterTooBusyError is an ingesterError. var _ ingesterError = ingesterTooBusyError{} +type ingesterPushGrpcDisabledError struct{} + +func (e ingesterPushGrpcDisabledError) Error() string { + return ingesterPushGrpcDisabledMsg +} + +func (e ingesterPushGrpcDisabledError) errorCause() mimirpb.ErrorCause { + return mimirpb.METHOD_NOT_ALLOWED +} + +// Ensure that ingesterPushGrpcDisabledError is an ingesterError. +var _ ingesterError = ingesterPushGrpcDisabledError{} + type ingesterErrSamplers struct { sampleTimestampTooOld *log.Sampler sampleTimestampTooOldOOOEnabled *log.Sampler diff --git a/pkg/ingester/errors_test.go b/pkg/ingester/errors_test.go index 2d36e89c6e..339b559c51 100644 --- a/pkg/ingester/errors_test.go +++ b/pkg/ingester/errors_test.go @@ -235,12 +235,12 @@ func TestNewTSDBIngestExemplarErr(t *testing.T) { } func TestTooBusyError(t *testing.T) { - require.Error(t, tooBusyError) - require.Equal(t, "the ingester is currently too busy to process queries, try again later", tooBusyError.Error()) - checkIngesterError(t, tooBusyError, mimirpb.TOO_BUSY, false) + require.Error(t, errTooBusy) + require.Equal(t, "ingester is currently too busy to process queries, try again later", errTooBusy.Error()) + checkIngesterError(t, errTooBusy, mimirpb.TOO_BUSY, false) - wrappedErr := wrapOrAnnotateWithUser(tooBusyError, userID) - require.ErrorIs(t, wrappedErr, tooBusyError) + wrappedErr := wrapOrAnnotateWithUser(errTooBusy, userID) + require.ErrorIs(t, wrappedErr, errTooBusy) var anotherIngesterTooBusyErr ingesterTooBusyError require.ErrorAs(t, wrappedErr, &anotherIngesterTooBusyErr) checkIngesterError(t, wrappedErr, mimirpb.TOO_BUSY, false) @@ -731,16 +731,16 @@ func TestMapReadErrorToErrorWithStatus(t *testing.T) { expectedMessage: fmt.Sprintf("wrapped: %s", newUnavailableError(services.Stopping).Error()), expectedDetails: &mimirpb.ErrorDetails{Cause: mimirpb.SERVICE_UNAVAILABLE}, }, - "tooBusyError gets translated into an errorWithStatus ResourceExhausted error with details": { - err: tooBusyError, + "errTooBusy gets translated into an errorWithStatus ResourceExhausted error with details": { + err: errTooBusy, expectedCode: codes.ResourceExhausted, - expectedMessage: tooBusyErrorMsg, + expectedMessage: ingesterTooBusyMsg, expectedDetails: &mimirpb.ErrorDetails{Cause: mimirpb.TOO_BUSY}, }, - "a wrapped tooBusyError gets translated into an errorWithStatus ResourceExhausted error with details": { - err: fmt.Errorf("wrapped: %w", tooBusyError), + "a wrapped errTooBusy gets translated into an errorWithStatus ResourceExhausted error with details": { + err: fmt.Errorf("wrapped: %w", errTooBusy), expectedCode: codes.ResourceExhausted, - expectedMessage: fmt.Sprintf("wrapped: %s", tooBusyErrorMsg), + expectedMessage: fmt.Sprintf("wrapped: %s", ingesterTooBusyMsg), expectedDetails: &mimirpb.ErrorDetails{Cause: mimirpb.TOO_BUSY}, }, } @@ -776,13 +776,13 @@ func TestMapReadErrorToErrorWithHTTPOrGRPCStatus(t *testing.T) { err: fmt.Errorf("wrapped: %w", newUnavailableError(services.Stopping)), expectedTranslation: newErrorWithStatus(fmt.Errorf("wrapped: %w", newUnavailableError(services.Stopping)), codes.Unavailable), }, - "tooBusyError gets translated into an errorWithHTTPStatus with status code 503": { - err: tooBusyError, - expectedTranslation: newErrorWithHTTPStatus(tooBusyError, http.StatusServiceUnavailable), + "errTooBusy gets translated into an errorWithHTTPStatus with status code 503": { + err: errTooBusy, + expectedTranslation: newErrorWithHTTPStatus(errTooBusy, http.StatusServiceUnavailable), }, - "a wrapped tooBusyError gets translated into an errorWithStatus with status code 503": { - err: fmt.Errorf("wrapped: %w", tooBusyError), - expectedTranslation: newErrorWithHTTPStatus(fmt.Errorf("wrapped: %w", tooBusyError), http.StatusServiceUnavailable), + "a wrapped errTooBusy gets translated into an errorWithStatus with status code 503": { + err: fmt.Errorf("wrapped: %w", errTooBusy), + expectedTranslation: newErrorWithHTTPStatus(fmt.Errorf("wrapped: %w", errTooBusy), http.StatusServiceUnavailable), }, } for name, tc := range testCases { diff --git a/pkg/ingester/ingester.go b/pkg/ingester/ingester.go index 75f0573452..1c5033551e 100644 --- a/pkg/ingester/ingester.go +++ b/pkg/ingester/ingester.go @@ -206,6 +206,8 @@ type Config struct { UpdateIngesterOwnedSeries bool `yaml:"track_ingester_owned_series" category:"experimental"` OwnedSeriesUpdateInterval time.Duration `yaml:"owned_series_update_interval" category:"experimental"` + PushGrpcMethodEnabled bool `yaml:"push_grpc_method_enabled" category:"experimental" doc:"hidden"` + // This config is dynamically injected because defined outside the ingester config. IngestStorageConfig ingest.Config `yaml:"-"` } @@ -230,6 +232,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet, logger log.Logger) { f.BoolVar(&cfg.UseIngesterOwnedSeriesForLimits, "ingester.use-ingester-owned-series-for-limits", false, "When enabled, only series currently owned by ingester according to the ring are used when checking user per-tenant series limit.") f.BoolVar(&cfg.UpdateIngesterOwnedSeries, "ingester.track-ingester-owned-series", false, "This option enables tracking of ingester-owned series based on ring state, even if -ingester.use-ingester-owned-series-for-limits is disabled.") f.DurationVar(&cfg.OwnedSeriesUpdateInterval, "ingester.owned-series-update-interval", 15*time.Second, "How often to check for ring changes and possibly recompute owned series as a result of detected change.") + f.BoolVar(&cfg.PushGrpcMethodEnabled, "ingester.push-grpc-method-enabled", true, "Enables Push gRPC method on ingester. Can be only disabled when using ingest-storage to make sure ingesters only receive data from Kafka.") // The ingester.return-only-grpc-errors flag has been deprecated. // According to the migration plan (https://github.com/grafana/mimir/issues/6008#issuecomment-1854320098) @@ -3487,14 +3490,26 @@ func (i *Ingester) checkAvailable() error { return newUnavailableError(s) } -// Push implements client.IngesterServer -func (i *Ingester) Push(ctx context.Context, req *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) { +// PushToStorage implements ingest.Pusher interface for ingestion via ingest-storage. +func (i *Ingester) PushToStorage(ctx context.Context, req *mimirpb.WriteRequest) error { err := i.PushWithCleanup(ctx, req, func() { mimirpb.ReuseSlice(req.Timeseries) }) - if err == nil { - return &mimirpb.WriteResponse{}, nil + if err != nil { + return i.mapPushErrorToErrorWithStatus(err) + } + return nil +} + +// Push implements client.IngesterServer, which is registered into gRPC server. +func (i *Ingester) Push(ctx context.Context, req *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) { + if !i.cfg.PushGrpcMethodEnabled { + return nil, errPushGrpcDisabled + } + + err := i.PushToStorage(ctx, req) + if err != nil { + return nil, err } - handledErr := i.mapPushErrorToErrorWithStatus(err) - return nil, handledErr + return &mimirpb.WriteResponse{}, err } func (i *Ingester) mapPushErrorToErrorWithStatus(err error) error { @@ -3724,7 +3739,7 @@ func (i *Ingester) checkReadOverloaded() error { } i.metrics.utilizationLimitedRequests.WithLabelValues(reason).Inc() - return tooBusyError + return errTooBusy } type utilizationBasedLimiter interface { diff --git a/pkg/ingester/ingester_activity.go b/pkg/ingester/ingester_activity.go index ad60f12665..30b7d66ff9 100644 --- a/pkg/ingester/ingester_activity.go +++ b/pkg/ingester/ingester_activity.go @@ -35,11 +35,6 @@ func (i *ActivityTrackerWrapper) Push(ctx context.Context, request *mimirpb.Writ return i.ing.Push(ctx, request) } -func (i *ActivityTrackerWrapper) PushWithCleanup(ctx context.Context, r *mimirpb.WriteRequest, cleanUp func()) error { - // No tracking in PushWithCleanup - return i.ing.PushWithCleanup(ctx, r, cleanUp) -} - func (i *ActivityTrackerWrapper) QueryStream(request *client.QueryRequest, server client.Ingester_QueryStreamServer) error { ix := i.tracker.Insert(func() string { return requestActivity(server.Context(), "Ingester/QueryStream", request) diff --git a/pkg/ingester/ingester_ingest_storage_test.go b/pkg/ingester/ingester_ingest_storage_test.go index 56a211c45a..a7824fac49 100644 --- a/pkg/ingester/ingester_ingest_storage_test.go +++ b/pkg/ingester/ingester_ingest_storage_test.go @@ -381,6 +381,9 @@ func TestIngester_ShouldNotCreatePartitionIfThereIsShutdownMarker(t *testing.T) func createTestIngesterWithIngestStorage(t testing.TB, ingesterCfg *Config, overrides *validation.Overrides, reg prometheus.Registerer) (*Ingester, *kfake.Cluster, *ring.PartitionRingWatcher) { defaultIngesterConfig := defaultIngesterTestConfig(t) + // Always disable gRPC Push API when testing ingest store. + ingesterCfg.PushGrpcMethodEnabled = false + ingesterCfg.IngestStorageConfig.Enabled = true ingesterCfg.IngestStorageConfig.KafkaConfig.Topic = "mimir" ingesterCfg.IngestStorageConfig.KafkaConfig.LastProducedOffsetPollInterval = 100 * time.Millisecond diff --git a/pkg/ingester/ingester_test.go b/pkg/ingester/ingester_test.go index e95ac76d61..85e872be87 100644 --- a/pkg/ingester/ingester_test.go +++ b/pkg/ingester/ingester_test.go @@ -2537,7 +2537,7 @@ func Test_Ingester_LabelNames(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -2601,7 +2601,7 @@ func Test_Ingester_LabelValues(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -2802,7 +2802,7 @@ func TestIngester_LabelNamesAndValues(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -2922,7 +2922,7 @@ func TestIngester_LabelValuesCardinality(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -3414,7 +3414,7 @@ func Test_Ingester_MetricsForLabelMatchers(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -3812,7 +3812,7 @@ func TestIngester_QueryStream(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -4271,7 +4271,7 @@ func TestIngester_QueryExemplars(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -5606,7 +5606,7 @@ func Test_Ingester_UserStats(t *testing.T) { stat, ok := grpcutil.ErrorToStatus(err) require.True(t, ok) require.Equal(t, codes.ResourceExhausted, stat.Code()) - require.Equal(t, tooBusyErrorMsg, stat.Message()) + require.Equal(t, ingesterTooBusyMsg, stat.Message()) verifyUtilizationLimitedRequestsMetric(t, registry) }) } @@ -6748,6 +6748,31 @@ func TestIngester_PushInstanceLimitsWithCircuitBreaker_LimitInflightRequestsUsin } } +func TestIngester_PushGrpcMethod_Disabled(t *testing.T) { + cfg := defaultIngesterTestConfig(t) + cfg.PushGrpcMethodEnabled = false + + registry := prometheus.NewRegistry() + + i, err := prepareIngesterWithBlocksStorage(t, cfg, nil, registry) + require.NoError(t, err) + require.NoError(t, services.StartAndAwaitRunning(context.Background(), i)) + defer services.StopAndAwaitTerminated(context.Background(), i) //nolint:errcheck + + // Wait until the ingester is healthy + test.Poll(t, 100*time.Millisecond, 1, func() any { + return i.lifecycler.HealthyInstancesCount() + }) + + ctx := user.InjectOrgID(context.Background(), "test") + req := writeRequestSingleSeries( + labels.FromStrings(labels.MetricName, "foo", "l", "1"), + []mimirpb.Sample{{TimestampMs: 1_000, Value: 1}}, + ) + _, err = i.Push(ctx, req) + require.ErrorIs(t, err, errPushGrpcDisabled) +} + func TestIngester_instanceLimitsMetrics(t *testing.T) { reg := prometheus.NewRegistry() diff --git a/pkg/mimir/mimir.go b/pkg/mimir/mimir.go index eb34a409f7..bb7bd6965b 100644 --- a/pkg/mimir/mimir.go +++ b/pkg/mimir/mimir.go @@ -240,8 +240,13 @@ func (c *Config) Validate(log log.Logger) error { if err := c.IngestStorage.Validate(); err != nil { return errors.Wrap(err, "invalid ingest storage config") } - if c.isAnyModuleEnabled(Ingester, Write, All) && c.IngestStorage.Enabled && !c.Ingester.DeprecatedReturnOnlyGRPCErrors { - return errors.New("to use ingest storage (-ingest-storage.enabled) also enable -ingester.return-only-grpc-errors") + if c.isAnyModuleEnabled(Ingester, Write, All) { + if c.IngestStorage.Enabled && !c.Ingester.DeprecatedReturnOnlyGRPCErrors { + return errors.New("to use ingest storage (-ingest-storage.enabled) also enable -ingester.return-only-grpc-errors") + } + if !c.IngestStorage.Enabled && !c.Ingester.PushGrpcMethodEnabled { + return errors.New("cannot disable Push gRPC method in ingester, while ingest storage (-ingest-storage.enabled) is not enabled") + } } if err := c.BlocksStorage.Validate(c.Ingester.ActiveSeriesMetrics); err != nil { return errors.Wrap(err, "invalid TSDB config") diff --git a/pkg/mimir/mimir_test.go b/pkg/mimir/mimir_test.go index 92ce55f8a2..7ff85d2c99 100644 --- a/pkg/mimir/mimir_test.go +++ b/pkg/mimir/mimir_test.go @@ -448,6 +448,18 @@ func TestConfigValidation(t *testing.T) { }, expectAnyError: true, }, + { + name: "should fails if push api disabled in ingester, and the ingester isn't running with ingest storage", + getTestConfig: func() *Config { + cfg := newDefaultConfig() + _ = cfg.Target.Set("ingester") + cfg.Ingester.PushGrpcMethodEnabled = false + cfg.IngestStorage.Enabled = false + + return cfg + }, + expectAnyError: true, + }, } { t.Run(tc.name, func(t *testing.T) { err := tc.getTestConfig().Validate(log.NewNopLogger()) diff --git a/pkg/mimirpb/mimir.pb.go b/pkg/mimirpb/mimir.pb.go index be4b6b9678..6955ecd4c9 100644 --- a/pkg/mimirpb/mimir.pb.go +++ b/pkg/mimirpb/mimir.pb.go @@ -43,6 +43,7 @@ const ( TSDB_UNAVAILABLE ErrorCause = 8 TOO_BUSY ErrorCause = 9 CIRCUIT_BREAKER_OPEN ErrorCause = 10 + METHOD_NOT_ALLOWED ErrorCause = 11 ) var ErrorCause_name = map[int32]string{ @@ -57,6 +58,7 @@ var ErrorCause_name = map[int32]string{ 8: "TSDB_UNAVAILABLE", 9: "TOO_BUSY", 10: "CIRCUIT_BREAKER_OPEN", + 11: "METHOD_NOT_ALLOWED", } var ErrorCause_value = map[string]int32{ @@ -71,6 +73,7 @@ var ErrorCause_value = map[string]int32{ "TSDB_UNAVAILABLE": 8, "TOO_BUSY": 9, "CIRCUIT_BREAKER_OPEN": 10, + "METHOD_NOT_ALLOWED": 11, } func (ErrorCause) EnumDescriptor() ([]byte, []int) { @@ -1888,130 +1891,131 @@ func init() { func init() { proto.RegisterFile("mimir.proto", fileDescriptor_86d4d7485f544059) } var fileDescriptor_86d4d7485f544059 = []byte{ - // 1959 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcf, 0x73, 0xdc, 0x48, - 0xf5, 0x1f, 0xcd, 0x68, 0x7e, 0xe8, 0x79, 0xc6, 0xee, 0x74, 0xfc, 0xcd, 0xce, 0xba, 0x36, 0x63, - 0x47, 0xdf, 0x62, 0x31, 0x29, 0x70, 0xa8, 0x5d, 0xc8, 0xd6, 0xa6, 0x42, 0x81, 0x66, 0x46, 0x89, - 0xc7, 0xf1, 0x68, 0xbc, 0x2d, 0x4d, 0x96, 0x70, 0x51, 0xc9, 0xe3, 0xb6, 0xad, 0x5a, 0x69, 0x34, - 0x48, 0x9a, 0x6c, 0xcc, 0x09, 0x0e, 0x50, 0x14, 0x27, 0x2e, 0x5c, 0x28, 0x6e, 0x5c, 0xf8, 0x0b, - 0xf8, 0x07, 0xb8, 0xa4, 0x8a, 0xa2, 0x2a, 0xc7, 0x2d, 0x0e, 0x29, 0xe2, 0x5c, 0xf6, 0xb8, 0x07, - 0x4e, 0x9c, 0xa8, 0xee, 0xd6, 0x8f, 0xd1, 0xd8, 0x86, 0x00, 0xb9, 0xe9, 0xbd, 0xf7, 0xe9, 0xa7, - 0x8f, 0x5e, 0x7f, 0x5e, 0xeb, 0x49, 0xb0, 0xe2, 0xbb, 0xbe, 0x1b, 0xee, 0xcc, 0xc2, 0x20, 0x0e, - 0x70, 0x63, 0x12, 0x84, 0x31, 0x7d, 0x36, 0x3b, 0xdc, 0xf8, 0xd6, 0x89, 0x1b, 0x9f, 0xce, 0x0f, - 0x77, 0x26, 0x81, 0x7f, 0xe7, 0x24, 0x38, 0x09, 0xee, 0x70, 0xc0, 0xe1, 0xfc, 0x98, 0x5b, 0xdc, - 0xe0, 0x57, 0x62, 0xa1, 0xfa, 0xc7, 0x32, 0x34, 0x3f, 0x0d, 0xdd, 0x98, 0x12, 0xfa, 0xe3, 0x39, - 0x8d, 0x62, 0x7c, 0x00, 0x10, 0xbb, 0x3e, 0x8d, 0x68, 0xe8, 0xd2, 0xa8, 0x2d, 0x6d, 0x55, 0xb6, - 0x57, 0x3e, 0x58, 0xdf, 0x49, 0xd3, 0xef, 0x58, 0xae, 0x4f, 0x4d, 0x1e, 0xeb, 0x6e, 0x3c, 0x7f, - 0xb9, 0x59, 0xfa, 0xeb, 0xcb, 0x4d, 0x7c, 0x10, 0x52, 0xc7, 0xf3, 0x82, 0x89, 0x95, 0xad, 0x23, - 0x0b, 0x39, 0xf0, 0xc7, 0x50, 0x33, 0x83, 0x79, 0x38, 0xa1, 0xed, 0xf2, 0x96, 0xb4, 0xbd, 0xfa, - 0xc1, 0xad, 0x3c, 0xdb, 0xe2, 0x9d, 0x77, 0x04, 0x48, 0x9f, 0xce, 0x7d, 0x92, 0x2c, 0xc0, 0xf7, - 0xa0, 0xe1, 0xd3, 0xd8, 0x39, 0x72, 0x62, 0xa7, 0x5d, 0xe1, 0x54, 0xda, 0xf9, 0xe2, 0x21, 0x8d, - 0x43, 0x77, 0x32, 0x4c, 0xe2, 0x5d, 0xf9, 0xf9, 0xcb, 0x4d, 0x89, 0x64, 0x78, 0x7c, 0x1f, 0x36, - 0xa2, 0xcf, 0xdc, 0x99, 0xed, 0x39, 0x87, 0xd4, 0xb3, 0xa7, 0x8e, 0x4f, 0xed, 0xa7, 0x8e, 0xe7, - 0x1e, 0x39, 0xb1, 0x1b, 0x4c, 0xdb, 0x5f, 0xd6, 0xb7, 0xa4, 0xed, 0x06, 0x79, 0x87, 0x41, 0xf6, - 0x19, 0xc2, 0x70, 0x7c, 0xfa, 0x38, 0x8b, 0xab, 0x9b, 0x00, 0x39, 0x1f, 0x5c, 0x87, 0x8a, 0x76, - 0x30, 0x40, 0x25, 0xdc, 0x00, 0x99, 0x8c, 0xf7, 0x75, 0x24, 0xa9, 0x6b, 0xd0, 0x4a, 0xd8, 0x47, - 0xb3, 0x60, 0x1a, 0x51, 0xf5, 0x1e, 0x34, 0xf5, 0x30, 0x0c, 0xc2, 0x3e, 0x8d, 0x1d, 0xd7, 0x8b, - 0xf0, 0x6d, 0xa8, 0xf6, 0x9c, 0x79, 0x44, 0xdb, 0x12, 0x7f, 0xea, 0x85, 0x1a, 0x72, 0x18, 0x8f, - 0x11, 0x01, 0x51, 0xff, 0x2e, 0x01, 0xe4, 0x95, 0xc5, 0x1a, 0xd4, 0x38, 0xeb, 0xb4, 0xfe, 0xd7, - 0xf3, 0xb5, 0x9c, 0xeb, 0x81, 0xe3, 0x86, 0xdd, 0xf5, 0xa4, 0xfc, 0x4d, 0xee, 0xd2, 0x8e, 0x9c, - 0x59, 0x4c, 0x43, 0x92, 0x2c, 0xc4, 0xdf, 0x86, 0x7a, 0xe4, 0xf8, 0x33, 0x8f, 0x46, 0xed, 0x32, - 0xcf, 0x81, 0xf2, 0x1c, 0x26, 0x0f, 0xf0, 0x82, 0x95, 0x48, 0x0a, 0xc3, 0x77, 0x41, 0xa1, 0xcf, - 0xa8, 0x3f, 0xf3, 0x9c, 0x30, 0x4a, 0x8a, 0x8d, 0x17, 0x38, 0x27, 0xa1, 0x64, 0x55, 0x0e, 0xc5, - 0x1f, 0x03, 0x9c, 0xba, 0x51, 0x1c, 0x9c, 0x84, 0x8e, 0x1f, 0xb5, 0xe5, 0x65, 0xc2, 0xbb, 0x69, - 0x2c, 0x59, 0xb9, 0x00, 0x56, 0xbf, 0x0b, 0x4a, 0xf6, 0x3c, 0x18, 0x83, 0xcc, 0x36, 0x89, 0x97, - 0xab, 0x49, 0xf8, 0x35, 0x5e, 0x87, 0xea, 0x53, 0xc7, 0x9b, 0x0b, 0xe5, 0x34, 0x89, 0x30, 0x54, - 0x0d, 0x6a, 0xe2, 0x11, 0xf0, 0x2d, 0x68, 0x72, 0xa1, 0xc5, 0x8e, 0x3f, 0xb3, 0xfd, 0x88, 0xc3, - 0x2a, 0x64, 0x25, 0xf3, 0x0d, 0xa3, 0x3c, 0x05, 0xcb, 0x2b, 0xa5, 0x29, 0x7e, 0x5b, 0x86, 0xd5, - 0xa2, 0x7e, 0xf0, 0x47, 0x20, 0xc7, 0x67, 0xb3, 0x74, 0xbb, 0xfe, 0xff, 0x2a, 0x9d, 0x25, 0xa6, - 0x75, 0x36, 0xa3, 0x84, 0x2f, 0xc0, 0xdf, 0x04, 0xec, 0x73, 0x9f, 0x7d, 0xec, 0xf8, 0xae, 0x77, - 0xc6, 0xb5, 0xc6, 0xa9, 0x28, 0x04, 0x89, 0xc8, 0x03, 0x1e, 0x60, 0x12, 0x63, 0x8f, 0x79, 0x4a, - 0xbd, 0x59, 0x5b, 0xe6, 0x71, 0x7e, 0xcd, 0x7c, 0xf3, 0xa9, 0x1b, 0xb7, 0xab, 0xc2, 0xc7, 0xae, - 0xd5, 0x33, 0x80, 0xfc, 0x4e, 0x78, 0x05, 0xea, 0x63, 0xe3, 0x91, 0x31, 0xfa, 0xd4, 0x40, 0x25, - 0x66, 0xf4, 0x46, 0x63, 0xc3, 0xd2, 0x09, 0x92, 0xb0, 0x02, 0xd5, 0x87, 0xda, 0xf8, 0xa1, 0x8e, - 0xca, 0xb8, 0x05, 0xca, 0xee, 0xc0, 0xb4, 0x46, 0x0f, 0x89, 0x36, 0x44, 0x15, 0x8c, 0x61, 0x95, - 0x47, 0x72, 0x9f, 0xcc, 0x96, 0x9a, 0xe3, 0xe1, 0x50, 0x23, 0x4f, 0x50, 0x95, 0x89, 0x79, 0x60, - 0x3c, 0x18, 0xa1, 0x1a, 0x6e, 0x42, 0xc3, 0xb4, 0x34, 0x4b, 0x37, 0x75, 0x0b, 0xd5, 0xd5, 0x47, - 0x50, 0x13, 0xb7, 0x7e, 0x0b, 0x42, 0x54, 0x7f, 0x21, 0x41, 0x23, 0x15, 0xcf, 0xdb, 0x10, 0x76, - 0x41, 0x12, 0xe9, 0x7e, 0x5e, 0x10, 0x42, 0xe5, 0x82, 0x10, 0xd4, 0x3f, 0x57, 0x41, 0xc9, 0xc4, - 0x88, 0x6f, 0x82, 0x32, 0x09, 0xe6, 0xd3, 0xd8, 0x76, 0xa7, 0x31, 0xdf, 0x72, 0x79, 0xb7, 0x44, - 0x1a, 0xdc, 0x35, 0x98, 0xc6, 0xf8, 0x16, 0xac, 0x88, 0xf0, 0xb1, 0x17, 0x38, 0xb1, 0xb8, 0xd7, - 0x6e, 0x89, 0x00, 0x77, 0x3e, 0x60, 0x3e, 0x8c, 0xa0, 0x12, 0xcd, 0x7d, 0x7e, 0x27, 0x89, 0xb0, - 0x4b, 0x7c, 0x03, 0x6a, 0xd1, 0xe4, 0x94, 0xfa, 0x0e, 0xdf, 0xdc, 0x6b, 0x24, 0xb1, 0xf0, 0xd7, - 0x60, 0xf5, 0x27, 0x34, 0x0c, 0xec, 0xf8, 0x34, 0xa4, 0xd1, 0x69, 0xe0, 0x1d, 0xf1, 0x8d, 0x96, - 0x48, 0x8b, 0x79, 0xad, 0xd4, 0x89, 0xdf, 0x4f, 0x60, 0x39, 0xaf, 0x1a, 0xe7, 0x25, 0x91, 0x26, - 0xf3, 0xf7, 0x52, 0x6e, 0xb7, 0x01, 0x2d, 0xe0, 0x04, 0xc1, 0x3a, 0x27, 0x28, 0x91, 0xd5, 0x0c, - 0x29, 0x48, 0x6a, 0xb0, 0x3a, 0xa5, 0x27, 0x4e, 0xec, 0x3e, 0xa5, 0x76, 0x34, 0x73, 0xa6, 0x51, - 0xbb, 0xb1, 0x7c, 0xa2, 0x77, 0xe7, 0x93, 0xcf, 0x68, 0x6c, 0xce, 0x9c, 0x69, 0xd2, 0xa1, 0xad, - 0x74, 0x05, 0xf3, 0x45, 0xf8, 0xeb, 0xb0, 0x96, 0xa5, 0x38, 0xa2, 0x5e, 0xec, 0x44, 0x6d, 0x65, - 0xab, 0xb2, 0x8d, 0x49, 0x96, 0xb9, 0xcf, 0xbd, 0x05, 0x20, 0xe7, 0x16, 0xb5, 0x61, 0xab, 0xb2, - 0x2d, 0xe5, 0x40, 0x4e, 0x8c, 0x1d, 0x6f, 0xab, 0xb3, 0x20, 0x72, 0x17, 0x48, 0xad, 0xfc, 0x7b, - 0x52, 0xe9, 0x8a, 0x8c, 0x54, 0x96, 0x22, 0x21, 0xd5, 0x14, 0xa4, 0x52, 0x77, 0x4e, 0x2a, 0x03, - 0x26, 0xa4, 0x5a, 0x82, 0x54, 0xea, 0x4e, 0x48, 0xdd, 0x07, 0x08, 0x69, 0x44, 0x63, 0xfb, 0x94, - 0x55, 0x7e, 0x95, 0x1f, 0x02, 0x37, 0x2f, 0x39, 0xc6, 0x76, 0x08, 0x43, 0xed, 0xba, 0xd3, 0x98, - 0x28, 0x61, 0x7a, 0x89, 0xdf, 0x03, 0x25, 0xd3, 0x5a, 0x7b, 0x8d, 0x8b, 0x2f, 0x77, 0xa8, 0xf7, - 0x40, 0xc9, 0x56, 0x15, 0x5b, 0xb9, 0x0e, 0x95, 0x27, 0xba, 0x89, 0x24, 0x5c, 0x83, 0xb2, 0x31, - 0x42, 0xe5, 0xbc, 0x9d, 0x2b, 0x1b, 0xf2, 0x2f, 0x7f, 0xdf, 0x91, 0xba, 0x75, 0xa8, 0x72, 0xde, - 0xdd, 0x26, 0x40, 0xbe, 0xed, 0xea, 0x5f, 0x64, 0x58, 0xe5, 0x5b, 0x9c, 0x4b, 0x3a, 0x02, 0xcc, - 0x63, 0x34, 0xb4, 0x97, 0x9e, 0xa4, 0xd5, 0xd5, 0xff, 0xf1, 0x72, 0x53, 0x5b, 0x98, 0x0c, 0x66, - 0x61, 0xe0, 0xd3, 0xf8, 0x94, 0xce, 0xa3, 0xc5, 0x4b, 0x3f, 0x38, 0xa2, 0xde, 0x9d, 0xec, 0x80, - 0xde, 0xe9, 0x89, 0x74, 0xf9, 0x13, 0xa3, 0xc9, 0x92, 0xe7, 0x7f, 0xd5, 0xfc, 0xcd, 0xc5, 0x87, - 0x12, 0x2a, 0x26, 0x4a, 0xa6, 0x61, 0xd6, 0xec, 0x22, 0x92, 0x34, 0x3b, 0x37, 0x2e, 0xe9, 0xbc, - 0xb7, 0xa0, 0xa8, 0xb7, 0xd0, 0x29, 0xdf, 0x00, 0x94, 0xb1, 0x38, 0xe4, 0xd8, 0x54, 0x6c, 0x99, - 0x06, 0x45, 0x0a, 0x0e, 0xcd, 0xee, 0x96, 0x42, 0x45, 0xb3, 0x64, 0x3d, 0x94, 0x40, 0xf7, 0xe4, - 0x86, 0x84, 0xca, 0x7b, 0x72, 0xa3, 0x86, 0xea, 0x7b, 0x72, 0x43, 0x41, 0xb0, 0x27, 0x37, 0x9a, - 0xa8, 0xb5, 0x27, 0x37, 0xd6, 0x10, 0x22, 0xf9, 0x29, 0x46, 0x96, 0x4e, 0x0f, 0xb2, 0xdc, 0xb6, - 0x64, 0xb9, 0x65, 0x16, 0x25, 0x7a, 0x1f, 0x20, 0x7f, 0x3c, 0xb6, 0xab, 0xc1, 0xf1, 0x71, 0x44, - 0xc5, 0xd1, 0x78, 0x8d, 0x24, 0x16, 0xf3, 0x7b, 0x74, 0x7a, 0x12, 0x9f, 0xf2, 0x0d, 0x69, 0x91, - 0xc4, 0x52, 0xe7, 0x80, 0x8b, 0x62, 0xe4, 0x6f, 0xf4, 0x37, 0x78, 0x3b, 0xdf, 0x07, 0x25, 0x93, - 0x1b, 0xbf, 0x57, 0x61, 0xc2, 0x2b, 0xe6, 0x4c, 0x26, 0xbc, 0x7c, 0x81, 0x3a, 0x85, 0x35, 0x31, - 0x08, 0xe4, 0x4d, 0x90, 0x29, 0x46, 0xba, 0x44, 0x31, 0xe5, 0x5c, 0x31, 0x1f, 0x42, 0x3d, 0xad, - 0xbb, 0x98, 0x75, 0xde, 0xbd, 0x6c, 0x64, 0xe1, 0x08, 0x92, 0x22, 0xd5, 0x08, 0xd6, 0x96, 0x62, - 0xb8, 0x03, 0x70, 0x18, 0xcc, 0xa7, 0x47, 0x4e, 0x32, 0x2e, 0x4b, 0xdb, 0x55, 0xb2, 0xe0, 0x61, - 0x7c, 0xbc, 0xe0, 0x73, 0x1a, 0xa6, 0x0a, 0xe6, 0x06, 0xf3, 0xce, 0x67, 0x33, 0x1a, 0x26, 0x1a, - 0x16, 0x46, 0xce, 0x5d, 0x5e, 0xe0, 0xae, 0x7a, 0x70, 0x7d, 0xe9, 0x21, 0x79, 0x71, 0x0b, 0x27, - 0x4e, 0x79, 0xe9, 0xc4, 0xc1, 0x1f, 0x5d, 0xac, 0xeb, 0xbb, 0xcb, 0x03, 0x60, 0x96, 0x6f, 0xb1, - 0xa4, 0x7f, 0x92, 0xa1, 0xf5, 0xc9, 0x9c, 0x86, 0x67, 0xe9, 0x5c, 0x8b, 0xef, 0x42, 0x2d, 0x8a, - 0x9d, 0x78, 0x1e, 0x25, 0x93, 0x51, 0x27, 0xcf, 0x53, 0x00, 0xee, 0x98, 0x1c, 0x45, 0x12, 0x34, - 0xfe, 0x01, 0x00, 0x65, 0x83, 0xae, 0xcd, 0xa7, 0xaa, 0x0b, 0xa3, 0x7f, 0x71, 0x2d, 0x1f, 0x89, - 0xf9, 0x4c, 0xa5, 0xd0, 0xf4, 0x92, 0xd5, 0x83, 0x1b, 0xbc, 0x4a, 0x0a, 0x11, 0x06, 0xde, 0x61, - 0x7c, 0x42, 0x77, 0x7a, 0xc2, 0xcb, 0x54, 0x68, 0x50, 0x93, 0xfb, 0xfb, 0x4e, 0xec, 0xec, 0x96, - 0x48, 0x82, 0x62, 0xf8, 0xa7, 0x74, 0x12, 0x07, 0x21, 0x3f, 0x81, 0x0a, 0xf8, 0xc7, 0xdc, 0x9f, - 0xe2, 0x05, 0x8a, 0xe7, 0x9f, 0x38, 0x9e, 0x13, 0xf2, 0xd7, 0x6f, 0x31, 0x3f, 0xf7, 0x67, 0xf9, - 0xb9, 0xc5, 0xf0, 0xbe, 0x13, 0x87, 0xee, 0x33, 0x7e, 0x7c, 0x15, 0xf0, 0x43, 0xee, 0x4f, 0xf1, - 0x02, 0x85, 0x37, 0xa0, 0xf1, 0xb9, 0x13, 0x4e, 0xdd, 0xe9, 0x89, 0x38, 0x62, 0x14, 0x92, 0xd9, - 0xea, 0xfb, 0x50, 0x13, 0x55, 0x64, 0xef, 0x01, 0x9d, 0x90, 0x11, 0x11, 0xe3, 0x9e, 0x39, 0xee, - 0xf5, 0x74, 0xd3, 0x44, 0x92, 0x78, 0x29, 0xa8, 0xbf, 0x91, 0x40, 0xc9, 0x4a, 0xc6, 0xe6, 0x38, - 0x63, 0x64, 0xe8, 0x02, 0x6a, 0x0d, 0x86, 0xfa, 0x68, 0x6c, 0x21, 0x89, 0x0d, 0x75, 0x3d, 0xcd, - 0xe8, 0xe9, 0xfb, 0x7a, 0x5f, 0x0c, 0x87, 0xfa, 0x0f, 0xf5, 0xde, 0xd8, 0x1a, 0x8c, 0x0c, 0x54, - 0x61, 0xc1, 0xae, 0xd6, 0xb7, 0xfb, 0x9a, 0xa5, 0x21, 0x99, 0x59, 0x03, 0x36, 0x4f, 0x1a, 0xda, - 0x3e, 0xaa, 0xe2, 0x35, 0x58, 0x19, 0x1b, 0xda, 0x63, 0x6d, 0xb0, 0xaf, 0x75, 0xf7, 0x75, 0x54, - 0x63, 0x6b, 0x8d, 0x91, 0x65, 0x3f, 0x18, 0x8d, 0x8d, 0x3e, 0xaa, 0xb3, 0xc1, 0x92, 0x99, 0x5a, - 0xaf, 0xa7, 0x1f, 0x58, 0x1c, 0xd2, 0x48, 0x5e, 0x56, 0x35, 0x90, 0xd9, 0x8c, 0xac, 0xea, 0x00, - 0xf9, 0x5e, 0x14, 0x47, 0x70, 0xe5, 0xaa, 0x91, 0xed, 0xe2, 0xe9, 0xa0, 0xfe, 0x5c, 0x02, 0xc8, - 0xf7, 0x08, 0xdf, 0xcd, 0xbf, 0x69, 0xc4, 0xf8, 0x78, 0x63, 0x79, 0x2b, 0x2f, 0xff, 0xb2, 0xf9, - 0x7e, 0xe1, 0x0b, 0xa5, 0xbc, 0xdc, 0xee, 0x62, 0xe9, 0xbf, 0xfa, 0x4e, 0xb1, 0xa1, 0xb9, 0x98, - 0x9f, 0x1d, 0x83, 0x62, 0xae, 0xe7, 0x3c, 0x14, 0x92, 0x58, 0xff, 0xfd, 0x6c, 0xfa, 0x2b, 0x09, - 0xd6, 0x96, 0x68, 0x5c, 0x79, 0x93, 0xc2, 0x91, 0x59, 0x7e, 0x83, 0x23, 0xb3, 0xb4, 0xd0, 0xdf, - 0x6f, 0x42, 0x86, 0x6d, 0x5e, 0x26, 0xf4, 0xcb, 0xbf, 0x9f, 0xde, 0x64, 0xf3, 0xba, 0x00, 0xb9, - 0xfe, 0xf1, 0x77, 0xa0, 0x56, 0xf8, 0xa5, 0x70, 0x63, 0xb9, 0x4b, 0x92, 0x9f, 0x0a, 0x82, 0x70, - 0x82, 0x55, 0x7f, 0x27, 0x41, 0x73, 0x31, 0x7c, 0x65, 0x51, 0xfe, 0xf3, 0xcf, 0xdd, 0x6e, 0x41, - 0x14, 0xe2, 0x1d, 0xf0, 0xde, 0x55, 0x75, 0xe4, 0xdf, 0x25, 0x17, 0x74, 0x71, 0xfb, 0x67, 0x65, - 0x80, 0xfc, 0x63, 0x1e, 0x5f, 0x83, 0x56, 0x32, 0xd9, 0xd9, 0x3d, 0x6d, 0x6c, 0xb2, 0x86, 0xdc, - 0x80, 0x1b, 0x44, 0x3f, 0xd8, 0x1f, 0xf4, 0x34, 0xd3, 0xee, 0x0f, 0xfa, 0x36, 0xeb, 0x9b, 0xa1, - 0x66, 0xf5, 0x76, 0x91, 0x84, 0xff, 0x0f, 0xae, 0x59, 0xa3, 0x91, 0x3d, 0xd4, 0x8c, 0x27, 0x76, - 0x6f, 0x7f, 0x6c, 0x5a, 0x3a, 0x31, 0x51, 0xb9, 0xd0, 0x99, 0x15, 0x96, 0x60, 0x60, 0x3c, 0xd4, - 0x4d, 0xd6, 0xb6, 0x36, 0xd1, 0x2c, 0xdd, 0xde, 0x1f, 0x0c, 0x07, 0x96, 0xde, 0x47, 0x32, 0x6e, - 0xc3, 0x3a, 0xd1, 0x3f, 0x19, 0xeb, 0xa6, 0x55, 0x8c, 0x54, 0x59, 0x87, 0x0e, 0x0c, 0xd3, 0x62, - 0xdd, 0x2f, 0xbc, 0xa8, 0x86, 0xdf, 0x81, 0xeb, 0xa6, 0x4e, 0x1e, 0x0f, 0x7a, 0xba, 0xbd, 0xd8, - 0xdd, 0x75, 0xbc, 0x0e, 0xc8, 0x32, 0xfb, 0xdd, 0x82, 0xb7, 0xc1, 0x68, 0x30, 0x76, 0xdd, 0xb1, - 0xf9, 0x04, 0x29, 0xec, 0x56, 0xbd, 0x01, 0xe9, 0x8d, 0x07, 0x96, 0xdd, 0x25, 0xba, 0xf6, 0x48, - 0x27, 0xf6, 0xe8, 0x40, 0x37, 0x10, 0x74, 0xbf, 0xf7, 0xe2, 0x55, 0xa7, 0xf4, 0xc5, 0xab, 0x4e, - 0xe9, 0xab, 0x57, 0x1d, 0xe9, 0xa7, 0xe7, 0x1d, 0xe9, 0x0f, 0xe7, 0x1d, 0xe9, 0xf9, 0x79, 0x47, - 0x7a, 0x71, 0xde, 0x91, 0xfe, 0x76, 0xde, 0x91, 0xbe, 0x3c, 0xef, 0x94, 0xbe, 0x3a, 0xef, 0x48, - 0xbf, 0x7e, 0xdd, 0x29, 0xbd, 0x78, 0xdd, 0x29, 0x7d, 0xf1, 0xba, 0x53, 0xfa, 0x51, 0x9d, 0xff, - 0xbc, 0x9a, 0x1d, 0x1e, 0xd6, 0xf8, 0x6f, 0xa8, 0x0f, 0xff, 0x19, 0x00, 0x00, 0xff, 0xff, 0x3d, - 0xca, 0x70, 0x87, 0xce, 0x12, 0x00, 0x00, + // 1975 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcd, 0x73, 0xdc, 0x48, + 0x15, 0x1f, 0xcd, 0x68, 0x3e, 0xf4, 0x3c, 0x63, 0x77, 0x3a, 0xc6, 0x3b, 0xeb, 0xda, 0x8c, 0x1d, + 0x51, 0x2c, 0x26, 0x05, 0x0e, 0xb5, 0x0b, 0xd9, 0xda, 0x54, 0x28, 0xd0, 0xcc, 0x28, 0xf1, 0x38, + 0xf3, 0xe1, 0x6d, 0x69, 0x12, 0xc2, 0x45, 0x25, 0x8f, 0xdb, 0xb6, 0x6a, 0xa5, 0xd1, 0x20, 0x69, + 0xb2, 0x31, 0x27, 0x2e, 0x50, 0x14, 0x27, 0x2e, 0x1c, 0xa0, 0xb8, 0x71, 0xe1, 0x2f, 0xe0, 0x1f, + 0xe0, 0x92, 0x2a, 0x8a, 0xaa, 0x1c, 0xb7, 0x38, 0xa4, 0x88, 0x73, 0xd9, 0xe3, 0x1e, 0x38, 0x71, + 0xa2, 0xba, 0x5b, 0x1f, 0xa3, 0xb1, 0x0d, 0x81, 0xcd, 0x4d, 0xfd, 0xde, 0xaf, 0x5f, 0xff, 0xfa, + 0xf5, 0xef, 0xb5, 0x9e, 0x04, 0x2b, 0x9e, 0xe3, 0x39, 0xc1, 0xee, 0x2c, 0xf0, 0x23, 0x1f, 0xd7, + 0x26, 0x7e, 0x10, 0xd1, 0x67, 0xb3, 0xc3, 0xcd, 0xef, 0x9c, 0x38, 0xd1, 0xe9, 0xfc, 0x70, 0x77, + 0xe2, 0x7b, 0xb7, 0x4f, 0xfc, 0x13, 0xff, 0x36, 0x07, 0x1c, 0xce, 0x8f, 0xf9, 0x88, 0x0f, 0xf8, + 0x93, 0x98, 0xa8, 0xfe, 0xb9, 0x08, 0xf5, 0xc7, 0x81, 0x13, 0x51, 0x42, 0x7f, 0x3a, 0xa7, 0x61, + 0x84, 0x0f, 0x00, 0x22, 0xc7, 0xa3, 0x21, 0x0d, 0x1c, 0x1a, 0x36, 0xa5, 0xed, 0xd2, 0xce, 0xca, + 0x07, 0xeb, 0xbb, 0x49, 0xf8, 0x5d, 0xd3, 0xf1, 0xa8, 0xc1, 0x7d, 0xed, 0xcd, 0xe7, 0x2f, 0xb7, + 0x0a, 0x7f, 0x7f, 0xb9, 0x85, 0x0f, 0x02, 0x6a, 0xbb, 0xae, 0x3f, 0x31, 0xd3, 0x79, 0x64, 0x21, + 0x06, 0xfe, 0x18, 0x2a, 0x86, 0x3f, 0x0f, 0x26, 0xb4, 0x59, 0xdc, 0x96, 0x76, 0x56, 0x3f, 0xb8, + 0x99, 0x45, 0x5b, 0x5c, 0x79, 0x57, 0x80, 0xf4, 0xe9, 0xdc, 0x23, 0xf1, 0x04, 0x7c, 0x17, 0x6a, + 0x1e, 0x8d, 0xec, 0x23, 0x3b, 0xb2, 0x9b, 0x25, 0x4e, 0xa5, 0x99, 0x4d, 0x1e, 0xd0, 0x28, 0x70, + 0x26, 0x83, 0xd8, 0xdf, 0x96, 0x9f, 0xbf, 0xdc, 0x92, 0x48, 0x8a, 0xc7, 0xf7, 0x60, 0x33, 0xfc, + 0xd4, 0x99, 0x59, 0xae, 0x7d, 0x48, 0x5d, 0x6b, 0x6a, 0x7b, 0xd4, 0x7a, 0x6a, 0xbb, 0xce, 0x91, + 0x1d, 0x39, 0xfe, 0xb4, 0xf9, 0x45, 0x75, 0x5b, 0xda, 0xa9, 0x91, 0x77, 0x18, 0xa4, 0xcf, 0x10, + 0x43, 0xdb, 0xa3, 0x8f, 0x52, 0xbf, 0xba, 0x05, 0x90, 0xf1, 0xc1, 0x55, 0x28, 0x69, 0x07, 0x3d, + 0x54, 0xc0, 0x35, 0x90, 0xc9, 0xb8, 0xaf, 0x23, 0x49, 0x5d, 0x83, 0x46, 0xcc, 0x3e, 0x9c, 0xf9, + 0xd3, 0x90, 0xaa, 0x77, 0xa1, 0xae, 0x07, 0x81, 0x1f, 0x74, 0x69, 0x64, 0x3b, 0x6e, 0x88, 0x6f, + 0x41, 0xb9, 0x63, 0xcf, 0x43, 0xda, 0x94, 0xf8, 0xae, 0x17, 0x72, 0xc8, 0x61, 0xdc, 0x47, 0x04, + 0x44, 0xfd, 0xa7, 0x04, 0x90, 0x65, 0x16, 0x6b, 0x50, 0xe1, 0xac, 0x93, 0xfc, 0x5f, 0xcf, 0xe6, + 0x72, 0xae, 0x07, 0xb6, 0x13, 0xb4, 0xd7, 0xe3, 0xf4, 0xd7, 0xb9, 0x49, 0x3b, 0xb2, 0x67, 0x11, + 0x0d, 0x48, 0x3c, 0x11, 0x7f, 0x17, 0xaa, 0xa1, 0xed, 0xcd, 0x5c, 0x1a, 0x36, 0x8b, 0x3c, 0x06, + 0xca, 0x62, 0x18, 0xdc, 0xc1, 0x13, 0x56, 0x20, 0x09, 0x0c, 0xdf, 0x01, 0x85, 0x3e, 0xa3, 0xde, + 0xcc, 0xb5, 0x83, 0x30, 0x4e, 0x36, 0x5e, 0xe0, 0x1c, 0xbb, 0xe2, 0x59, 0x19, 0x14, 0x7f, 0x0c, + 0x70, 0xea, 0x84, 0x91, 0x7f, 0x12, 0xd8, 0x5e, 0xd8, 0x94, 0x97, 0x09, 0xef, 0x25, 0xbe, 0x78, + 0xe6, 0x02, 0x58, 0xfd, 0x3e, 0x28, 0xe9, 0x7e, 0x30, 0x06, 0x99, 0x1d, 0x12, 0x4f, 0x57, 0x9d, + 0xf0, 0x67, 0xbc, 0x0e, 0xe5, 0xa7, 0xb6, 0x3b, 0x17, 0xca, 0xa9, 0x13, 0x31, 0x50, 0x35, 0xa8, + 0x88, 0x2d, 0xe0, 0x9b, 0x50, 0xe7, 0x42, 0x8b, 0x6c, 0x6f, 0x66, 0x79, 0x21, 0x87, 0x95, 0xc8, + 0x4a, 0x6a, 0x1b, 0x84, 0x59, 0x08, 0x16, 0x57, 0x4a, 0x42, 0xfc, 0xbe, 0x08, 0xab, 0x79, 0xfd, + 0xe0, 0x8f, 0x40, 0x8e, 0xce, 0x66, 0xc9, 0x71, 0x7d, 0xfd, 0x2a, 0x9d, 0xc5, 0x43, 0xf3, 0x6c, + 0x46, 0x09, 0x9f, 0x80, 0xbf, 0x0d, 0xd8, 0xe3, 0x36, 0xeb, 0xd8, 0xf6, 0x1c, 0xf7, 0x8c, 0x6b, + 0x8d, 0x53, 0x51, 0x08, 0x12, 0x9e, 0xfb, 0xdc, 0xc1, 0x24, 0xc6, 0xb6, 0x79, 0x4a, 0xdd, 0x59, + 0x53, 0xe6, 0x7e, 0xfe, 0xcc, 0x6c, 0xf3, 0xa9, 0x13, 0x35, 0xcb, 0xc2, 0xc6, 0x9e, 0xd5, 0x33, + 0x80, 0x6c, 0x25, 0xbc, 0x02, 0xd5, 0xf1, 0xf0, 0xe1, 0x70, 0xf4, 0x78, 0x88, 0x0a, 0x6c, 0xd0, + 0x19, 0x8d, 0x87, 0xa6, 0x4e, 0x90, 0x84, 0x15, 0x28, 0x3f, 0xd0, 0xc6, 0x0f, 0x74, 0x54, 0xc4, + 0x0d, 0x50, 0xf6, 0x7a, 0x86, 0x39, 0x7a, 0x40, 0xb4, 0x01, 0x2a, 0x61, 0x0c, 0xab, 0xdc, 0x93, + 0xd9, 0x64, 0x36, 0xd5, 0x18, 0x0f, 0x06, 0x1a, 0x79, 0x82, 0xca, 0x4c, 0xcc, 0xbd, 0xe1, 0xfd, + 0x11, 0xaa, 0xe0, 0x3a, 0xd4, 0x0c, 0x53, 0x33, 0x75, 0x43, 0x37, 0x51, 0x55, 0x7d, 0x08, 0x15, + 0xb1, 0xf4, 0x5b, 0x10, 0xa2, 0xfa, 0x4b, 0x09, 0x6a, 0x89, 0x78, 0xde, 0x86, 0xb0, 0x73, 0x92, + 0x48, 0xce, 0xf3, 0x82, 0x10, 0x4a, 0x17, 0x84, 0xa0, 0xfe, 0xb5, 0x0c, 0x4a, 0x2a, 0x46, 0x7c, + 0x03, 0x94, 0x89, 0x3f, 0x9f, 0x46, 0x96, 0x33, 0x8d, 0xf8, 0x91, 0xcb, 0x7b, 0x05, 0x52, 0xe3, + 0xa6, 0xde, 0x34, 0xc2, 0x37, 0x61, 0x45, 0xb8, 0x8f, 0x5d, 0xdf, 0x8e, 0xc4, 0x5a, 0x7b, 0x05, + 0x02, 0xdc, 0x78, 0x9f, 0xd9, 0x30, 0x82, 0x52, 0x38, 0xf7, 0xf8, 0x4a, 0x12, 0x61, 0x8f, 0x78, + 0x03, 0x2a, 0xe1, 0xe4, 0x94, 0x7a, 0x36, 0x3f, 0xdc, 0x6b, 0x24, 0x1e, 0xe1, 0x6f, 0xc0, 0xea, + 0xcf, 0x68, 0xe0, 0x5b, 0xd1, 0x69, 0x40, 0xc3, 0x53, 0xdf, 0x3d, 0xe2, 0x07, 0x2d, 0x91, 0x06, + 0xb3, 0x9a, 0x89, 0x11, 0xbf, 0x1f, 0xc3, 0x32, 0x5e, 0x15, 0xce, 0x4b, 0x22, 0x75, 0x66, 0xef, + 0x24, 0xdc, 0x6e, 0x01, 0x5a, 0xc0, 0x09, 0x82, 0x55, 0x4e, 0x50, 0x22, 0xab, 0x29, 0x52, 0x90, + 0xd4, 0x60, 0x75, 0x4a, 0x4f, 0xec, 0xc8, 0x79, 0x4a, 0xad, 0x70, 0x66, 0x4f, 0xc3, 0x66, 0x6d, + 0xf9, 0x46, 0x6f, 0xcf, 0x27, 0x9f, 0xd2, 0xc8, 0x98, 0xd9, 0xd3, 0xb8, 0x42, 0x1b, 0xc9, 0x0c, + 0x66, 0x0b, 0xf1, 0x37, 0x61, 0x2d, 0x0d, 0x71, 0x44, 0xdd, 0xc8, 0x0e, 0x9b, 0xca, 0x76, 0x69, + 0x07, 0x93, 0x34, 0x72, 0x97, 0x5b, 0x73, 0x40, 0xce, 0x2d, 0x6c, 0xc2, 0x76, 0x69, 0x47, 0xca, + 0x80, 0x9c, 0x18, 0xbb, 0xde, 0x56, 0x67, 0x7e, 0xe8, 0x2c, 0x90, 0x5a, 0xf9, 0xef, 0xa4, 0x92, + 0x19, 0x29, 0xa9, 0x34, 0x44, 0x4c, 0xaa, 0x2e, 0x48, 0x25, 0xe6, 0x8c, 0x54, 0x0a, 0x8c, 0x49, + 0x35, 0x04, 0xa9, 0xc4, 0x1c, 0x93, 0xba, 0x07, 0x10, 0xd0, 0x90, 0x46, 0xd6, 0x29, 0xcb, 0xfc, + 0x2a, 0xbf, 0x04, 0x6e, 0x5c, 0x72, 0x8d, 0xed, 0x12, 0x86, 0xda, 0x73, 0xa6, 0x11, 0x51, 0x82, + 0xe4, 0x11, 0xbf, 0x07, 0x4a, 0xaa, 0xb5, 0xe6, 0x1a, 0x17, 0x5f, 0x66, 0x50, 0xef, 0x82, 0x92, + 0xce, 0xca, 0x97, 0x72, 0x15, 0x4a, 0x4f, 0x74, 0x03, 0x49, 0xb8, 0x02, 0xc5, 0xe1, 0x08, 0x15, + 0xb3, 0x72, 0x2e, 0x6d, 0xca, 0xbf, 0xfa, 0x63, 0x4b, 0x6a, 0x57, 0xa1, 0xcc, 0x79, 0xb7, 0xeb, + 0x00, 0xd9, 0xb1, 0xab, 0x7f, 0x93, 0x61, 0x95, 0x1f, 0x71, 0x26, 0xe9, 0x10, 0x30, 0xf7, 0xd1, + 0xc0, 0x5a, 0xda, 0x49, 0xa3, 0xad, 0xff, 0xeb, 0xe5, 0x96, 0xb6, 0xd0, 0x19, 0xcc, 0x02, 0xdf, + 0xa3, 0xd1, 0x29, 0x9d, 0x87, 0x8b, 0x8f, 0x9e, 0x7f, 0x44, 0xdd, 0xdb, 0xe9, 0x05, 0xbd, 0xdb, + 0x11, 0xe1, 0xb2, 0x1d, 0xa3, 0xc9, 0x92, 0xe5, 0xab, 0x6a, 0xfe, 0xc6, 0xe2, 0xa6, 0x84, 0x8a, + 0x89, 0x92, 0x6a, 0x98, 0x15, 0xbb, 0xf0, 0xc4, 0xc5, 0xce, 0x07, 0x97, 0x54, 0xde, 0x5b, 0x50, + 0xd4, 0x5b, 0xa8, 0x94, 0x6f, 0x01, 0x4a, 0x59, 0x1c, 0x72, 0x6c, 0x22, 0xb6, 0x54, 0x83, 0x22, + 0x04, 0x87, 0xa6, 0xab, 0x25, 0x50, 0x51, 0x2c, 0x69, 0x0d, 0xc5, 0xd0, 0x7d, 0xb9, 0x26, 0xa1, + 0xe2, 0xbe, 0x5c, 0xab, 0xa0, 0xea, 0xbe, 0x5c, 0x53, 0x10, 0xec, 0xcb, 0xb5, 0x3a, 0x6a, 0xec, + 0xcb, 0xb5, 0x35, 0x84, 0x48, 0x76, 0x8b, 0x91, 0xa5, 0xdb, 0x83, 0x2c, 0x97, 0x2d, 0x59, 0x2e, + 0x99, 0x45, 0x89, 0xde, 0x03, 0xc8, 0xb6, 0xc7, 0x4e, 0xd5, 0x3f, 0x3e, 0x0e, 0xa9, 0xb8, 0x1a, + 0xaf, 0x91, 0x78, 0xc4, 0xec, 0x2e, 0x9d, 0x9e, 0x44, 0xa7, 0xfc, 0x40, 0x1a, 0x24, 0x1e, 0xa9, + 0x73, 0xc0, 0x79, 0x31, 0xf2, 0x37, 0xfa, 0x1b, 0xbc, 0x9d, 0xef, 0x81, 0x92, 0xca, 0x8d, 0xaf, + 0x95, 0xeb, 0xf0, 0xf2, 0x31, 0xe3, 0x0e, 0x2f, 0x9b, 0xa0, 0x4e, 0x61, 0x4d, 0x34, 0x02, 0x59, + 0x11, 0xa4, 0x8a, 0x91, 0x2e, 0x51, 0x4c, 0x31, 0x53, 0xcc, 0x87, 0x50, 0x4d, 0xf2, 0x2e, 0x7a, + 0x9d, 0x77, 0x2f, 0x6b, 0x59, 0x38, 0x82, 0x24, 0x48, 0x35, 0x84, 0xb5, 0x25, 0x1f, 0x6e, 0x01, + 0x1c, 0xfa, 0xf3, 0xe9, 0x91, 0x1d, 0xb7, 0xcb, 0xd2, 0x4e, 0x99, 0x2c, 0x58, 0x18, 0x1f, 0xd7, + 0xff, 0x8c, 0x06, 0x89, 0x82, 0xf9, 0x80, 0x59, 0xe7, 0xb3, 0x19, 0x0d, 0x62, 0x0d, 0x8b, 0x41, + 0xc6, 0x5d, 0x5e, 0xe0, 0xae, 0xba, 0x70, 0x7d, 0x69, 0x93, 0x3c, 0xb9, 0xb9, 0x1b, 0xa7, 0xb8, + 0x74, 0xe3, 0xe0, 0x8f, 0x2e, 0xe6, 0xf5, 0xdd, 0xe5, 0x06, 0x30, 0x8d, 0xb7, 0x98, 0xd2, 0xbf, + 0xc8, 0xd0, 0xf8, 0x64, 0x4e, 0x83, 0xb3, 0xa4, 0xaf, 0xc5, 0x77, 0xa0, 0x12, 0x46, 0x76, 0x34, + 0x0f, 0xe3, 0xce, 0xa8, 0x95, 0xc5, 0xc9, 0x01, 0x77, 0x0d, 0x8e, 0x22, 0x31, 0x1a, 0xff, 0x08, + 0x80, 0xb2, 0x46, 0xd7, 0xe2, 0x5d, 0xd5, 0x85, 0xd6, 0x3f, 0x3f, 0x97, 0xb7, 0xc4, 0xbc, 0xa7, + 0x52, 0x68, 0xf2, 0xc8, 0xf2, 0xc1, 0x07, 0x3c, 0x4b, 0x0a, 0x11, 0x03, 0xbc, 0xcb, 0xf8, 0x04, + 0xce, 0xf4, 0x84, 0xa7, 0x29, 0x57, 0xa0, 0x06, 0xb7, 0x77, 0xed, 0xc8, 0xde, 0x2b, 0x90, 0x18, + 0xc5, 0xf0, 0x4f, 0xe9, 0x24, 0xf2, 0x03, 0x7e, 0x03, 0xe5, 0xf0, 0x8f, 0xb8, 0x3d, 0xc1, 0x0b, + 0x14, 0x8f, 0x3f, 0xb1, 0x5d, 0x3b, 0xe0, 0xaf, 0xdf, 0x7c, 0x7c, 0x6e, 0x4f, 0xe3, 0xf3, 0x11, + 0xc3, 0x7b, 0x76, 0x14, 0x38, 0xcf, 0xf8, 0xf5, 0x95, 0xc3, 0x0f, 0xb8, 0x3d, 0xc1, 0x0b, 0x14, + 0xde, 0x84, 0xda, 0x67, 0x76, 0x30, 0x75, 0xa6, 0x27, 0xe2, 0x8a, 0x51, 0x48, 0x3a, 0x56, 0xdf, + 0x87, 0x8a, 0xc8, 0x22, 0x7b, 0x0f, 0xe8, 0x84, 0x8c, 0x88, 0x68, 0xf7, 0x8c, 0x71, 0xa7, 0xa3, + 0x1b, 0x06, 0x92, 0xc4, 0x4b, 0x41, 0xfd, 0xad, 0x04, 0x4a, 0x9a, 0x32, 0xd6, 0xc7, 0x0d, 0x47, + 0x43, 0x5d, 0x40, 0xcd, 0xde, 0x40, 0x1f, 0x8d, 0x4d, 0x24, 0xb1, 0xa6, 0xae, 0xa3, 0x0d, 0x3b, + 0x7a, 0x5f, 0xef, 0x8a, 0xe6, 0x50, 0xff, 0xb1, 0xde, 0x19, 0x9b, 0xbd, 0xd1, 0x10, 0x95, 0x98, + 0xb3, 0xad, 0x75, 0xad, 0xae, 0x66, 0x6a, 0x48, 0x66, 0xa3, 0x1e, 0xeb, 0x27, 0x87, 0x5a, 0x1f, + 0x95, 0xf1, 0x1a, 0xac, 0x8c, 0x87, 0xda, 0x23, 0xad, 0xd7, 0xd7, 0xda, 0x7d, 0x1d, 0x55, 0xd8, + 0xdc, 0xe1, 0xc8, 0xb4, 0xee, 0x8f, 0xc6, 0xc3, 0x2e, 0xaa, 0xb2, 0xc6, 0x92, 0x0d, 0xb5, 0x4e, + 0x47, 0x3f, 0x30, 0x39, 0xa4, 0x16, 0xbf, 0xac, 0x2a, 0x20, 0xb3, 0x1e, 0x59, 0xd5, 0x01, 0xb2, + 0xb3, 0xc8, 0xb7, 0xe0, 0xca, 0x55, 0x2d, 0xdb, 0xc5, 0xdb, 0x41, 0xfd, 0x85, 0x04, 0x90, 0x9d, + 0x11, 0xbe, 0x93, 0x7d, 0xd3, 0x88, 0xf6, 0x71, 0x63, 0xf9, 0x28, 0x2f, 0xff, 0xb2, 0xf9, 0x61, + 0xee, 0x0b, 0xa5, 0xb8, 0x5c, 0xee, 0x62, 0xea, 0x7f, 0xfa, 0x4e, 0xb1, 0xa0, 0xbe, 0x18, 0x9f, + 0x5d, 0x83, 0xa2, 0xaf, 0xe7, 0x3c, 0x14, 0x12, 0x8f, 0xfe, 0xff, 0xde, 0xf4, 0xd7, 0x12, 0xac, + 0x2d, 0xd1, 0xb8, 0x72, 0x91, 0xdc, 0x95, 0x59, 0x7c, 0x83, 0x2b, 0xb3, 0xb0, 0x50, 0xdf, 0x6f, + 0x42, 0x86, 0x1d, 0x5e, 0x2a, 0xf4, 0xcb, 0xbf, 0x9f, 0xde, 0xe4, 0xf0, 0xda, 0x00, 0x99, 0xfe, + 0xf1, 0xf7, 0xa0, 0x92, 0xfb, 0xa5, 0xb0, 0xb1, 0x5c, 0x25, 0xf1, 0x4f, 0x05, 0x41, 0x38, 0xc6, + 0xaa, 0x7f, 0x90, 0xa0, 0xbe, 0xe8, 0xbe, 0x32, 0x29, 0xff, 0xfb, 0xe7, 0x6e, 0x3b, 0x27, 0x0a, + 0xf1, 0x0e, 0x78, 0xef, 0xaa, 0x3c, 0xf2, 0xef, 0x92, 0x0b, 0xba, 0xb8, 0xf5, 0xbb, 0x22, 0x40, + 0xf6, 0x31, 0x8f, 0xaf, 0x41, 0x23, 0xee, 0xec, 0xac, 0x8e, 0x36, 0x36, 0x58, 0x41, 0x6e, 0xc2, + 0x06, 0xd1, 0x0f, 0xfa, 0xbd, 0x8e, 0x66, 0x58, 0xdd, 0x5e, 0xd7, 0x62, 0x75, 0x33, 0xd0, 0xcc, + 0xce, 0x1e, 0x92, 0xf0, 0xd7, 0xe0, 0x9a, 0x39, 0x1a, 0x59, 0x03, 0x6d, 0xf8, 0xc4, 0xea, 0xf4, + 0xc7, 0x86, 0xa9, 0x13, 0x03, 0x15, 0x73, 0x95, 0x59, 0x62, 0x01, 0x7a, 0xc3, 0x07, 0xba, 0xc1, + 0xca, 0xd6, 0x22, 0x9a, 0xa9, 0x5b, 0xfd, 0xde, 0xa0, 0x67, 0xea, 0x5d, 0x24, 0xe3, 0x26, 0xac, + 0x13, 0xfd, 0x93, 0xb1, 0x6e, 0x98, 0x79, 0x4f, 0x99, 0x55, 0x68, 0x6f, 0x68, 0x98, 0xac, 0xfa, + 0x85, 0x15, 0x55, 0xf0, 0x3b, 0x70, 0xdd, 0xd0, 0xc9, 0xa3, 0x5e, 0x47, 0xb7, 0x16, 0xab, 0xbb, + 0x8a, 0xd7, 0x01, 0x99, 0x46, 0xb7, 0x9d, 0xb3, 0xd6, 0x18, 0x0d, 0xc6, 0xae, 0x3d, 0x36, 0x9e, + 0x20, 0x85, 0x2d, 0xd5, 0xe9, 0x91, 0xce, 0xb8, 0x67, 0x5a, 0x6d, 0xa2, 0x6b, 0x0f, 0x75, 0x62, + 0x8d, 0x0e, 0xf4, 0x21, 0x02, 0xbc, 0x01, 0x78, 0xa0, 0x9b, 0x7b, 0x23, 0xb1, 0x37, 0xad, 0xdf, + 0x1f, 0x3d, 0xd6, 0xbb, 0x68, 0xa5, 0xfd, 0x83, 0x17, 0xaf, 0x5a, 0x85, 0xcf, 0x5f, 0xb5, 0x0a, + 0x5f, 0xbe, 0x6a, 0x49, 0x3f, 0x3f, 0x6f, 0x49, 0x7f, 0x3a, 0x6f, 0x49, 0xcf, 0xcf, 0x5b, 0xd2, + 0x8b, 0xf3, 0x96, 0xf4, 0x8f, 0xf3, 0x96, 0xf4, 0xc5, 0x79, 0xab, 0xf0, 0xe5, 0x79, 0x4b, 0xfa, + 0xcd, 0xeb, 0x56, 0xe1, 0xc5, 0xeb, 0x56, 0xe1, 0xf3, 0xd7, 0xad, 0xc2, 0x4f, 0xaa, 0xfc, 0xa7, + 0xd6, 0xec, 0xf0, 0xb0, 0xc2, 0x7f, 0x4f, 0x7d, 0xf8, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdd, + 0x9d, 0x98, 0x5d, 0xe6, 0x12, 0x00, 0x00, } func (x ErrorCause) String() string { diff --git a/pkg/mimirpb/mimir.proto b/pkg/mimirpb/mimir.proto index 9057abea05..aff8fa380f 100644 --- a/pkg/mimirpb/mimir.proto +++ b/pkg/mimirpb/mimir.proto @@ -46,6 +46,7 @@ enum ErrorCause { TSDB_UNAVAILABLE = 8; TOO_BUSY = 9; CIRCUIT_BREAKER_OPEN = 10; + METHOD_NOT_ALLOWED = 11; } message ErrorDetails { diff --git a/pkg/storage/ingest/pusher.go b/pkg/storage/ingest/pusher.go index 10350cd4a7..dc5fac6d95 100644 --- a/pkg/storage/ingest/pusher.go +++ b/pkg/storage/ingest/pusher.go @@ -19,7 +19,7 @@ import ( ) type Pusher interface { - Push(context.Context, *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) + PushToStorage(context.Context, *mimirpb.WriteRequest) error } type pusherConsumer struct { @@ -88,7 +88,7 @@ func (c pusherConsumer) pushRequests(ctx context.Context, reqC <-chan parsedReco processingStart := time.Now() ctx := user.InjectOrgID(ctx, wr.tenantID) - _, err := c.p.Push(ctx, wr.WriteRequest) + err := c.p.PushToStorage(ctx, wr.WriteRequest) c.processingTimeSeconds.Observe(time.Since(processingStart).Seconds()) c.totalRequests.Inc() diff --git a/pkg/storage/ingest/pusher_test.go b/pkg/storage/ingest/pusher_test.go index c633b94147..77f894f920 100644 --- a/pkg/storage/ingest/pusher_test.go +++ b/pkg/storage/ingest/pusher_test.go @@ -17,9 +17,9 @@ import ( "github.com/grafana/mimir/pkg/mimirpb" ) -type pusherFunc func(context.Context, *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) +type pusherFunc func(context.Context, *mimirpb.WriteRequest) error -func (p pusherFunc) Push(ctx context.Context, request *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) { +func (p pusherFunc) PushToStorage(ctx context.Context, request *mimirpb.WriteRequest) error { return p(ctx, request) } @@ -41,11 +41,10 @@ func TestPusherConsumer(t *testing.T) { } type response struct { - *mimirpb.WriteResponse err error } - okResponse := response{WriteResponse: &mimirpb.WriteResponse{}} + okResponse := response{nil} testCases := map[string]struct { records []record @@ -162,7 +161,7 @@ func TestPusherConsumer(t *testing.T) { tc := tc t.Run(name, func(t *testing.T) { receivedReqs := 0 - pusher := pusherFunc(func(ctx context.Context, request *mimirpb.WriteRequest) (*mimirpb.WriteResponse, error) { + pusher := pusherFunc(func(ctx context.Context, request *mimirpb.WriteRequest) error { defer func() { receivedReqs++ }() require.GreaterOrEqualf(t, len(tc.expectedWRs), receivedReqs+1, "received more requests (%d) than expected (%d)", receivedReqs+1, len(tc.expectedWRs)) @@ -175,7 +174,7 @@ func TestPusherConsumer(t *testing.T) { assert.NoError(t, err) assert.Equal(t, tenantID, actualTenantID) - return tc.responses[receivedReqs].WriteResponse, tc.responses[receivedReqs].err + return tc.responses[receivedReqs].err }) c := newPusherConsumer(pusher, prometheus.NewPedanticRegistry(), log.NewNopLogger()) err := c.consume(context.Background(), tc.records)