From ef7e6450ba54406e6cfcf0085fb5d4522d5a72bc Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Fri, 9 Jan 2026 17:26:01 +0530 Subject: [PATCH 01/52] feat: cache plans --- router/core/cache_warmup_plans.go | 29 ++++++++++++++++++ router/core/graph_server.go | 51 ++++++++++++++++++++----------- router/core/operation_planner.go | 8 +++++ router/core/router.go | 12 ++++++-- 4 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 router/core/cache_warmup_plans.go diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go new file mode 100644 index 0000000000..a8d71854e5 --- /dev/null +++ b/router/core/cache_warmup_plans.go @@ -0,0 +1,29 @@ +package core + +import ( + "context" + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" + "go.uber.org/zap" +) + +var _ CacheWarmupSource = (*PlanSource)(nil) + +type PlanSource struct { + plans map[uint64]string +} + +func NewPlanSource(plans map[uint64]string) *PlanSource { + return &PlanSource{plans: plans} +} + +func (c *PlanSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { + var items []*nodev1.Operation + + for _, query := range c.plans { + items = append(items, &nodev1.Operation{ + Request: &nodev1.OperationRequest{Query: query}, + }) + } + + return items, nil +} diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 87aa96331c..003fa4c4b3 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -102,6 +102,7 @@ type ( traceDialer *TraceDialer connector *grpcconnector.Connector circuitBreakerManager *circuit.Manager + operationPlanner *OperationPlanner } ) @@ -112,6 +113,7 @@ type BuildGraphMuxOptions struct { EngineConfig *nodev1.EngineConfiguration ConfigSubgraphs []*nodev1.Subgraph RoutingUrlGroupings map[string]map[string]bool + Plans map[uint64]string } func (b BuildGraphMuxOptions) IsBaseGraph() bool { @@ -119,7 +121,7 @@ func (b BuildGraphMuxOptions) IsBaseGraph() bool { } // newGraphServer creates a new server instance. -func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc) (*graphServer, error) { +func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc, plans map[uint64]string) (*graphServer, error) { /* Older versions of composition will not populate a compatibility version. * Currently, all "old" router execution configurations are compatible as there have been no breaking * changes. @@ -273,6 +275,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC EngineConfig: routerConfig.GetEngineConfig(), ConfigSubgraphs: routerConfig.GetSubgraphs(), RoutingUrlGroupings: routingUrlGroupings, + Plans: plans, }) if err != nil { return nil, fmt.Errorf("failed to build base mux: %w", err) @@ -283,7 +286,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC s.logger.Info("Feature flags enabled", zap.Strings("flags", maps.Keys(featureFlagConfigMap))) } - multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap) + multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, plans) if err != nil { return nil, fmt.Errorf("failed to build feature flag handler: %w", err) } @@ -433,6 +436,7 @@ func (s *graphServer) buildMultiGraphHandler( ctx context.Context, baseMux *chi.Mux, featureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig, + plans map[uint64]string, ) (http.HandlerFunc, error) { if len(featureFlagConfigs) == 0 { return baseMux.ServeHTTP, nil @@ -447,6 +451,7 @@ func (s *graphServer) buildMultiGraphHandler( RouterConfigVersion: executionConfig.GetVersion(), EngineConfig: executionConfig.GetEngineConfig(), ConfigSubgraphs: executionConfig.Subgraphs, + Plans: plans, }) if err != nil { return nil, fmt.Errorf("failed to build mux for feature flag '%s': %w", featureFlagName, err) @@ -519,12 +524,12 @@ type graphMux struct { validationCache *ristretto.Cache[uint64, bool] operationHashCache *ristretto.Cache[uint64, string] - accessLogsFileLogger *logging.BufferedLogger - metricStore rmetric.Store - prometheusCacheMetrics *rmetric.CacheMetrics - otelCacheMetrics *rmetric.CacheMetrics - streamMetricStore rmetric.StreamMetricStore - prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter + accessLogsFileLogger *logging.BufferedLogger + metricStore rmetric.Store + prometheusCacheMetrics *rmetric.CacheMetrics + otelCacheMetrics *rmetric.CacheMetrics + streamMetricStore rmetric.StreamMetricStore + prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter } // buildOperationCaches creates the caches for the graph mux. @@ -749,6 +754,7 @@ func (s *graphMux) configureCacheMetrics(srv *graphServer, baseOtelAttributes [] func (s *graphMux) Shutdown(ctx context.Context) error { s.planCache.Close() + //s.planCache.Get() s.persistedOperationCache.Close() s.normalizationCache.Close() s.variablesNormalizationCache.Close() @@ -802,6 +808,10 @@ func (s *graphMux) Shutdown(ctx context.Context) error { return nil } +func (s *graphServer) getManifestCache() map[uint64]string { + return nil +} + // buildGraphMux creates a new graph mux with the given feature flags and engine configuration. // It also creates a new execution plan cache for the mux. The mux is not mounted on the server. // The mux is appended internally to the graph server's list of muxes to clean up later when the server is swapped. @@ -1297,6 +1307,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) operationPlanner := NewOperationPlanner(executor, gm.planCache) + s.operationPlanner = operationPlanner // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { @@ -1305,7 +1316,7 @@ func (s *graphServer) buildGraphMux( } } - if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled { + if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled || opts.Plans != nil { if s.graphApiToken == "" { return nil, fmt.Errorf("graph token is required for cache warmup in order to communicate with the CDN") @@ -1346,16 +1357,20 @@ func (s *graphServer) buildGraphMux( ) } - if s.Config.cacheWarmup.Source.Filesystem != nil { - warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ - RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, - }) - } else { - cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) - if err != nil { - return nil, fmt.Errorf("failed to create cdn source: %w", err) + if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled { + if s.Config.cacheWarmup.Source.Filesystem != nil { + warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ + RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, + }) + } else { + cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) + if err != nil { + return nil, fmt.Errorf("failed to create cdn source: %w", err) + } + warmupConfig.Source = cdnSource } - warmupConfig.Source = cdnSource + } else if opts.Plans != nil { + warmupConfig.Source = NewPlanSource(opts.Plans) } err = WarmupCaches(ctx, warmupConfig) diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index 38c3b6aac5..a07433ffb7 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -26,6 +26,7 @@ type planWithMetaData struct { type OperationPlanner struct { sf singleflight.Group planCache ExecutionPlanCache[uint64, *planWithMetaData] + plans map[uint64]string executor *Executor trackUsageInfo bool } @@ -44,9 +45,14 @@ func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64 planCache: planCache, executor: executor, trackUsageInfo: executor.TrackUsageInfo, + plans: make(map[uint64]string), } } +func (p *OperationPlanner) getPlans() map[uint64]string { + return p.plans +} + func (p *OperationPlanner) preparePlan(ctx *operationContext) (*planWithMetaData, error) { doc, report := astparser.ParseGraphqlDocumentString(ctx.content) if report.HasErrors() { @@ -125,6 +131,7 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions operationID := opContext.internalHash // try to get a prepared plan for this operation ID from the cache cachedPlan, ok := p.planCache.Get(operationID) + if ok && cachedPlan != nil { // re-use a prepared plan opContext.preparedPlan = cachedPlan @@ -139,6 +146,7 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions return nil, err } p.planCache.Set(operationID, prepared, 1) + p.plans[operationID] = opContext.Content() return prepared, nil }) if err != nil { diff --git a/router/core/router.go b/router/core/router.go index 8bdc557b29..ccc92f7f2d 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -596,7 +596,12 @@ func NewRouter(opts ...Option) (*Router, error) { // newGraphServer creates a new server. func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error { - server, err := newGraphServer(ctx, r, cfg, r.proxy) + var plans map[uint64]string + if r.httpServer.graphServer != nil { + plans = r.httpServer.graphServer.operationPlanner.getPlans() + } + + server, err := newGraphServer(ctx, r, cfg, r.proxy, plans) if err != nil { r.logger.Error("Failed to create graph server. Keeping the old server", zap.Error(err)) return err @@ -1357,7 +1362,7 @@ func (r *Router) Start(ctx context.Context) error { ) } - r.configPoller.Subscribe(ctx, func(newConfig *nodev1.RouterConfig, oldVersion string) error { + handler := func(newConfig *nodev1.RouterConfig, oldVersion string) error { if r.shutdown.Load() { r.logger.Warn("Router is in shutdown state. Skipping config update") return nil @@ -1370,7 +1375,8 @@ func (r *Router) Start(ctx context.Context) error { } return nil - }) + } + r.configPoller.Subscribe(ctx, handler) // Mark the server as ready r.httpServer.healthcheck.SetReady(true) From 419cabffbd08e2dab76377e0c8083019fdbdd7ed Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Fri, 9 Jan 2026 17:28:34 +0530 Subject: [PATCH 02/52] fix: cleanup --- router/core/graph_server.go | 5 ----- router/core/router.go | 5 ++--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 003fa4c4b3..ea6a410fa6 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -754,7 +754,6 @@ func (s *graphMux) configureCacheMetrics(srv *graphServer, baseOtelAttributes [] func (s *graphMux) Shutdown(ctx context.Context) error { s.planCache.Close() - //s.planCache.Get() s.persistedOperationCache.Close() s.normalizationCache.Close() s.variablesNormalizationCache.Close() @@ -808,10 +807,6 @@ func (s *graphMux) Shutdown(ctx context.Context) error { return nil } -func (s *graphServer) getManifestCache() map[uint64]string { - return nil -} - // buildGraphMux creates a new graph mux with the given feature flags and engine configuration. // It also creates a new execution plan cache for the mux. The mux is not mounted on the server. // The mux is appended internally to the graph server's list of muxes to clean up later when the server is swapped. diff --git a/router/core/router.go b/router/core/router.go index ccc92f7f2d..3154a1f217 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1362,7 +1362,7 @@ func (r *Router) Start(ctx context.Context) error { ) } - handler := func(newConfig *nodev1.RouterConfig, oldVersion string) error { + r.configPoller.Subscribe(ctx, func(newConfig *nodev1.RouterConfig, oldVersion string) error { if r.shutdown.Load() { r.logger.Warn("Router is in shutdown state. Skipping config update") return nil @@ -1375,8 +1375,7 @@ func (r *Router) Start(ctx context.Context) error { } return nil - } - r.configPoller.Subscribe(ctx, handler) + }) // Mark the server as ready r.httpServer.healthcheck.SetReady(true) From e65cdf2d987f68e2ac57004fe9d0ce7ec924dd92 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 13 Jan 2026 16:27:01 +0530 Subject: [PATCH 03/52] fix: updates --- router/core/cache_warmup_plans.go | 8 +- router/core/graph_server.go | 44 ++++---- router/core/http_server.go | 1 + router/core/operation_planner.go | 28 +++-- router/core/restart_switchover_config.go | 131 +++++++++++++++++++++++ router/core/router.go | 63 ++--------- router/core/router_config.go | 2 + router/pkg/config/config.go | 40 ++++--- 8 files changed, 202 insertions(+), 115 deletions(-) create mode 100644 router/core/restart_switchover_config.go diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index a8d71854e5..0a182c1421 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -9,17 +9,17 @@ import ( var _ CacheWarmupSource = (*PlanSource)(nil) type PlanSource struct { - plans map[uint64]string + queries *ringBuffer } -func NewPlanSource(plans map[uint64]string) *PlanSource { - return &PlanSource{plans: plans} +func NewPlanSource(switchoverCacheWarmerQueries *ringBuffer) *PlanSource { + return &PlanSource{queries: switchoverCacheWarmerQueries} } func (c *PlanSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { var items []*nodev1.Operation - for _, query := range c.plans { + for _, query := range c.queries.Snapshot() { items = append(items, &nodev1.Operation{ Request: &nodev1.OperationRequest{Query: query}, }) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index ea6a410fa6..14d14f0a4b 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -102,7 +102,6 @@ type ( traceDialer *TraceDialer connector *grpcconnector.Connector circuitBreakerManager *circuit.Manager - operationPlanner *OperationPlanner } ) @@ -113,7 +112,7 @@ type BuildGraphMuxOptions struct { EngineConfig *nodev1.EngineConfiguration ConfigSubgraphs []*nodev1.Subgraph RoutingUrlGroupings map[string]map[string]bool - Plans map[uint64]string + SwitchoverConfig *SwitchoverConfig } func (b BuildGraphMuxOptions) IsBaseGraph() bool { @@ -121,7 +120,7 @@ func (b BuildGraphMuxOptions) IsBaseGraph() bool { } // newGraphServer creates a new server instance. -func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc, plans map[uint64]string) (*graphServer, error) { +func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc, switchoverConfig *SwitchoverConfig) (*graphServer, error) { /* Older versions of composition will not populate a compatibility version. * Currently, all "old" router execution configurations are compatible as there have been no breaking * changes. @@ -275,7 +274,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC EngineConfig: routerConfig.GetEngineConfig(), ConfigSubgraphs: routerConfig.GetSubgraphs(), RoutingUrlGroupings: routingUrlGroupings, - Plans: plans, + SwitchoverConfig: switchoverConfig, }) if err != nil { return nil, fmt.Errorf("failed to build base mux: %w", err) @@ -286,7 +285,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC s.logger.Info("Feature flags enabled", zap.Strings("flags", maps.Keys(featureFlagConfigMap))) } - multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, plans) + multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, switchoverConfig) if err != nil { return nil, fmt.Errorf("failed to build feature flag handler: %w", err) } @@ -436,7 +435,7 @@ func (s *graphServer) buildMultiGraphHandler( ctx context.Context, baseMux *chi.Mux, featureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig, - plans map[uint64]string, + switchoverConfig *SwitchoverConfig, ) (http.HandlerFunc, error) { if len(featureFlagConfigs) == 0 { return baseMux.ServeHTTP, nil @@ -451,7 +450,7 @@ func (s *graphServer) buildMultiGraphHandler( RouterConfigVersion: executionConfig.GetVersion(), EngineConfig: executionConfig.GetEngineConfig(), ConfigSubgraphs: executionConfig.Subgraphs, - Plans: plans, + SwitchoverConfig: switchoverConfig, }) if err != nil { return nil, fmt.Errorf("failed to build mux for feature flag '%s': %w", featureFlagName, err) @@ -1301,8 +1300,9 @@ func (s *graphServer) buildGraphMux( DisableExposingVariablesContentOnValidationError: s.engineExecutionConfiguration.DisableExposingVariablesContentOnValidationError, ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache) - s.operationPlanner = operationPlanner + + cacheWarmerQueries := opts.SwitchoverConfig.CacheWarmerQueries.getOrCreateBuffer(opts.FeatureFlagName) + operationPlanner := NewOperationPlanner(executor, gm.planCache, cacheWarmerQueries) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { @@ -1311,7 +1311,7 @@ func (s *graphServer) buildGraphMux( } } - if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled || opts.Plans != nil { + if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled { if s.graphApiToken == "" { return nil, fmt.Errorf("graph token is required for cache warmup in order to communicate with the CDN") @@ -1352,20 +1352,18 @@ func (s *graphServer) buildGraphMux( ) } - if s.Config.cacheWarmup != nil && s.Config.cacheWarmup.Enabled { - if s.Config.cacheWarmup.Source.Filesystem != nil { - warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ - RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, - }) - } else { - cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) - if err != nil { - return nil, fmt.Errorf("failed to create cdn source: %w", err) - } - warmupConfig.Source = cdnSource + if s.Config.cacheWarmup.Source.Filesystem != nil { + warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ + RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, + }) + } else if s.Config.cacheWarmup.Source.InMemorySwitchover.Enabled { + warmupConfig.Source = NewPlanSource(cacheWarmerQueries) + } else { + cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) + if err != nil { + return nil, fmt.Errorf("failed to create cdn source: %w", err) } - } else if opts.Plans != nil { - warmupConfig.Source = NewPlanSource(opts.Plans) + warmupConfig.Source = cdnSource } err = WarmupCaches(ctx, warmupConfig) diff --git a/router/core/http_server.go b/router/core/http_server.go index 9ad8dcd350..8ca083510f 100644 --- a/router/core/http_server.go +++ b/router/core/http_server.go @@ -36,6 +36,7 @@ type httpServerOptions struct { livenessCheckPath string readinessCheckPath string healthCheckPath string + switchoverConfig *SwitchoverConfig } func newServer(opts *httpServerOptions) *server { diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index a07433ffb7..041714e4a4 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -24,11 +24,11 @@ type planWithMetaData struct { } type OperationPlanner struct { - sf singleflight.Group - planCache ExecutionPlanCache[uint64, *planWithMetaData] - plans map[uint64]string - executor *Executor - trackUsageInfo bool + sf singleflight.Group + planCache ExecutionPlanCache[uint64, *planWithMetaData] + executor *Executor + trackUsageInfo bool + cacheWarmerQueries *ringBuffer } type ExecutionPlanCache[K any, V any] interface { @@ -40,19 +40,15 @@ type ExecutionPlanCache[K any, V any] interface { Close() } -func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64, *planWithMetaData]) *OperationPlanner { +func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64, *planWithMetaData], cacheWarmerQueries *ringBuffer) *OperationPlanner { return &OperationPlanner{ - planCache: planCache, - executor: executor, - trackUsageInfo: executor.TrackUsageInfo, - plans: make(map[uint64]string), + planCache: planCache, + executor: executor, + trackUsageInfo: executor.TrackUsageInfo, + cacheWarmerQueries: cacheWarmerQueries, } } -func (p *OperationPlanner) getPlans() map[uint64]string { - return p.plans -} - func (p *OperationPlanner) preparePlan(ctx *operationContext) (*planWithMetaData, error) { doc, report := astparser.ParseGraphqlDocumentString(ctx.content) if report.HasErrors() { @@ -146,7 +142,9 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions return nil, err } p.planCache.Set(operationID, prepared, 1) - p.plans[operationID] = opContext.Content() + if p.cacheWarmerQueries != nil { + p.cacheWarmerQueries.Add(opContext.content) + } return prepared, nil }) if err != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go new file mode 100644 index 0000000000..72451e5b6c --- /dev/null +++ b/router/core/restart_switchover_config.go @@ -0,0 +1,131 @@ +package core + +import ( + "sync" + + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" +) + +// This file describes any configuration which should persist across router restarts +type SwitchoverConfig struct { + CacheWarmerQueries *CacheWarmerQueries +} + +type CacheWarmerQueries struct { + maxSize int // Maximum size of the ring buffer per feature flag + mu sync.RWMutex + queriesForFeatureFlag map[string]*ringBuffer // Map of feature flag key to ring buffer ("" is default) +} + +func NewSwitchoverConfig(config *Config) *SwitchoverConfig { + switchoverConfig := &SwitchoverConfig{} + + inMemorySwitchoverCacheWarmerEnabled := config.cacheWarmup != nil && config.cacheWarmup.Enabled && config.cacheWarmup.Source.InMemorySwitchover.Enabled + + if inMemorySwitchoverCacheWarmerEnabled { + switchoverConfig.CacheWarmerQueries = &CacheWarmerQueries{ + maxSize: config.cacheWarmup.Source.InMemorySwitchover.MaxEntries, + queriesForFeatureFlag: make(map[string]*ringBuffer), + } + } + + return switchoverConfig +} + +func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { + // If not initialized will do nothing + if s == nil { + return + } + + s.CacheWarmerQueries.cleanupUnusedFeatureFlags(routerCfg) +} + +func (c *CacheWarmerQueries) getOrCreateBuffer(featureFlagKey string) *ringBuffer { + // If not initialized will return nil + if c == nil { + return nil + } + + c.mu.RLock() + buf, exists := c.queriesForFeatureFlag[featureFlagKey] + c.mu.RUnlock() + + if exists { + return buf + } + + c.mu.Lock() + defer c.mu.Unlock() + + // Double-check in case another goroutine created it while we were waiting for the write lock + buf, exists = c.queriesForFeatureFlag[featureFlagKey] + if exists { + return buf + } + + buf = newRingBuffer(c.maxSize) + c.queriesForFeatureFlag[featureFlagKey] = buf + return buf +} + +func (c *CacheWarmerQueries) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { + if c == nil { + return + } + + c.mu.Lock() + defer c.mu.Unlock() + + ffNames := make(map[string]struct{}) + for ffName, _ := range routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName { + ffNames[ffName] = struct{}{} + } + + for ffName, _ := range c.queriesForFeatureFlag { + if _, exists := ffNames[ffName]; !exists { + delete(c.queriesForFeatureFlag, ffName) + } + } +} + +type ringBuffer struct { + mu sync.Mutex + ring []string // Ring buffer to track queries + head int // Index where next item will be written + maxSize int // Maximum size of the ring buffer +} + +func newRingBuffer(maxSize int) *ringBuffer { + return &ringBuffer{ + ring: make([]string, 0, maxSize), + head: 0, + maxSize: maxSize, + } +} + +func (rb *ringBuffer) Add(query string) { + rb.mu.Lock() + defer rb.mu.Unlock() + + // If ring buffer is not yet full, append to it + if len(rb.ring) < rb.maxSize { + rb.ring = append(rb.ring, query) + return + } + + // Add new entry at head position + rb.ring[rb.head] = query + + // Move head to next position (wrap around) + rb.head = (rb.head + 1) % rb.maxSize +} + +func (rb *ringBuffer) Snapshot() []string { + rb.mu.Lock() + defer rb.mu.Unlock() + + snapshot := make([]string, len(rb.ring)) + copy(snapshot, rb.ring) + return snapshot +} diff --git a/router/core/router.go b/router/core/router.go index 3154a1f217..384a8ed9f8 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -90,6 +90,7 @@ type ( proxy ProxyFunc disableUsageTracking bool usage UsageTracker + switchoverConfig *SwitchoverConfig } UsageTracker interface { @@ -596,12 +597,7 @@ func NewRouter(opts ...Option) (*Router, error) { // newGraphServer creates a new server. func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error { - var plans map[uint64]string - if r.httpServer.graphServer != nil { - plans = r.httpServer.graphServer.operationPlanner.getPlans() - } - - server, err := newGraphServer(ctx, r, cfg, r.proxy, plans) + server, err := newGraphServer(ctx, r, cfg, r.proxy, r.switchoverConfig) if err != nil { r.logger.Error("Failed to create graph server. Keeping the old server", zap.Error(err)) return err @@ -609,6 +605,9 @@ func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error r.httpServer.SwapGraphServer(ctx, server) + // Cleanup feature flags + r.switchoverConfig.CleanupFeatureFlags(cfg) + return nil } @@ -729,56 +728,6 @@ func (r *Router) BaseURL() string { return r.baseURL } -// NewServer prepares a new server instance but does not start it. The method should only be used when you want to bootstrap -// the server manually otherwise you can use Router.Start(). You're responsible for setting health checks status to ready with Server.HealthChecks(). -// The server can be shutdown with Router.Shutdown(). Use core.WithExecutionConfig to pass the initial config otherwise the Router will -// try to fetch the config from the control plane. You can swap the router config by using Router.newGraphServer(). -func (r *Router) NewServer(ctx context.Context) (Server, error) { - if r.shutdown.Load() { - return nil, fmt.Errorf("router is shutdown. Create a new instance with router.NewRouter()") - } - - if err := r.bootstrap(ctx); err != nil { - return nil, fmt.Errorf("failed to bootstrap application: %w", err) - } - - r.httpServer = newServer(&httpServerOptions{ - addr: r.listenAddr, - logger: r.logger, - tlsConfig: r.tlsConfig, - tlsServerConfig: r.tlsServerConfig, - healthcheck: r.healthcheck, - baseURL: r.baseURL, - maxHeaderBytes: int(r.routerTrafficConfig.MaxHeaderBytes.Uint64()), - livenessCheckPath: r.livenessCheckPath, - readinessCheckPath: r.readinessCheckPath, - healthCheckPath: r.healthCheckPath, - }) - - // Start the server with the static config without polling - if r.staticExecutionConfig != nil { - r.logger.Info("Static execution config provided. Polling is disabled. Updating execution config is only possible by providing a config.") - return r.httpServer, r.newServer(ctx, r.staticExecutionConfig) - } - - // when no static config is provided and no poller is configured, we can't start the server - if r.configPoller == nil { - return nil, fmt.Errorf("config fetcher not provided. Please provide a static execution config instead") - } - - cfg, err := r.configPoller.GetRouterConfig(ctx) - if err != nil { - return nil, fmt.Errorf("failed to get initial execution config: %w", err) - } - - if err := r.newServer(ctx, cfg.Config); err != nil { - r.logger.Error("Failed to start server with initial config", zap.Error(err)) - return nil, err - } - - return r.httpServer, nil -} - // bootstrap initializes the Router. It is called by Start() and NewServer(). // It should only be called once for a Router instance. func (r *Router) bootstrap(ctx context.Context) error { @@ -1225,6 +1174,8 @@ func (r *Router) Start(ctx context.Context) error { healthCheckPath: r.healthCheckPath, }) + r.switchoverConfig = NewSwitchoverConfig(&r.Config) + // Start the server with the static config without polling if r.staticExecutionConfig != nil { diff --git a/router/core/router_config.go b/router/core/router_config.go index 319216a18a..bfbe46924e 100644 --- a/router/core/router_config.go +++ b/router/core/router_config.go @@ -314,6 +314,8 @@ func (c *Config) Usage() map[string]any { if c.cacheWarmup != nil && c.cacheWarmup.Enabled { if c.cacheWarmup.Source.Filesystem != nil { usage["cache_warmup_source"] = "filesystem" + } else if c.cacheWarmup.Source.InMemorySwitchover { + usage["cache_warmup_source"] = "in_memory_switchover" } else { usage["cache_warmup_source"] = "cdn" } diff --git a/router/pkg/config/config.go b/router/pkg/config/config.go index 4e430627c0..21affe31f7 100644 --- a/router/pkg/config/config.go +++ b/router/pkg/config/config.go @@ -360,25 +360,25 @@ func (r *ResponseHeaderRule) GetMatching() string { } type EngineDebugConfiguration struct { - PrintOperationTransformations bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_TRANSFORMATIONS" yaml:"print_operation_transformations"` - PrintOperationEnableASTRefs bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_ENABLE_AST_REFS" yaml:"print_operation_enable_ast_refs"` - PrintPlanningPaths bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_PLANNING_PATHS" yaml:"print_planning_paths"` - PrintQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_QUERY_PLANS" yaml:"print_query_plans"` - PrintIntermediateQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_INTERMEDIATE_QUERY_PLANS" yaml:"print_intermediate_query_plans"` - PrintNodeSuggestions bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_NODE_SUGGESTIONS" yaml:"print_node_suggestions"` - ConfigurationVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_CONFIGURATION_VISITOR" yaml:"configuration_visitor"` - PlanningVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_PLANNING_VISITOR" yaml:"planning_visitor"` - DatasourceVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_DATASOURCE_VISITOR" yaml:"datasource_visitor"` - ReportWebSocketConnections bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_WEBSOCKET_CONNECTIONS" yaml:"report_websocket_connections"` - ReportMemoryUsage bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_MEMORY_USAGE" yaml:"report_memory_usage"` - EnableResolverDebugging bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_RESOLVER_DEBUGGING" yaml:"enable_resolver_debugging"` + PrintOperationTransformations bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_TRANSFORMATIONS" yaml:"print_operation_transformations"` + PrintOperationEnableASTRefs bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_ENABLE_AST_REFS" yaml:"print_operation_enable_ast_refs"` + PrintPlanningPaths bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_PLANNING_PATHS" yaml:"print_planning_paths"` + PrintQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_QUERY_PLANS" yaml:"print_query_plans"` + PrintIntermediateQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_INTERMEDIATE_QUERY_PLANS" yaml:"print_intermediate_query_plans"` + PrintNodeSuggestions bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_NODE_SUGGESTIONS" yaml:"print_node_suggestions"` + ConfigurationVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_CONFIGURATION_VISITOR" yaml:"configuration_visitor"` + PlanningVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_PLANNING_VISITOR" yaml:"planning_visitor"` + DatasourceVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_DATASOURCE_VISITOR" yaml:"datasource_visitor"` + ReportWebSocketConnections bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_WEBSOCKET_CONNECTIONS" yaml:"report_websocket_connections"` + ReportMemoryUsage bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_MEMORY_USAGE" yaml:"report_memory_usage"` + EnableResolverDebugging bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_RESOLVER_DEBUGGING" yaml:"enable_resolver_debugging"` // EnablePersistedOperationsCacheResponseHeader is deprecated, use EnableCacheResponseHeaders instead. EnablePersistedOperationsCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_PERSISTED_OPERATIONS_CACHE_RESPONSE_HEADER" yaml:"enable_persisted_operations_cache_response_header"` // EnableNormalizationCacheResponseHeader is deprecated, use EnableCacheResponseHeaders instead. - EnableNormalizationCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_NORMALIZATION_CACHE_RESPONSE_HEADER" yaml:"enable_normalization_cache_response_header"` - EnableCacheResponseHeaders bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_CACHE_RESPONSE_HEADERS" yaml:"enable_cache_response_headers"` - AlwaysIncludeQueryPlan bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_INCLUDE_QUERY_PLAN" yaml:"always_include_query_plan"` - AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"` + EnableNormalizationCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_NORMALIZATION_CACHE_RESPONSE_HEADER" yaml:"enable_normalization_cache_response_header"` + EnableCacheResponseHeaders bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_CACHE_RESPONSE_HEADERS" yaml:"enable_cache_response_headers"` + AlwaysIncludeQueryPlan bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_INCLUDE_QUERY_PLAN" yaml:"always_include_query_plan"` + AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"` } type EngineExecutionConfiguration struct { @@ -971,13 +971,19 @@ type ClientHeader struct { } type CacheWarmupSource struct { - Filesystem *CacheWarmupFileSystemSource `yaml:"filesystem,omitempty"` + Filesystem *CacheWarmupFileSystemSource `yaml:"filesystem,omitempty"` + InMemorySwitchover CacheWarmupInMemorySwitchover `yaml:"in_memory_switchover,omitempty"` } type CacheWarmupFileSystemSource struct { Path string `yaml:"path" env:"CACHE_WARMUP_SOURCE_FILESYSTEM_PATH"` } +type CacheWarmupInMemorySwitchover struct { + Enabled bool `yaml:"enabled" envDefault:"false" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_ENABLED"` + MaxEntries int `yaml:"max_entries" envDefault:"100" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_MAX_ENTRIES"` +} + type CacheWarmupCDNSource struct{} type CacheWarmupConfiguration struct { From 2f89643e95e07d85cc0c53778338fb238fbefdc4 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 01:32:25 +0530 Subject: [PATCH 04/52] fix: updates --- router/core/cache_warmup_plans.go | 24 +++---- router/core/graph_server.go | 6 +- router/core/operation_planner.go | 40 +++++++----- router/core/restart_switchover_config.go | 81 ++++++------------------ router/core/router.go | 2 +- router/go.mod | 4 +- router/go.sum | 8 +-- 7 files changed, 68 insertions(+), 97 deletions(-) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 0a182c1421..0790e2d9f8 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -2,6 +2,7 @@ package core import ( "context" + "github.com/dgraph-io/ristretto/v2" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" "go.uber.org/zap" ) @@ -9,21 +10,20 @@ import ( var _ CacheWarmupSource = (*PlanSource)(nil) type PlanSource struct { - queries *ringBuffer + queries []*nodev1.Operation } -func NewPlanSource(switchoverCacheWarmerQueries *ringBuffer) *PlanSource { - return &PlanSource{queries: switchoverCacheWarmerQueries} -} - -func (c *PlanSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { - var items []*nodev1.Operation - - for _, query := range c.queries.Snapshot() { +func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWithMetaData]) *PlanSource { + items := make([]*nodev1.Operation, 0) + switchoverCacheWarmerQueries.Iter(func(k any, v *planWithMetaData) (stop bool) { items = append(items, &nodev1.Operation{ - Request: &nodev1.OperationRequest{Query: query}, + Request: &nodev1.OperationRequest{Query: v.content}, }) - } + return false + }) + return &PlanSource{queries: items} +} - return items, nil +func (c *PlanSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { + return c.queries, nil } diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 14d14f0a4b..370cde9439 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1301,8 +1301,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - cacheWarmerQueries := opts.SwitchoverConfig.CacheWarmerQueries.getOrCreateBuffer(opts.FeatureFlagName) - operationPlanner := NewOperationPlanner(executor, gm.planCache, cacheWarmerQueries) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.CacheWarmerQueries != nil) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { @@ -1357,7 +1356,8 @@ func (s *graphServer) buildGraphMux( RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) } else if s.Config.cacheWarmup.Source.InMemorySwitchover.Enabled { - warmupConfig.Source = NewPlanSource(cacheWarmerQueries) + warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.CacheWarmerQueries.getPlanCacheForFF(opts.FeatureFlagName)) + opts.SwitchoverConfig.CacheWarmerQueries.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) } else { cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) if err != nil { diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index 041714e4a4..4c6b3e2312 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -21,14 +21,19 @@ type planWithMetaData struct { operationDocument, schemaDocument *ast.Document typeFieldUsageInfo []*graphqlschemausage.TypeFieldUsageInfo argumentUsageInfo []*graphqlmetricsv1.ArgumentUsageInfo + content string } type OperationPlanner struct { - sf singleflight.Group - planCache ExecutionPlanCache[uint64, *planWithMetaData] - executor *Executor - trackUsageInfo bool - cacheWarmerQueries *ringBuffer + sf singleflight.Group + planCache ExecutionPlanCache[uint64, *planWithMetaData] + executor *Executor + trackUsageInfo bool + storeContent bool +} + +type operationPlannerOpts struct { + storeContent bool } type ExecutionPlanCache[K any, V any] interface { @@ -36,20 +41,22 @@ type ExecutionPlanCache[K any, V any] interface { Get(key K) (V, bool) // Set the value in the cache with a cost. The cost depends on the cache implementation Set(key K, value V, cost int64) bool + // Iterate over all items in the cache (non-deterministic) + Iter(cb func(k any, v V) (stop bool)) // Close the cache and free resources Close() } -func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64, *planWithMetaData], cacheWarmerQueries *ringBuffer) *OperationPlanner { +func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64, *planWithMetaData], storeContent bool) *OperationPlanner { return &OperationPlanner{ - planCache: planCache, - executor: executor, - trackUsageInfo: executor.TrackUsageInfo, - cacheWarmerQueries: cacheWarmerQueries, + planCache: planCache, + executor: executor, + trackUsageInfo: executor.TrackUsageInfo, + storeContent: storeContent, } } -func (p *OperationPlanner) preparePlan(ctx *operationContext) (*planWithMetaData, error) { +func (p *OperationPlanner) preparePlan(ctx *operationContext, opts operationPlannerOpts) (*planWithMetaData, error) { doc, report := astparser.ParseGraphqlDocumentString(ctx.content) if report.HasErrors() { return nil, &reportError{report: &report} @@ -83,6 +90,10 @@ func (p *OperationPlanner) preparePlan(ctx *operationContext) (*planWithMetaData schemaDocument: p.executor.RouterSchema, } + if opts.storeContent { + out.content = ctx.Content() + } + if p.trackUsageInfo { out.typeFieldUsageInfo = graphqlschemausage.GetTypeFieldUsageInfo(preparedPlan) out.argumentUsageInfo, err = graphqlschemausage.GetArgumentUsageInfo(&doc, p.executor.RouterSchema, ctx.variables, preparedPlan, ctx.remapVariables) @@ -108,7 +119,7 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions skipCache := options.TraceOptions.Enable || options.ExecutionOptions.IncludeQueryPlanInResponse if skipCache { - prepared, err := p.preparePlan(opContext) + prepared, err := p.preparePlan(opContext, operationPlannerOpts{storeContent: false}) if err != nil { return err } @@ -137,14 +148,11 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions // this ensures that we only prepare the plan once for this operation ID operationIDStr := strconv.FormatUint(operationID, 10) sharedPreparedPlan, err, _ := p.sf.Do(operationIDStr, func() (interface{}, error) { - prepared, err := p.preparePlan(opContext) + prepared, err := p.preparePlan(opContext, operationPlannerOpts{storeContent: p.storeContent}) if err != nil { return nil, err } p.planCache.Set(operationID, prepared, 1) - if p.cacheWarmerQueries != nil { - p.cacheWarmerQueries.Add(opContext.content) - } return prepared, nil }) if err != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 72451e5b6c..081f76cce0 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -1,6 +1,7 @@ package core import ( + "github.com/dgraph-io/ristretto/v2" "sync" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" @@ -11,10 +12,11 @@ type SwitchoverConfig struct { CacheWarmerQueries *CacheWarmerQueries } +type planCache *ristretto.Cache[uint64, *planWithMetaData] + type CacheWarmerQueries struct { - maxSize int // Maximum size of the ring buffer per feature flag mu sync.RWMutex - queriesForFeatureFlag map[string]*ringBuffer // Map of feature flag key to ring buffer ("" is default) + queriesForFeatureFlag map[string]planCache } func NewSwitchoverConfig(config *Config) *SwitchoverConfig { @@ -24,8 +26,7 @@ func NewSwitchoverConfig(config *Config) *SwitchoverConfig { if inMemorySwitchoverCacheWarmerEnabled { switchoverConfig.CacheWarmerQueries = &CacheWarmerQueries{ - maxSize: config.cacheWarmup.Source.InMemorySwitchover.MaxEntries, - queriesForFeatureFlag: make(map[string]*ringBuffer), + queriesForFeatureFlag: make(map[string]planCache), } } @@ -33,40 +34,41 @@ func NewSwitchoverConfig(config *Config) *SwitchoverConfig { } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { - // If not initialized will do nothing - if s == nil { - return - } - s.CacheWarmerQueries.cleanupUnusedFeatureFlags(routerCfg) } -func (c *CacheWarmerQueries) getOrCreateBuffer(featureFlagKey string) *ringBuffer { +func (c *CacheWarmerQueries) getPlanCacheForFF(featureFlagKey string) planCache { + c.mu.RLock() + warmer, _ := c.queriesForFeatureFlag[featureFlagKey] + c.mu.RUnlock() + return warmer +} + +func (c *CacheWarmerQueries) setPlanCacheForFF(featureFlagKey string, cache planCache) bool { // If not initialized will return nil - if c == nil { - return nil + if c == nil || cache == nil { + return false } c.mu.RLock() - buf, exists := c.queriesForFeatureFlag[featureFlagKey] + _, exists := c.queriesForFeatureFlag[featureFlagKey] c.mu.RUnlock() if exists { - return buf + return true } c.mu.Lock() defer c.mu.Unlock() // Double-check in case another goroutine created it while we were waiting for the write lock - buf, exists = c.queriesForFeatureFlag[featureFlagKey] + _, exists = c.queriesForFeatureFlag[featureFlagKey] if exists { - return buf + return true } - buf = newRingBuffer(c.maxSize) - c.queriesForFeatureFlag[featureFlagKey] = buf - return buf + c.queriesForFeatureFlag[featureFlagKey] = cache + return true } func (c *CacheWarmerQueries) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { @@ -88,44 +90,3 @@ func (c *CacheWarmerQueries) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterC } } } - -type ringBuffer struct { - mu sync.Mutex - ring []string // Ring buffer to track queries - head int // Index where next item will be written - maxSize int // Maximum size of the ring buffer -} - -func newRingBuffer(maxSize int) *ringBuffer { - return &ringBuffer{ - ring: make([]string, 0, maxSize), - head: 0, - maxSize: maxSize, - } -} - -func (rb *ringBuffer) Add(query string) { - rb.mu.Lock() - defer rb.mu.Unlock() - - // If ring buffer is not yet full, append to it - if len(rb.ring) < rb.maxSize { - rb.ring = append(rb.ring, query) - return - } - - // Add new entry at head position - rb.ring[rb.head] = query - - // Move head to next position (wrap around) - rb.head = (rb.head + 1) % rb.maxSize -} - -func (rb *ringBuffer) Snapshot() []string { - rb.mu.Lock() - defer rb.mu.Unlock() - - snapshot := make([]string, len(rb.ring)) - copy(snapshot, rb.ring) - return snapshot -} diff --git a/router/core/router.go b/router/core/router.go index 384a8ed9f8..9058c3d1ee 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -605,7 +605,7 @@ func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error r.httpServer.SwapGraphServer(ctx, server) - // Cleanup feature flags + // Cleanup any unused feature flags r.switchoverConfig.CleanupFeatureFlags(cfg) return nil diff --git a/router/go.mod b/router/go.mod index bde71925bf..2619abd0a0 100644 --- a/router/go.mod +++ b/router/go.mod @@ -63,7 +63,7 @@ require ( github.com/alicebob/miniredis/v2 v2.34.0 github.com/caarlos0/env/v11 v11.3.1 github.com/cep21/circuit/v4 v4.0.0 - github.com/dgraph-io/ristretto/v2 v2.1.0 + github.com/dgraph-io/ristretto/v2 v2.0.0 github.com/expr-lang/expr v1.17.7 github.com/goccy/go-json v0.10.3 github.com/google/go-containerregistry v0.20.3 @@ -195,3 +195,5 @@ replace ( // Use what is best for your personal workflow. See CONTRIBUTING.md for more information //replace github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2 + +replace github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d diff --git a/router/go.sum b/router/go.sum index bf848f1712..80f9fb4dd5 100644 --- a/router/go.sum +++ b/router/go.sum @@ -54,10 +54,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= -github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= @@ -324,6 +322,8 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242 h1:0ieQmRxYz0nbJEbaaA4Cx2RPcxlomhQ8KI31uuevWx0= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= +github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d h1:FlfUZzJbnc8+bgSKJ2jCqozn9CS08ToZe/JJxh4DPGo= +github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= From cf6e9df3828a05084c0e8f0997f5eb690948ef5d Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 01:50:42 +0530 Subject: [PATCH 05/52] fix: updates --- router/core/cache_warmup_plans.go | 15 ++++-- router/core/graph_server.go | 19 ++++---- router/core/restart_switchover_config.go | 58 ++++++++++-------------- router/core/router.go | 2 +- router/pkg/config/config.go | 36 +++++++-------- 5 files changed, 62 insertions(+), 68 deletions(-) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 0790e2d9f8..0053b1f45b 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -14,13 +14,18 @@ type PlanSource struct { } func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWithMetaData]) *PlanSource { + // Extract the items on creation so that the previous planCache can be garbage collected as we won't hold a reference items := make([]*nodev1.Operation, 0) - switchoverCacheWarmerQueries.Iter(func(k any, v *planWithMetaData) (stop bool) { - items = append(items, &nodev1.Operation{ - Request: &nodev1.OperationRequest{Query: v.content}, + + if switchoverCacheWarmerQueries != nil { + switchoverCacheWarmerQueries.Iter(func(k any, v *planWithMetaData) (stop bool) { + items = append(items, &nodev1.Operation{ + Request: &nodev1.OperationRequest{Query: v.content}, + }) + return false }) - return false - }) + } + return &PlanSource{queries: items} } diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 370cde9439..d5649e93f6 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -523,13 +523,12 @@ type graphMux struct { validationCache *ristretto.Cache[uint64, bool] operationHashCache *ristretto.Cache[uint64, string] - accessLogsFileLogger *logging.BufferedLogger - metricStore rmetric.Store - prometheusCacheMetrics *rmetric.CacheMetrics - otelCacheMetrics *rmetric.CacheMetrics - streamMetricStore rmetric.StreamMetricStore - prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter -} + accessLogsFileLogger *logging.BufferedLogger + metricStore rmetric.Store + prometheusCacheMetrics *rmetric.CacheMetrics + otelCacheMetrics *rmetric.CacheMetrics + streamMetricStore rmetric.StreamMetricStore + prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter} // buildOperationCaches creates the caches for the graph mux. // The caches are created based on the engine configuration. @@ -1301,7 +1300,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.CacheWarmerQueries != nil) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache != nil) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { @@ -1356,8 +1355,8 @@ func (s *graphServer) buildGraphMux( RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) } else if s.Config.cacheWarmup.Source.InMemorySwitchover.Enabled { - warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.CacheWarmerQueries.getPlanCacheForFF(opts.FeatureFlagName)) - opts.SwitchoverConfig.CacheWarmerQueries.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) + warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) + opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) } else { cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) if err != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 081f76cce0..e935b3e4be 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -7,25 +7,28 @@ import ( nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" ) -// This file describes any configuration which should persist across router restarts +type planCache *ristretto.Cache[uint64, *planWithMetaData] + +// This file describes any configuration which should persist or be shared across router restarts type SwitchoverConfig struct { - CacheWarmerQueries *CacheWarmerQueries + inMemorySwitchOverCache *InMemorySwitchOverCache } -type planCache *ristretto.Cache[uint64, *planWithMetaData] - -type CacheWarmerQueries struct { +type InMemorySwitchOverCache struct { + enabled bool mu sync.RWMutex queriesForFeatureFlag map[string]planCache } func NewSwitchoverConfig(config *Config) *SwitchoverConfig { - switchoverConfig := &SwitchoverConfig{} - - inMemorySwitchoverCacheWarmerEnabled := config.cacheWarmup != nil && config.cacheWarmup.Enabled && config.cacheWarmup.Source.InMemorySwitchover.Enabled + switchoverConfig := &SwitchoverConfig{ + inMemorySwitchOverCache: &InMemorySwitchOverCache{ + enabled: config.cacheWarmup.Enabled && config.cacheWarmup.Source.InMemorySwitchover.Enabled, + }, + } - if inMemorySwitchoverCacheWarmerEnabled { - switchoverConfig.CacheWarmerQueries = &CacheWarmerQueries{ + if switchoverConfig.inMemorySwitchOverCache.enabled { + switchoverConfig.inMemorySwitchOverCache = &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]planCache), } } @@ -34,44 +37,33 @@ func NewSwitchoverConfig(config *Config) *SwitchoverConfig { } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { - s.CacheWarmerQueries.cleanupUnusedFeatureFlags(routerCfg) + s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } -func (c *CacheWarmerQueries) getPlanCacheForFF(featureFlagKey string) planCache { +func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) planCache { + if !c.enabled { + return nil + } + c.mu.RLock() warmer, _ := c.queriesForFeatureFlag[featureFlagKey] c.mu.RUnlock() return warmer } -func (c *CacheWarmerQueries) setPlanCacheForFF(featureFlagKey string, cache planCache) bool { - // If not initialized will return nil - if c == nil || cache == nil { - return false - } - - c.mu.RLock() - _, exists := c.queriesForFeatureFlag[featureFlagKey] - c.mu.RUnlock() - - if exists { - return true +func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { + if !c.enabled || cache == nil { + return } c.mu.Lock() defer c.mu.Unlock() - - // Double-check in case another goroutine created it while we were waiting for the write lock - _, exists = c.queriesForFeatureFlag[featureFlagKey] - if exists { - return true - } - c.queriesForFeatureFlag[featureFlagKey] = cache - return true + + return } -func (c *CacheWarmerQueries) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { +func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { if c == nil { return } diff --git a/router/core/router.go b/router/core/router.go index 9058c3d1ee..9871b7755e 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -605,7 +605,7 @@ func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error r.httpServer.SwapGraphServer(ctx, server) - // Cleanup any unused feature flags + // Cleanup any unused feature flags in case a feature flag was removed r.switchoverConfig.CleanupFeatureFlags(cfg) return nil diff --git a/router/pkg/config/config.go b/router/pkg/config/config.go index 21affe31f7..f57b1cf05c 100644 --- a/router/pkg/config/config.go +++ b/router/pkg/config/config.go @@ -360,26 +360,25 @@ func (r *ResponseHeaderRule) GetMatching() string { } type EngineDebugConfiguration struct { - PrintOperationTransformations bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_TRANSFORMATIONS" yaml:"print_operation_transformations"` - PrintOperationEnableASTRefs bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_ENABLE_AST_REFS" yaml:"print_operation_enable_ast_refs"` - PrintPlanningPaths bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_PLANNING_PATHS" yaml:"print_planning_paths"` - PrintQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_QUERY_PLANS" yaml:"print_query_plans"` - PrintIntermediateQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_INTERMEDIATE_QUERY_PLANS" yaml:"print_intermediate_query_plans"` - PrintNodeSuggestions bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_NODE_SUGGESTIONS" yaml:"print_node_suggestions"` - ConfigurationVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_CONFIGURATION_VISITOR" yaml:"configuration_visitor"` - PlanningVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_PLANNING_VISITOR" yaml:"planning_visitor"` - DatasourceVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_DATASOURCE_VISITOR" yaml:"datasource_visitor"` - ReportWebSocketConnections bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_WEBSOCKET_CONNECTIONS" yaml:"report_websocket_connections"` - ReportMemoryUsage bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_MEMORY_USAGE" yaml:"report_memory_usage"` - EnableResolverDebugging bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_RESOLVER_DEBUGGING" yaml:"enable_resolver_debugging"` + PrintOperationTransformations bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_TRANSFORMATIONS" yaml:"print_operation_transformations"` + PrintOperationEnableASTRefs bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_OPERATION_ENABLE_AST_REFS" yaml:"print_operation_enable_ast_refs"` + PrintPlanningPaths bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_PLANNING_PATHS" yaml:"print_planning_paths"` + PrintQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_QUERY_PLANS" yaml:"print_query_plans"` + PrintIntermediateQueryPlans bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_INTERMEDIATE_QUERY_PLANS" yaml:"print_intermediate_query_plans"` + PrintNodeSuggestions bool `envDefault:"false" env:"ENGINE_DEBUG_PRINT_NODE_SUGGESTIONS" yaml:"print_node_suggestions"` + ConfigurationVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_CONFIGURATION_VISITOR" yaml:"configuration_visitor"` + PlanningVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_PLANNING_VISITOR" yaml:"planning_visitor"` + DatasourceVisitor bool `envDefault:"false" env:"ENGINE_DEBUG_DATASOURCE_VISITOR" yaml:"datasource_visitor"` + ReportWebSocketConnections bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_WEBSOCKET_CONNECTIONS" yaml:"report_websocket_connections"` + ReportMemoryUsage bool `envDefault:"false" env:"ENGINE_DEBUG_REPORT_MEMORY_USAGE" yaml:"report_memory_usage"` + EnableResolverDebugging bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_RESOLVER_DEBUGGING" yaml:"enable_resolver_debugging"` // EnablePersistedOperationsCacheResponseHeader is deprecated, use EnableCacheResponseHeaders instead. EnablePersistedOperationsCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_PERSISTED_OPERATIONS_CACHE_RESPONSE_HEADER" yaml:"enable_persisted_operations_cache_response_header"` // EnableNormalizationCacheResponseHeader is deprecated, use EnableCacheResponseHeaders instead. - EnableNormalizationCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_NORMALIZATION_CACHE_RESPONSE_HEADER" yaml:"enable_normalization_cache_response_header"` - EnableCacheResponseHeaders bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_CACHE_RESPONSE_HEADERS" yaml:"enable_cache_response_headers"` - AlwaysIncludeQueryPlan bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_INCLUDE_QUERY_PLAN" yaml:"always_include_query_plan"` - AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"` -} + EnableNormalizationCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_NORMALIZATION_CACHE_RESPONSE_HEADER" yaml:"enable_normalization_cache_response_header"` + EnableCacheResponseHeaders bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_CACHE_RESPONSE_HEADERS" yaml:"enable_cache_response_headers"` + AlwaysIncludeQueryPlan bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_INCLUDE_QUERY_PLAN" yaml:"always_include_query_plan"` + AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"`} type EngineExecutionConfiguration struct { Debug EngineDebugConfiguration `yaml:"debug"` @@ -980,8 +979,7 @@ type CacheWarmupFileSystemSource struct { } type CacheWarmupInMemorySwitchover struct { - Enabled bool `yaml:"enabled" envDefault:"false" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_ENABLED"` - MaxEntries int `yaml:"max_entries" envDefault:"100" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_MAX_ENTRIES"` + Enabled bool `yaml:"enabled" envDefault:"false" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_ENABLED"` } type CacheWarmupCDNSource struct{} From 0d2e2db522b647ad777ad2adfca09d1564d582d4 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 01:51:16 +0530 Subject: [PATCH 06/52] fix: updates --- router/pkg/config/config.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router/pkg/config/config.go b/router/pkg/config/config.go index f57b1cf05c..30fab1ad50 100644 --- a/router/pkg/config/config.go +++ b/router/pkg/config/config.go @@ -378,7 +378,8 @@ type EngineDebugConfiguration struct { EnableNormalizationCacheResponseHeader bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_NORMALIZATION_CACHE_RESPONSE_HEADER" yaml:"enable_normalization_cache_response_header"` EnableCacheResponseHeaders bool `envDefault:"false" env:"ENGINE_DEBUG_ENABLE_CACHE_RESPONSE_HEADERS" yaml:"enable_cache_response_headers"` AlwaysIncludeQueryPlan bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_INCLUDE_QUERY_PLAN" yaml:"always_include_query_plan"` - AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"`} + AlwaysSkipLoader bool `envDefault:"false" env:"ENGINE_DEBUG_ALWAYS_SKIP_LOADER" yaml:"always_skip_loader"` +} type EngineExecutionConfiguration struct { Debug EngineDebugConfiguration `yaml:"debug"` From 52aa4741a9b02dd40881ca16e6737dbc659a5975 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 01:52:14 +0530 Subject: [PATCH 07/52] fix: updates --- router/core/graph_server.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index d5649e93f6..82b9ba25bf 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -528,7 +528,8 @@ type graphMux struct { prometheusCacheMetrics *rmetric.CacheMetrics otelCacheMetrics *rmetric.CacheMetrics streamMetricStore rmetric.StreamMetricStore - prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter} + prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter +} // buildOperationCaches creates the caches for the graph mux. // The caches are created based on the engine configuration. From 8cd21fec13f883307f9a095dd0aa715d6548dab2 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 01:52:50 +0530 Subject: [PATCH 08/52] fix: updates --- router/core/graph_server.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 82b9ba25bf..1d4e932319 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -523,12 +523,12 @@ type graphMux struct { validationCache *ristretto.Cache[uint64, bool] operationHashCache *ristretto.Cache[uint64, string] - accessLogsFileLogger *logging.BufferedLogger - metricStore rmetric.Store - prometheusCacheMetrics *rmetric.CacheMetrics - otelCacheMetrics *rmetric.CacheMetrics - streamMetricStore rmetric.StreamMetricStore - prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter + accessLogsFileLogger *logging.BufferedLogger + metricStore rmetric.Store + prometheusCacheMetrics *rmetric.CacheMetrics + otelCacheMetrics *rmetric.CacheMetrics + streamMetricStore rmetric.StreamMetricStore + prometheusMetricsExporter *graphqlmetrics.PrometheusMetricsExporter } // buildOperationCaches creates the caches for the graph mux. @@ -1301,7 +1301,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache != nil) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.enabled) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { From 822a4a4b132988d1ea72c233a674023bcc9c2dc5 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 02:25:38 +0530 Subject: [PATCH 09/52] fix: config updates --- router/core/graph_server.go | 2 ++ router/core/restart_switchover_config.go | 33 +++++++++---------- router/core/router_config.go | 2 +- router/pkg/config/config.schema.json | 14 ++++++++ .../pkg/config/testdata/config_defaults.json | 5 ++- router/pkg/config/testdata/config_full.json | 5 ++- 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 1d4e932319..81e8685d8c 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1356,6 +1356,8 @@ func (s *graphServer) buildGraphMux( RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) } else if s.Config.cacheWarmup.Source.InMemorySwitchover.Enabled { + // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries + // and reset the plan cache to the new plan cache for this start afterwords warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) } else { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index e935b3e4be..78662b4d22 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -9,17 +9,11 @@ import ( type planCache *ristretto.Cache[uint64, *planWithMetaData] -// This file describes any configuration which should persist or be shared across router restarts +// SwitchoverConfig This file describes any configuration which should persist or be shared across router restarts type SwitchoverConfig struct { inMemorySwitchOverCache *InMemorySwitchOverCache } -type InMemorySwitchOverCache struct { - enabled bool - mu sync.RWMutex - queriesForFeatureFlag map[string]planCache -} - func NewSwitchoverConfig(config *Config) *SwitchoverConfig { switchoverConfig := &SwitchoverConfig{ inMemorySwitchOverCache: &InMemorySwitchOverCache{ @@ -28,9 +22,7 @@ func NewSwitchoverConfig(config *Config) *SwitchoverConfig { } if switchoverConfig.inMemorySwitchOverCache.enabled { - switchoverConfig.inMemorySwitchOverCache = &InMemorySwitchOverCache{ - queriesForFeatureFlag: make(map[string]planCache), - } + switchoverConfig.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) } return switchoverConfig @@ -40,18 +32,23 @@ func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } +type InMemorySwitchOverCache struct { + enabled bool + mu sync.RWMutex + queriesForFeatureFlag map[string]planCache +} + func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) planCache { if !c.enabled { return nil } c.mu.RLock() - warmer, _ := c.queriesForFeatureFlag[featureFlagKey] - c.mu.RUnlock() - return warmer + defer c.mu.RUnlock() + return c.queriesForFeatureFlag[featureFlagKey] } -func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { +func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache *ristretto.Cache[uint64, *planWithMetaData]) { if !c.enabled || cache == nil { return } @@ -59,12 +56,14 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache c.mu.Lock() defer c.mu.Unlock() c.queriesForFeatureFlag[featureFlagKey] = cache - - return } func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { - if c == nil { + if !c.enabled { + return + } + + if routerCfg.FeatureFlagConfigs == nil { return } diff --git a/router/core/router_config.go b/router/core/router_config.go index bfbe46924e..e906b2e9d0 100644 --- a/router/core/router_config.go +++ b/router/core/router_config.go @@ -314,7 +314,7 @@ func (c *Config) Usage() map[string]any { if c.cacheWarmup != nil && c.cacheWarmup.Enabled { if c.cacheWarmup.Source.Filesystem != nil { usage["cache_warmup_source"] = "filesystem" - } else if c.cacheWarmup.Source.InMemorySwitchover { + } else if c.cacheWarmup.Source.InMemorySwitchover.Enabled { usage["cache_warmup_source"] = "in_memory_switchover" } else { usage["cache_warmup_source"] = "cdn" diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json index 0b5fc698c3..9d2e69803a 100644 --- a/router/pkg/config/config.schema.json +++ b/router/pkg/config/config.schema.json @@ -2387,11 +2387,25 @@ "format": "file-path" } } + }, + "in_memory_switchover": { + "type": "object", + "description": "The in memory switchover which reuses query plans for subsequent starts.", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "description": "Is in memory switchover enabled" + } + } } }, "oneOf": [ { "required": ["filesystem"] + }, + { + "required": ["in_memory_switchover"] } ] }, diff --git a/router/pkg/config/testdata/config_defaults.json b/router/pkg/config/testdata/config_defaults.json index ce91d417e7..44e4611488 100644 --- a/router/pkg/config/testdata/config_defaults.json +++ b/router/pkg/config/testdata/config_defaults.json @@ -311,7 +311,10 @@ "CacheWarmup": { "Enabled": false, "Source": { - "Filesystem": null + "Filesystem": null, + "InMemorySwitchover": { + "Enabled": false + } }, "Workers": 8, "ItemsPerSecond": 50, diff --git a/router/pkg/config/testdata/config_full.json b/router/pkg/config/testdata/config_full.json index 02064e09d5..fe9f31ead0 100644 --- a/router/pkg/config/testdata/config_full.json +++ b/router/pkg/config/testdata/config_full.json @@ -657,7 +657,10 @@ "CacheWarmup": { "Enabled": false, "Source": { - "Filesystem": null + "Filesystem": null, + "InMemorySwitchover": { + "Enabled": false + } }, "Workers": 8, "ItemsPerSecond": 50, From 3159713deca2defac361c452d3e54016350af6a9 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 21:44:54 +0530 Subject: [PATCH 10/52] fix: config reloading --- router-tests/cache_warmup_test.go | 195 +++++++++++++++++++++++ router/cmd/main.go | 3 +- router/core/operation_planner.go | 1 - router/core/restart_switchover_config.go | 34 ++-- router/core/router.go | 12 +- router/core/supervisor.go | 15 +- router/core/supervisor_instance.go | 5 +- 7 files changed, 244 insertions(+), 21 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 824c869f69..430c305d0a 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -2,6 +2,8 @@ package integration import ( "context" + "github.com/stretchr/testify/assert" + "github.com/wundergraph/cosmo/router/pkg/controlplane/configpoller" "net/http" "testing" "time" @@ -914,6 +916,199 @@ func TestCacheWarmup(t *testing.T) { }) } +func TestInMemorySwitchoverCaching(t *testing.T) { + t.Parallel() + + t.Run("Verify the plan is cached on config restart when in memory switchover is enabled", func(t *testing.T) { + t.Parallel() + + pm := ConfigPollerMock{ + ready: make(chan struct{}), + } + + testenv.Run(t, &testenv.Config{ + RouterOptions: []core.Option{ + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: true, + }, + }, + }), + core.WithConfigVersionHeader(true), + }, + RouterConfig: &testenv.RouterConfig{ + ConfigPollerFactory: func(config *nodev1.RouterConfig) configpoller.ConfigPoller { + pm.initConfig = config + return &pm + }, + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) + require.JSONEq(t, employeesIDData, res.Body) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + // Wait for the config poller to be ready + <-pm.ready + + pm.initConfig.Version = "updated" + require.NoError(t, pm.updateConfig(pm.initConfig, "old-1")) + + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.JSONEq(t, employeesIDData, res.Body) + require.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + + }) + }) + + t.Run("Verify the plan is not cached on config restart when in cache warmer is disabled", func(t *testing.T) { + t.Parallel() + + pm := ConfigPollerMock{ + ready: make(chan struct{}), + } + + testenv.Run(t, &testenv.Config{ + RouterOptions: []core.Option{ + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: false, + }), + core.WithConfigVersionHeader(true), + }, + RouterConfig: &testenv.RouterConfig{ + ConfigPollerFactory: func(config *nodev1.RouterConfig) configpoller.ConfigPoller { + pm.initConfig = config + return &pm + }, + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + // Wait for the config poller to be ready + <-pm.ready + + pm.initConfig.Version = "updated" + require.NoError(t, pm.updateConfig(pm.initConfig, "old-1")) + + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + }) + }) + + t.Run("Verify the plan is not cached on config restart when using default cache warmer", func(t *testing.T) { + t.Parallel() + + pm := ConfigPollerMock{ + ready: make(chan struct{}), + } + + testenv.Run(t, &testenv.Config{ + RouterOptions: []core.Option{ + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: false, + }, + }, + }), + core.WithConfigVersionHeader(true), + }, + RouterConfig: &testenv.RouterConfig{ + ConfigPollerFactory: func(config *nodev1.RouterConfig) configpoller.ConfigPoller { + pm.initConfig = config + return &pm + }, + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id customDetails: details { forename } } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + // Wait for the config poller to be ready + <-pm.ready + + pm.initConfig.Version = "updated" + require.NoError(t, pm.updateConfig(pm.initConfig, "old-1")) + + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `{ employees { id customDetails: details { forename } } }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + }) + }) + + t.Run("Verify plan is cached when static execution config is reloaded", func(t *testing.T) { + t.Parallel() + + // Create a temporary file for the router config + configFile := t.TempDir() + "/config.json" + + // Initial config with just the employees subgraph + writeTestConfig(t, "initial", configFile) + + testenv.Run(t, &testenv.Config{ + RouterOptions: []core.Option{ + core.WithConfigVersionHeader(true), + core.WithExecutionConfig(&core.ExecutionConfig{ + Path: configFile, + Watch: true, + WatchInterval: 100 * time.Millisecond, + }), + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: true, + }, + }, + }), + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, "initial", res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + writeTestConfig(t, "updated", configFile) + + require.EventuallyWithT(t, func(t *assert.CollectT) { + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + require.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + }, 2*time.Second, 100*time.Millisecond) + }) + }) + +} + // findDataPoint finds a data point in a slice of histogram data points by matching // the value of WgEnginePlanCacheHit attribute func findDataPoint(t *testing.T, dataPoints []metricdata.HistogramDataPoint[float64], cacheHit bool) metricdata.HistogramDataPoint[float64] { diff --git a/router/cmd/main.go b/router/cmd/main.go index 59cd9b8572..7001b46c69 100644 --- a/router/cmd/main.go +++ b/router/cmd/main.go @@ -150,7 +150,8 @@ func Main() { } rs, err := core.NewRouterSupervisor(&core.RouterSupervisorOpts{ - BaseLogger: baseLogger, + BaseLogger: baseLogger, + SwitchoverConfig: core.NewSwitchoverConfig(), ConfigFactory: func() (*config.Config, error) { result, err := config.LoadConfig(*configPathFlag) if err != nil { diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index 4c6b3e2312..3a18951bd7 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -138,7 +138,6 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions operationID := opContext.internalHash // try to get a prepared plan for this operation ID from the cache cachedPlan, ok := p.planCache.Get(operationID) - if ok && cachedPlan != nil { // re-use a prepared plan opContext.preparedPlan = cachedPlan diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 78662b4d22..cb4a670054 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -1,9 +1,10 @@ package core import ( - "github.com/dgraph-io/ristretto/v2" "sync" + "github.com/dgraph-io/ristretto/v2" + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" ) @@ -14,18 +15,26 @@ type SwitchoverConfig struct { inMemorySwitchOverCache *InMemorySwitchOverCache } -func NewSwitchoverConfig(config *Config) *SwitchoverConfig { - switchoverConfig := &SwitchoverConfig{ - inMemorySwitchOverCache: &InMemorySwitchOverCache{ - enabled: config.cacheWarmup.Enabled && config.cacheWarmup.Source.InMemorySwitchover.Enabled, - }, +func NewSwitchoverConfig() *SwitchoverConfig { + return &SwitchoverConfig{ + inMemorySwitchOverCache: &InMemorySwitchOverCache{}, } +} - if switchoverConfig.inMemorySwitchOverCache.enabled { - switchoverConfig.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) - } +func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config) { + s.inMemorySwitchOverCache.enabled = config.cacheWarmup != nil && + config.cacheWarmup.Enabled && + config.cacheWarmup.Source.InMemorySwitchover.Enabled - return switchoverConfig + if s.inMemorySwitchOverCache.enabled { + // Only initialize if its nil (because its a first start or it was disabled before) + if s.inMemorySwitchOverCache.queriesForFeatureFlag == nil { + s.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) + } + s.inMemorySwitchOverCache.testValue++ + } else { + s.inMemorySwitchOverCache.queriesForFeatureFlag = nil + } } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { @@ -35,6 +44,7 @@ func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { type InMemorySwitchOverCache struct { enabled bool mu sync.RWMutex + testValue int queriesForFeatureFlag map[string]planCache } @@ -76,6 +86,10 @@ func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.Ro } for ffName, _ := range c.queriesForFeatureFlag { + // Skip the base which is "" + if ffName == "" { + continue + } if _, exists := ffNames[ffName]; !exists { delete(c.queriesForFeatureFlag, ffName) } diff --git a/router/core/router.go b/router/core/router.go index 9871b7755e..f9e861d49d 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1174,7 +1174,11 @@ func (r *Router) Start(ctx context.Context) error { healthCheckPath: r.healthCheckPath, }) - r.switchoverConfig = NewSwitchoverConfig(&r.Config) + if r.switchoverConfig == nil { + // This is only applicable for tests since we do not call here via the sueprvisor + r.switchoverConfig = NewSwitchoverConfig() + } + r.switchoverConfig.UpdateSwitchoverConfig(&r.Config) // Start the server with the static config without polling if r.staticExecutionConfig != nil { @@ -2050,6 +2054,12 @@ func WithConfigPollerConfig(cfg *RouterConfigPollerConfig) Option { } } +func WithSwitchoverConfig(cfg *SwitchoverConfig) Option { + return func(r *Router) { + r.switchoverConfig = cfg + } +} + func WithPersistedOperationsConfig(cfg config.PersistedOperationsConfig) Option { return func(r *Router) { r.persistedOperationsConfig = cfg diff --git a/router/core/supervisor.go b/router/core/supervisor.go index 30e7e0fca8..699d2ab9fb 100644 --- a/router/core/supervisor.go +++ b/router/core/supervisor.go @@ -30,15 +30,17 @@ type RouterSupervisor struct { // RouterResources is a struct for holding resources used by the router. type RouterResources struct { - Config *config.Config - Logger *zap.Logger + Config *config.Config + Logger *zap.Logger + SwitchoverConfig *SwitchoverConfig } // RouterSupervisorOpts is a struct for configuring the router supervisor. type RouterSupervisorOpts struct { - BaseLogger *zap.Logger - ConfigFactory func() (*config.Config, error) - RouterFactory func(ctx context.Context, res *RouterResources) (*Router, error) + BaseLogger *zap.Logger + ConfigFactory func() (*config.Config, error) + RouterFactory func(ctx context.Context, res *RouterResources) (*Router, error) + SwitchoverConfig *SwitchoverConfig } // NewRouterSupervisor creates a new RouterSupervisor instance. @@ -48,7 +50,8 @@ func NewRouterSupervisor(opts *RouterSupervisorOpts) (*RouterSupervisor, error) logger: opts.BaseLogger.With(zap.String("component", "supervisor")), configFactory: opts.ConfigFactory, resources: &RouterResources{ - Logger: opts.BaseLogger, + Logger: opts.BaseLogger, + SwitchoverConfig: opts.SwitchoverConfig, }, } diff --git a/router/core/supervisor_instance.go b/router/core/supervisor_instance.go index b791053bc5..3240aeb9f7 100644 --- a/router/core/supervisor_instance.go +++ b/router/core/supervisor_instance.go @@ -50,7 +50,7 @@ func newRouter(ctx context.Context, params RouterResources, additionalOptions .. } } - options := optionsFromResources(logger, cfg) + options := optionsFromResources(logger, cfg, params.SwitchoverConfig) options = append(options, additionalOptions...) authenticators, err := setupAuthenticators(ctx, logger, cfg) @@ -181,7 +181,7 @@ func newRouter(ctx context.Context, params RouterResources, additionalOptions .. return NewRouter(options...) } -func optionsFromResources(logger *zap.Logger, config *config.Config) []Option { +func optionsFromResources(logger *zap.Logger, config *config.Config, switchoverConfig *SwitchoverConfig) []Option { options := []Option{ WithListenerAddr(config.ListenAddr), WithOverrideRoutingURL(config.OverrideRoutingURL), @@ -272,6 +272,7 @@ func optionsFromResources(logger *zap.Logger, config *config.Config) []Option { WithPlugins(config.Plugins), WithDemoMode(config.DemoMode), WithStreamsHandlerConfiguration(config.Events.Handlers), + WithSwitchoverConfig(switchoverConfig), } return options From 2bdf426764d9ae77c4fc9ab6839aed0b3d4b945c Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 21:50:37 +0530 Subject: [PATCH 11/52] fix: update router-tests --- router-tests/go.mod | 1 + router-tests/go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/router-tests/go.mod b/router-tests/go.mod index c9a3abaf01..0e0779672b 100644 --- a/router-tests/go.mod +++ b/router-tests/go.mod @@ -204,6 +204,7 @@ replace ( // Use what is best for your personal workflow. See CONTRIBUTING.md for more information replace ( + github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d github.com/wundergraph/cosmo/demo => ../demo github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects => ../demo/pkg/subgraphs/projects github.com/wundergraph/cosmo/router => ../router diff --git a/router-tests/go.sum b/router-tests/go.sum index 6370091021..4c57d6e621 100644 --- a/router-tests/go.sum +++ b/router-tests/go.sum @@ -65,10 +65,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= -github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= @@ -354,6 +352,8 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242 h1:0ieQmRxYz0nbJEbaaA4Cx2RPcxlomhQ8KI31uuevWx0= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= +github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d h1:FlfUZzJbnc8+bgSKJ2jCqozn9CS08ToZe/JJxh4DPGo= +github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= From 0e92ca10230b7ceb6fc1439ccbf5e53cdd4b041e Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 22:09:04 +0530 Subject: [PATCH 12/52] fix: cleanup --- router/core/http_server.go | 1 - router/core/restart_switchover_config.go | 38 +- router/core/restart_switchover_config_test.go | 382 ++++++++++++++++++ router/core/router.go | 2 +- 4 files changed, 405 insertions(+), 18 deletions(-) create mode 100644 router/core/restart_switchover_config_test.go diff --git a/router/core/http_server.go b/router/core/http_server.go index 8ca083510f..9ad8dcd350 100644 --- a/router/core/http_server.go +++ b/router/core/http_server.go @@ -36,7 +36,6 @@ type httpServerOptions struct { livenessCheckPath string readinessCheckPath string healthCheckPath string - switchoverConfig *SwitchoverConfig } func newServer(opts *httpServerOptions) *server { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index cb4a670054..cf017e3c01 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -22,19 +22,7 @@ func NewSwitchoverConfig() *SwitchoverConfig { } func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config) { - s.inMemorySwitchOverCache.enabled = config.cacheWarmup != nil && - config.cacheWarmup.Enabled && - config.cacheWarmup.Source.InMemorySwitchover.Enabled - - if s.inMemorySwitchOverCache.enabled { - // Only initialize if its nil (because its a first start or it was disabled before) - if s.inMemorySwitchOverCache.queriesForFeatureFlag == nil { - s.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) - } - s.inMemorySwitchOverCache.testValue++ - } else { - s.inMemorySwitchOverCache.queriesForFeatureFlag = nil - } + s.inMemorySwitchOverCache.UpdateInMemorySwitchOverCacheForConfigChanges(config) } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { @@ -44,10 +32,28 @@ func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { type InMemorySwitchOverCache struct { enabled bool mu sync.RWMutex - testValue int queriesForFeatureFlag map[string]planCache } +func (c *InMemorySwitchOverCache) UpdateInMemorySwitchOverCacheForConfigChanges(config *Config) { + c.mu.RLock() + defer c.mu.RUnlock() + + c.enabled = config.cacheWarmup != nil && + config.cacheWarmup.Enabled && + config.cacheWarmup.Source.InMemorySwitchover.Enabled + + // If the configuration change occurred which disabled or enabled the switchover cache, we need to update the internal state + if c.enabled { + // Only initialize if its nil (because its a first start or it was disabled before) + if c.queriesForFeatureFlag == nil { + c.queriesForFeatureFlag = make(map[string]planCache) + } + } else { + c.queriesForFeatureFlag = nil + } +} + func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) planCache { if !c.enabled { return nil @@ -81,11 +87,11 @@ func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.Ro defer c.mu.Unlock() ffNames := make(map[string]struct{}) - for ffName, _ := range routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName { + for ffName := range routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName { ffNames[ffName] = struct{}{} } - for ffName, _ := range c.queriesForFeatureFlag { + for ffName := range c.queriesForFeatureFlag { // Skip the base which is "" if ffName == "" { continue diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go new file mode 100644 index 0000000000..02d0c7c787 --- /dev/null +++ b/router/core/restart_switchover_config_test.go @@ -0,0 +1,382 @@ +package core + +import ( + "testing" + + "github.com/dgraph-io/ristretto/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" + "github.com/wundergraph/cosmo/router/pkg/config" +) + +func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t *testing.T) { + t.Run("enable cache from disabled state", func(t *testing.T) { + cache := &InMemorySwitchOverCache{} + cfg := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: true, + }, + }, + }, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.True(t, cache.enabled) + assert.NotNil(t, cache.queriesForFeatureFlag) + assert.Empty(t, cache.queriesForFeatureFlag) + }) + + t.Run("disable cache from enabled state", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["test"] = nil + + cfg := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: false, + }, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.False(t, cache.enabled) + assert.Nil(t, cache.queriesForFeatureFlag) + }) + + t.Run("update when already enabled keeps existing data", func(t *testing.T) { + existingMap := make(map[string]planCache) + existingMap["test"] = nil + + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: existingMap, + } + + cfg := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: true, + }, + }, + }, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.True(t, cache.enabled) + assert.NotNil(t, cache.queriesForFeatureFlag) + assert.Len(t, cache.queriesForFeatureFlag, 1) + assert.Contains(t, cache.queriesForFeatureFlag, "test") + }) + + t.Run("update when already disabled", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: false, + queriesForFeatureFlag: nil, + } + + cfg := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: false, + }, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.False(t, cache.enabled) + assert.Nil(t, cache.queriesForFeatureFlag) + }) + + t.Run("nil cacheWarmup config disables cache", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + + cfg := &Config{ + cacheWarmup: nil, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.False(t, cache.enabled) + assert.Nil(t, cache.queriesForFeatureFlag) + }) + + t.Run("cacheWarmup enabled but InMemorySwitchover disabled", func(t *testing.T) { + cache := &InMemorySwitchOverCache{} + + cfg := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: false, + }, + }, + }, + } + + cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + + assert.False(t, cache.enabled) + assert.Nil(t, cache.queriesForFeatureFlag) + }) +} + +func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { + t.Run("returns cache for existing feature flag when enabled", func(t *testing.T) { + mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ + MaxCost: 100, + NumCounters: 10000, + BufferItems: 64, + }) + require.NoError(t, err) + + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["test-ff"] = mockCache + + result := cache.getPlanCacheForFF("test-ff") + + assert.NotNil(t, result) + // Verify it's the same cache by comparing pointer addresses + assert.Equal(t, mockCache, (*ristretto.Cache[uint64, *planWithMetaData])(result)) + }) + + t.Run("returns nil for non-existent feature flag", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + + result := cache.getPlanCacheForFF("non-existent") + + assert.Nil(t, result) + }) + + t.Run("returns nil when cache is disabled", func(t *testing.T) { + mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ + MaxCost: 100, + NumCounters: 10000, + BufferItems: 64, + }) + require.NoError(t, err) + + cache := &InMemorySwitchOverCache{ + enabled: false, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["test-ff"] = mockCache + + result := cache.getPlanCacheForFF("test-ff") + + assert.Nil(t, result) + }) +} + +func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { + t.Run("sets cache for feature flag when enabled", func(t *testing.T) { + mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ + MaxCost: 100, + NumCounters: 10000, + BufferItems: 64, + }) + require.NoError(t, err) + + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + + cache.setPlanCacheForFF("test-ff", mockCache) + + assert.Contains(t, cache.queriesForFeatureFlag, "test-ff") + // Verify it's the same cache by comparing the underlying pointer + assert.Equal(t, mockCache, (*ristretto.Cache[uint64, *planWithMetaData])(cache.queriesForFeatureFlag["test-ff"])) + }) + + t.Run("does not set cache when disabled", func(t *testing.T) { + mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ + MaxCost: 100, + NumCounters: 10000, + BufferItems: 64, + }) + require.NoError(t, err) + + cache := &InMemorySwitchOverCache{ + enabled: false, + queriesForFeatureFlag: make(map[string]planCache), + } + + cache.setPlanCacheForFF("test-ff", mockCache) + + assert.NotContains(t, cache.queriesForFeatureFlag, "test-ff") + }) + + t.Run("does not set nil cache", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + + cache.setPlanCacheForFF("test-ff", nil) + + assert.NotContains(t, cache.queriesForFeatureFlag, "test-ff") + }) +} + +func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { + t.Run("removes unused feature flags", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["ff1"] = nil + cache.queriesForFeatureFlag["ff2"] = nil + cache.queriesForFeatureFlag["ff3"] = nil + + routerCfg := &nodev1.RouterConfig{ + FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ + ConfigByFeatureFlagName: map[string]*nodev1.FeatureFlagRouterExecutionConfig{ + "ff1": {}, + "ff2": {}, + }, + }, + } + + cache.cleanupUnusedFeatureFlags(routerCfg) + + assert.Len(t, cache.queriesForFeatureFlag, 2) + assert.Contains(t, cache.queriesForFeatureFlag, "ff1") + assert.Contains(t, cache.queriesForFeatureFlag, "ff2") + assert.NotContains(t, cache.queriesForFeatureFlag, "ff3") + }) + + t.Run("keeps empty string feature flag", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag[""] = nil + cache.queriesForFeatureFlag["ff1"] = nil + + routerCfg := &nodev1.RouterConfig{ + FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ + ConfigByFeatureFlagName: map[string]*nodev1.FeatureFlagRouterExecutionConfig{}, + }, + } + + cache.cleanupUnusedFeatureFlags(routerCfg) + + assert.Len(t, cache.queriesForFeatureFlag, 1) + assert.Contains(t, cache.queriesForFeatureFlag, "") + assert.NotContains(t, cache.queriesForFeatureFlag, "ff1") + }) + + t.Run("does nothing when cache is disabled", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: false, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["ff1"] = nil + + routerCfg := &nodev1.RouterConfig{ + FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ + ConfigByFeatureFlagName: map[string]*nodev1.FeatureFlagRouterExecutionConfig{}, + }, + } + + cache.cleanupUnusedFeatureFlags(routerCfg) + + // Should still have ff1 because cleanup is skipped when disabled + assert.Len(t, cache.queriesForFeatureFlag, 1) + assert.Contains(t, cache.queriesForFeatureFlag, "ff1") + }) + + t.Run("does nothing when FeatureFlagConfigs is nil", func(t *testing.T) { + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]planCache), + } + cache.queriesForFeatureFlag["ff1"] = nil + + routerCfg := &nodev1.RouterConfig{ + FeatureFlagConfigs: nil, + } + + cache.cleanupUnusedFeatureFlags(routerCfg) + + // Should still have ff1 because FeatureFlagConfigs is nil + assert.Len(t, cache.queriesForFeatureFlag, 1) + assert.Contains(t, cache.queriesForFeatureFlag, "ff1") + }) +} + +func TestSwitchoverConfig_NewSwitchoverConfig(t *testing.T) { + t.Run("creates new switchover config with initialized cache", func(t *testing.T) { + cfg := NewSwitchoverConfig() + + assert.NotNil(t, cfg) + assert.NotNil(t, cfg.inMemorySwitchOverCache) + assert.False(t, cfg.inMemorySwitchOverCache.enabled) + assert.Nil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) + }) +} + +func TestSwitchoverConfig_UpdateSwitchoverConfig(t *testing.T) { + t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { + cfg := NewSwitchoverConfig() + routerConfig := &Config{ + cacheWarmup: &config.CacheWarmupConfiguration{ + Enabled: true, + Source: config.CacheWarmupSource{ + InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ + Enabled: true, + }, + }, + }, + } + + cfg.UpdateSwitchoverConfig(routerConfig) + + assert.True(t, cfg.inMemorySwitchOverCache.enabled) + assert.NotNil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) + }) +} + +func TestSwitchoverConfig_CleanupFeatureFlags(t *testing.T) { + t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { + cfg := NewSwitchoverConfig() + cfg.inMemorySwitchOverCache.enabled = true + cfg.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) + cfg.inMemorySwitchOverCache.queriesForFeatureFlag["ff1"] = nil + cfg.inMemorySwitchOverCache.queriesForFeatureFlag["ff2"] = nil + + routerCfg := &nodev1.RouterConfig{ + FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ + ConfigByFeatureFlagName: map[string]*nodev1.FeatureFlagRouterExecutionConfig{ + "ff1": {}, + }, + }, + } + + cfg.CleanupFeatureFlags(routerCfg) + + assert.Len(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, 1) + assert.Contains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff1") + assert.NotContains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff2") + }) +} diff --git a/router/core/router.go b/router/core/router.go index f9e861d49d..d74c80ae0c 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1175,7 +1175,7 @@ func (r *Router) Start(ctx context.Context) error { }) if r.switchoverConfig == nil { - // This is only applicable for tests since we do not call here via the sueprvisor + // This is only applicable for tests since we do not call here via the supervisor r.switchoverConfig = NewSwitchoverConfig() } r.switchoverConfig.UpdateSwitchoverConfig(&r.Config) From 78fc67d4dbe6926321cfe6deecc86f15eacf929a Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 22:13:04 +0530 Subject: [PATCH 13/52] fix: use assert --- router-tests/cache_warmup_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 430c305d0a..fbf3c9105d 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -1101,8 +1101,8 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `query { hello }`, }) - require.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) - require.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + assert.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) + assert.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) }, 2*time.Second, 100*time.Millisecond) }) }) From f4850f6ddb36501e4579db394cb63b15dee06dc4 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Wed, 14 Jan 2026 22:25:26 +0530 Subject: [PATCH 14/52] fix: review comments --- router/core/restart_switchover_config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index cf017e3c01..8b359512e2 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -36,8 +36,8 @@ type InMemorySwitchOverCache struct { } func (c *InMemorySwitchOverCache) UpdateInMemorySwitchOverCacheForConfigChanges(config *Config) { - c.mu.RLock() - defer c.mu.RUnlock() + c.mu.Lock() + defer c.mu.Unlock() c.enabled = config.cacheWarmup != nil && config.cacheWarmup.Enabled && From 7ec23f1e98513c3a7927207596637bc7f46c4a2f Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 15 Jan 2026 01:05:26 +0530 Subject: [PATCH 15/52] fix: linting --- router-tests/cache_warmup_test.go | 6 +- router/core/cache_warmup_plans.go | 4 +- router/core/graph_server.go | 7 +- router/core/restart_switchover_config_test.go | 113 +++++++++++------- 4 files changed, 78 insertions(+), 52 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index fbf3c9105d..370826854e 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -948,7 +948,7 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id } }`, }) - require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, 200, res.Response.StatusCode) require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) require.JSONEq(t, employeesIDData, res.Body) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) @@ -962,8 +962,8 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id } }`, }) - require.Equal(t, res.Response.StatusCode, 200) - require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.Equal(t, 200, res.Response.StatusCode) + require.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) require.JSONEq(t, employeesIDData, res.Body) require.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 0053b1f45b..93055a689b 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -18,7 +18,7 @@ func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWi items := make([]*nodev1.Operation, 0) if switchoverCacheWarmerQueries != nil { - switchoverCacheWarmerQueries.Iter(func(k any, v *planWithMetaData) (stop bool) { + switchoverCacheWarmerQueries.Iter(func(_ any, v *planWithMetaData) (stop bool) { items = append(items, &nodev1.Operation{ Request: &nodev1.OperationRequest{Query: v.content}, }) @@ -29,6 +29,6 @@ func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWi return &PlanSource{queries: items} } -func (c *PlanSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { +func (c *PlanSource) LoadItems(_ context.Context, _ *zap.Logger) ([]*nodev1.Operation, error) { return c.queries, nil } diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 81e8685d8c..f5cc536777 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1351,16 +1351,17 @@ func (s *graphServer) buildGraphMux( ) } - if s.Config.cacheWarmup.Source.Filesystem != nil { + switch { + case s.cacheWarmup.Source.Filesystem != nil: warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) - } else if s.Config.cacheWarmup.Source.InMemorySwitchover.Enabled { + case s.cacheWarmup.Source.InMemorySwitchover.Enabled: // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries // and reset the plan cache to the new plan cache for this start afterwords warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) - } else { + default: cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) if err != nil { return nil, fmt.Errorf("failed to create cdn source: %w", err) diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 02d0c7c787..337f4c5924 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/dgraph-io/ristretto/v2" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" @@ -12,7 +11,9 @@ import ( ) func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t *testing.T) { + t.Parallel() t.Run("enable cache from disabled state", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{} cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -27,12 +28,13 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.True(t, cache.enabled) - assert.NotNil(t, cache.queriesForFeatureFlag) - assert.Empty(t, cache.queriesForFeatureFlag) + require.True(t, cache.enabled) + require.NotNil(t, cache.queriesForFeatureFlag) + require.Empty(t, cache.queriesForFeatureFlag) }) t.Run("disable cache from enabled state", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -47,11 +49,12 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.False(t, cache.enabled) - assert.Nil(t, cache.queriesForFeatureFlag) + require.False(t, cache.enabled) + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("update when already enabled keeps existing data", func(t *testing.T) { + t.Parallel() existingMap := make(map[string]planCache) existingMap["test"] = nil @@ -73,13 +76,14 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.True(t, cache.enabled) - assert.NotNil(t, cache.queriesForFeatureFlag) - assert.Len(t, cache.queriesForFeatureFlag, 1) - assert.Contains(t, cache.queriesForFeatureFlag, "test") + require.True(t, cache.enabled) + require.NotNil(t, cache.queriesForFeatureFlag) + require.Len(t, cache.queriesForFeatureFlag, 1) + require.Contains(t, cache.queriesForFeatureFlag, "test") }) t.Run("update when already disabled", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: false, queriesForFeatureFlag: nil, @@ -93,11 +97,12 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.False(t, cache.enabled) - assert.Nil(t, cache.queriesForFeatureFlag) + require.False(t, cache.enabled) + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("nil cacheWarmup config disables cache", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -109,11 +114,12 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.False(t, cache.enabled) - assert.Nil(t, cache.queriesForFeatureFlag) + require.False(t, cache.enabled) + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("cacheWarmup enabled but InMemorySwitchover disabled", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{} cfg := &Config{ @@ -129,13 +135,15 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) - assert.False(t, cache.enabled) - assert.Nil(t, cache.queriesForFeatureFlag) + require.False(t, cache.enabled) + require.Nil(t, cache.queriesForFeatureFlag) }) } func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { + t.Parallel() t.Run("returns cache for existing feature flag when enabled", func(t *testing.T) { + t.Parallel() mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ MaxCost: 100, NumCounters: 10000, @@ -151,12 +159,13 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { result := cache.getPlanCacheForFF("test-ff") - assert.NotNil(t, result) + require.NotNil(t, result) // Verify it's the same cache by comparing pointer addresses - assert.Equal(t, mockCache, (*ristretto.Cache[uint64, *planWithMetaData])(result)) + require.Equal(t, (*ristretto.Cache[uint64, *planWithMetaData])(result), mockCache) }) t.Run("returns nil for non-existent feature flag", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -164,10 +173,11 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { result := cache.getPlanCacheForFF("non-existent") - assert.Nil(t, result) + require.Nil(t, result) }) t.Run("returns nil when cache is disabled", func(t *testing.T) { + t.Parallel() mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ MaxCost: 100, NumCounters: 10000, @@ -183,12 +193,14 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { result := cache.getPlanCacheForFF("test-ff") - assert.Nil(t, result) + require.Nil(t, result) }) } func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { + t.Parallel() t.Run("sets cache for feature flag when enabled", func(t *testing.T) { + t.Parallel() mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ MaxCost: 100, NumCounters: 10000, @@ -203,12 +215,13 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache.setPlanCacheForFF("test-ff", mockCache) - assert.Contains(t, cache.queriesForFeatureFlag, "test-ff") + require.Contains(t, cache.queriesForFeatureFlag, "test-ff") // Verify it's the same cache by comparing the underlying pointer - assert.Equal(t, mockCache, (*ristretto.Cache[uint64, *planWithMetaData])(cache.queriesForFeatureFlag["test-ff"])) + require.Equal(t, (*ristretto.Cache[uint64, *planWithMetaData])(cache.queriesForFeatureFlag["test-ff"]), mockCache) }) t.Run("does not set cache when disabled", func(t *testing.T) { + t.Parallel() mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ MaxCost: 100, NumCounters: 10000, @@ -223,10 +236,11 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache.setPlanCacheForFF("test-ff", mockCache) - assert.NotContains(t, cache.queriesForFeatureFlag, "test-ff") + require.NotContains(t, cache.queriesForFeatureFlag, "test-ff") }) t.Run("does not set nil cache", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -234,12 +248,14 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache.setPlanCacheForFF("test-ff", nil) - assert.NotContains(t, cache.queriesForFeatureFlag, "test-ff") + require.NotContains(t, cache.queriesForFeatureFlag, "test-ff") }) } func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { + t.Parallel() t.Run("removes unused feature flags", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -259,13 +275,14 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache.cleanupUnusedFeatureFlags(routerCfg) - assert.Len(t, cache.queriesForFeatureFlag, 2) - assert.Contains(t, cache.queriesForFeatureFlag, "ff1") - assert.Contains(t, cache.queriesForFeatureFlag, "ff2") - assert.NotContains(t, cache.queriesForFeatureFlag, "ff3") + require.Len(t, cache.queriesForFeatureFlag, 2) + require.Contains(t, cache.queriesForFeatureFlag, "ff1") + require.Contains(t, cache.queriesForFeatureFlag, "ff2") + require.NotContains(t, cache.queriesForFeatureFlag, "ff3") }) t.Run("keeps empty string feature flag", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -281,12 +298,13 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache.cleanupUnusedFeatureFlags(routerCfg) - assert.Len(t, cache.queriesForFeatureFlag, 1) - assert.Contains(t, cache.queriesForFeatureFlag, "") - assert.NotContains(t, cache.queriesForFeatureFlag, "ff1") + require.Len(t, cache.queriesForFeatureFlag, 1) + require.Contains(t, cache.queriesForFeatureFlag, "") + require.NotContains(t, cache.queriesForFeatureFlag, "ff1") }) t.Run("does nothing when cache is disabled", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: false, queriesForFeatureFlag: make(map[string]planCache), @@ -302,11 +320,12 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache.cleanupUnusedFeatureFlags(routerCfg) // Should still have ff1 because cleanup is skipped when disabled - assert.Len(t, cache.queriesForFeatureFlag, 1) - assert.Contains(t, cache.queriesForFeatureFlag, "ff1") + require.Len(t, cache.queriesForFeatureFlag, 1) + require.Contains(t, cache.queriesForFeatureFlag, "ff1") }) t.Run("does nothing when FeatureFlagConfigs is nil", func(t *testing.T) { + t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, queriesForFeatureFlag: make(map[string]planCache), @@ -320,24 +339,28 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache.cleanupUnusedFeatureFlags(routerCfg) // Should still have ff1 because FeatureFlagConfigs is nil - assert.Len(t, cache.queriesForFeatureFlag, 1) - assert.Contains(t, cache.queriesForFeatureFlag, "ff1") + require.Len(t, cache.queriesForFeatureFlag, 1) + require.Contains(t, cache.queriesForFeatureFlag, "ff1") }) } func TestSwitchoverConfig_NewSwitchoverConfig(t *testing.T) { + t.Parallel() t.Run("creates new switchover config with initialized cache", func(t *testing.T) { + t.Parallel() cfg := NewSwitchoverConfig() - assert.NotNil(t, cfg) - assert.NotNil(t, cfg.inMemorySwitchOverCache) - assert.False(t, cfg.inMemorySwitchOverCache.enabled) - assert.Nil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) + require.NotNil(t, cfg) + require.NotNil(t, cfg.inMemorySwitchOverCache) + require.False(t, cfg.inMemorySwitchOverCache.enabled) + require.Nil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) }) } func TestSwitchoverConfig_UpdateSwitchoverConfig(t *testing.T) { + t.Parallel() t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { + t.Parallel() cfg := NewSwitchoverConfig() routerConfig := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -352,13 +375,15 @@ func TestSwitchoverConfig_UpdateSwitchoverConfig(t *testing.T) { cfg.UpdateSwitchoverConfig(routerConfig) - assert.True(t, cfg.inMemorySwitchOverCache.enabled) - assert.NotNil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) + require.True(t, cfg.inMemorySwitchOverCache.enabled) + require.NotNil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) }) } func TestSwitchoverConfig_CleanupFeatureFlags(t *testing.T) { + t.Parallel() t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { + t.Parallel() cfg := NewSwitchoverConfig() cfg.inMemorySwitchOverCache.enabled = true cfg.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) @@ -375,8 +400,8 @@ func TestSwitchoverConfig_CleanupFeatureFlags(t *testing.T) { cfg.CleanupFeatureFlags(routerCfg) - assert.Len(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, 1) - assert.Contains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff1") - assert.NotContains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff2") + require.Len(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, 1) + require.Contains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff1") + require.NotContains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff2") }) } From 42bbcbd903528cbc929ddba4ba1e5b121343ef48 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 15 Jan 2026 01:07:48 +0530 Subject: [PATCH 16/52] fix: linting --- router-tests/cache_warmup_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 370826854e..ee60598af7 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -994,7 +994,7 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id } }`, }) - require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, 200, res.Response.StatusCode) require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) @@ -1007,8 +1007,8 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id } }`, }) - require.Equal(t, res.Response.StatusCode, 200) - require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.Equal(t, 200, res.Response.StatusCode) + require.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) }) }) @@ -1042,7 +1042,7 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id customDetails: details { forename } } }`, }) - require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, 200, res.Response.StatusCode) require.Equal(t, xEnv.RouterConfigVersionMain(), res.Response.Header.Get("X-Router-Config-Version")) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) @@ -1055,8 +1055,8 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `{ employees { id customDetails: details { forename } } }`, }) - require.Equal(t, res.Response.StatusCode, 200) - require.Equal(t, res.Response.Header.Get("X-Router-Config-Version"), "updated") + require.Equal(t, 200, res.Response.StatusCode) + require.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) }) }) @@ -1091,7 +1091,7 @@ func TestInMemorySwitchoverCaching(t *testing.T) { res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ Query: `query { hello }`, }) - require.Equal(t, res.Response.StatusCode, 200) + require.Equal(t, 200, res.Response.StatusCode) require.Equal(t, "initial", res.Response.Header.Get("X-Router-Config-Version")) require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) From 480967d4820c003ca7715ea3b893da11d7453dcb Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 19 Jan 2026 00:53:22 +0530 Subject: [PATCH 17/52] fix: go modules --- router-tests/go.mod | 2 +- router-tests/go.sum | 4 ++-- router/core/cache_warmup_plans.go | 2 +- router/go.mod | 2 +- router/go.sum | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/router-tests/go.mod b/router-tests/go.mod index 0e0779672b..933a1746c8 100644 --- a/router-tests/go.mod +++ b/router-tests/go.mod @@ -204,7 +204,7 @@ replace ( // Use what is best for your personal workflow. See CONTRIBUTING.md for more information replace ( - github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d + github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c github.com/wundergraph/cosmo/demo => ../demo github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects => ../demo/pkg/subgraphs/projects github.com/wundergraph/cosmo/router => ../router diff --git a/router-tests/go.sum b/router-tests/go.sum index 4c57d6e621..6a603e2981 100644 --- a/router-tests/go.sum +++ b/router-tests/go.sum @@ -352,8 +352,8 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242 h1:0ieQmRxYz0nbJEbaaA4Cx2RPcxlomhQ8KI31uuevWx0= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= -github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d h1:FlfUZzJbnc8+bgSKJ2jCqozn9CS08ToZe/JJxh4DPGo= -github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= +github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= +github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 93055a689b..155d0c5a0e 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -18,7 +18,7 @@ func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWi items := make([]*nodev1.Operation, 0) if switchoverCacheWarmerQueries != nil { - switchoverCacheWarmerQueries.Iter(func(_ any, v *planWithMetaData) (stop bool) { + switchoverCacheWarmerQueries.IterValues(func(v *planWithMetaData) (stop bool) { items = append(items, &nodev1.Operation{ Request: &nodev1.OperationRequest{Query: v.content}, }) diff --git a/router/go.mod b/router/go.mod index 2619abd0a0..d2b1a37407 100644 --- a/router/go.mod +++ b/router/go.mod @@ -196,4 +196,4 @@ replace ( //replace github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2 -replace github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d +replace github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c diff --git a/router/go.sum b/router/go.sum index 80f9fb4dd5..cad6252dd3 100644 --- a/router/go.sum +++ b/router/go.sum @@ -322,8 +322,8 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242 h1:0ieQmRxYz0nbJEbaaA4Cx2RPcxlomhQ8KI31uuevWx0= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.242/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= -github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d h1:FlfUZzJbnc8+bgSKJ2jCqozn9CS08ToZe/JJxh4DPGo= -github.com/wundergraph/ristretto/v2 v2.0.0-20260113151003-f7231509ad4d/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= +github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= +github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= From d542eecb639bf7aa8480b8fa07d43522d28d3b75 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 19 Jan 2026 00:58:14 +0530 Subject: [PATCH 18/52] fix: updates --- router/core/operation_planner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index 3a18951bd7..8048a1abb6 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -42,7 +42,7 @@ type ExecutionPlanCache[K any, V any] interface { // Set the value in the cache with a cost. The cost depends on the cache implementation Set(key K, value V, cost int64) bool // Iterate over all items in the cache (non-deterministic) - Iter(cb func(k any, v V) (stop bool)) + IterValues(cb func(v V) (stop bool)) // Close the cache and free resources Close() } From 3564f0dddec8e2fb2ec3d0c9aa745a53e4ed0f70 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 19 Jan 2026 17:59:44 +0530 Subject: [PATCH 19/52] fix: updates --- router-tests/cache_warmup_test.go | 59 +++++++ router/cmd/main.go | 2 +- router/core/cache_warmup_plans.go | 17 +- router/core/restart_switchover_config.go | 72 ++++++-- router/core/restart_switchover_config_test.go | 156 ++++++++---------- router/core/router.go | 2 +- router/core/supervisor.go | 5 + 7 files changed, 196 insertions(+), 117 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index ee60598af7..c278ed04c4 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -5,6 +5,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/wundergraph/cosmo/router/pkg/controlplane/configpoller" "net/http" + "os" + "path/filepath" + "syscall" "testing" "time" @@ -1107,6 +1110,62 @@ func TestInMemorySwitchoverCaching(t *testing.T) { }) }) + t.Run("Successfully persists cache across config change restarts", func(t *testing.T) { + updateConfig := func(t *testing.T, xEnv *testenv.Environment, ctx context.Context, listenString string, config string) { + f, err := os.Create(filepath.Join(xEnv.GetRouterProcessCwd(), "config.yaml")) + require.NoError(t, err) + + _, err = f.WriteString(config) + require.NoError(t, err) + require.NoError(t, f.Close()) + + err = xEnv.SignalRouterProcess(syscall.SIGHUP) + require.NoError(t, err) + require.NoError(t, xEnv.WaitForServer(ctx, xEnv.RouterURL+"/"+listenString, 600, 60), "healthcheck post-reload failed") + } + + getConfigString := func(listenString string) string { + return ` +version: "1" + +readiness_check_path: "/` + listenString + `" + +cache_warmup: + enabled: true + source: + in_memory_switchover: + enabled: true + +engine: + debug: + enable_cache_response_headers: true +` + } + + err := testenv.RunRouterBinary(t, &testenv.Config{ + DemoMode: true, + }, testenv.RunRouterBinConfigOptions{}, func(t *testing.T, xEnv *testenv.Environment) { + // Verify initial start + t.Logf("running router binary, cwd: %s", xEnv.GetRouterProcessCwd()) + ctx := context.Background() + require.NoError(t, xEnv.WaitForServer(ctx, xEnv.RouterURL+"/health/ready", 600, 60), "healthcheck pre-reload failed") + + // Enable cache response headers first + listenString1 := "after1" + updateConfig(t, xEnv, ctx, listenString1, getConfigString(listenString1)) + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{Query: `query { hello }`}) + assert.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + // Verify cache persisted on restart + listenString2 := "after2" + updateConfig(t, xEnv, ctx, listenString2, getConfigString(listenString2)) + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{Query: `query { hello }`}) + assert.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + }) + + require.NoError(t, err) + }) + } // findDataPoint finds a data point in a slice of histogram data points by matching diff --git a/router/cmd/main.go b/router/cmd/main.go index 7001b46c69..dd04ac292f 100644 --- a/router/cmd/main.go +++ b/router/cmd/main.go @@ -151,7 +151,7 @@ func Main() { rs, err := core.NewRouterSupervisor(&core.RouterSupervisorOpts{ BaseLogger: baseLogger, - SwitchoverConfig: core.NewSwitchoverConfig(), + SwitchoverConfig: core.NewSwitchoverConfig(baseLogger), ConfigFactory: func() (*config.Config, error) { result, err := config.LoadConfig(*configPathFlag) if err != nil { diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 155d0c5a0e..55469ea8b0 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -2,7 +2,6 @@ package core import ( "context" - "github.com/dgraph-io/ristretto/v2" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" "go.uber.org/zap" ) @@ -13,20 +12,8 @@ type PlanSource struct { queries []*nodev1.Operation } -func NewPlanSource(switchoverCacheWarmerQueries *ristretto.Cache[uint64, *planWithMetaData]) *PlanSource { - // Extract the items on creation so that the previous planCache can be garbage collected as we won't hold a reference - items := make([]*nodev1.Operation, 0) - - if switchoverCacheWarmerQueries != nil { - switchoverCacheWarmerQueries.IterValues(func(v *planWithMetaData) (stop bool) { - items = append(items, &nodev1.Operation{ - Request: &nodev1.OperationRequest{Query: v.content}, - }) - return false - }) - } - - return &PlanSource{queries: items} +func NewPlanSource(switchoverCacheWarmerQueries []*nodev1.Operation) *PlanSource { + return &PlanSource{queries: switchoverCacheWarmerQueries} } func (c *PlanSource) LoadItems(_ context.Context, _ *zap.Logger) ([]*nodev1.Operation, error) { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 8b359512e2..eb829a0d33 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -3,39 +3,52 @@ package core import ( "sync" + "go.uber.org/zap" + "github.com/dgraph-io/ristretto/v2" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" ) -type planCache *ristretto.Cache[uint64, *planWithMetaData] +type planCache = *ristretto.Cache[uint64, *planWithMetaData] // SwitchoverConfig This file describes any configuration which should persist or be shared across router restarts type SwitchoverConfig struct { inMemorySwitchOverCache *InMemorySwitchOverCache } -func NewSwitchoverConfig() *SwitchoverConfig { +func NewSwitchoverConfig(logger *zap.Logger) *SwitchoverConfig { return &SwitchoverConfig{ - inMemorySwitchOverCache: &InMemorySwitchOverCache{}, + inMemorySwitchOverCache: &InMemorySwitchOverCache{ + logger: logger, + }, } } func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config) { - s.inMemorySwitchOverCache.UpdateInMemorySwitchOverCacheForConfigChanges(config) + s.inMemorySwitchOverCache.updateStateFromConfig(config) } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } +func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { + // For cases of router config changes (not execution config), we shut down before creating the + // graph mux, because we need to initialize everything from the start + // This causes problems in using the previous planCache reference as it gets closed, so we need to + // copy it over before it gets closed, and we restart with config changes + s.inMemorySwitchOverCache.processOnConfigChangeRestart() +} + type InMemorySwitchOverCache struct { enabled bool mu sync.RWMutex - queriesForFeatureFlag map[string]planCache + queriesForFeatureFlag map[string]any + logger *zap.Logger } -func (c *InMemorySwitchOverCache) UpdateInMemorySwitchOverCacheForConfigChanges(config *Config) { +func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config) { c.mu.Lock() defer c.mu.Unlock() @@ -47,24 +60,37 @@ func (c *InMemorySwitchOverCache) UpdateInMemorySwitchOverCacheForConfigChanges( if c.enabled { // Only initialize if its nil (because its a first start or it was disabled before) if c.queriesForFeatureFlag == nil { - c.queriesForFeatureFlag = make(map[string]planCache) + c.queriesForFeatureFlag = make(map[string]any) } } else { c.queriesForFeatureFlag = nil } } -func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) planCache { +func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { if !c.enabled { return nil } c.mu.RLock() defer c.mu.RUnlock() - return c.queriesForFeatureFlag[featureFlagKey] + + switch cache := c.queriesForFeatureFlag[featureFlagKey].(type) { + case planCache: + return convertToNodeOperation(cache) + case []*nodev1.Operation: + return cache + case nil: + // This would occur during the first start + return make([]*nodev1.Operation, 0) + default: + // This should not happen as we cannot have any types other than the above + c.logger.Error("unexpected type") + return make([]*nodev1.Operation, 0) + } } -func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache *ristretto.Cache[uint64, *planWithMetaData]) { +func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { if !c.enabled || cache == nil { return } @@ -74,6 +100,21 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache c.queriesForFeatureFlag[featureFlagKey] = cache } +func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { + if !c.enabled { + return + } + + c.mu.Lock() + defer c.mu.Unlock() + + switchoverMap := make(map[string]any) + for k, data := range c.queriesForFeatureFlag { + switchoverMap[k] = convertToNodeOperation(data.(planCache)) + } + c.queriesForFeatureFlag = switchoverMap +} + func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { if !c.enabled { return @@ -101,3 +142,14 @@ func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.Ro } } } + +func convertToNodeOperation(data planCache) []*nodev1.Operation { + items := make([]*nodev1.Operation, 0) + data.IterValues(func(v *planWithMetaData) (stop bool) { + items = append(items, &nodev1.Operation{ + Request: &nodev1.OperationRequest{Query: v.content}, + }) + return false + }) + return items +} diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 337f4c5924..62d0f6decd 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -3,6 +3,8 @@ package core import ( "testing" + "go.uber.org/zap" + "github.com/dgraph-io/ristretto/v2" "github.com/stretchr/testify/require" @@ -26,7 +28,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.True(t, cache.enabled) require.NotNil(t, cache.queriesForFeatureFlag) @@ -37,7 +39,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test"] = nil @@ -47,7 +49,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -55,7 +57,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t t.Run("update when already enabled keeps existing data", func(t *testing.T) { t.Parallel() - existingMap := make(map[string]planCache) + existingMap := make(map[string]any) existingMap["test"] = nil cache := &InMemorySwitchOverCache{ @@ -74,7 +76,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.True(t, cache.enabled) require.NotNil(t, cache.queriesForFeatureFlag) @@ -95,7 +97,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -105,14 +107,14 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cfg := &Config{ cacheWarmup: nil, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -133,7 +135,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.UpdateInMemorySwitchOverCacheForConfigChanges(cfg) + cache.updateStateFromConfig(cfg) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -142,38 +144,74 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { t.Parallel() - t.Run("returns cache for existing feature flag when enabled", func(t *testing.T) { + t.Run("returns operations for existing feature flag when enabled with ristretto cache", func(t *testing.T) { t.Parallel() mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ - MaxCost: 100, - NumCounters: 10000, - BufferItems: 64, + MaxCost: 10000, + NumCounters: 10000000, + IgnoreInternalCost: true, + BufferItems: 64, }) require.NoError(t, err) + query1 := "query { test1 }" + query2 := "query { test2 }" + + mockCache.Set(1, &planWithMetaData{content: query1}, 1) + mockCache.Set(2, &planWithMetaData{content: query2}, 1) + mockCache.Wait() + cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test-ff"] = mockCache result := cache.getPlanCacheForFF("test-ff") require.NotNil(t, result) - // Verify it's the same cache by comparing pointer addresses - require.Equal(t, (*ristretto.Cache[uint64, *planWithMetaData])(result), mockCache) + require.IsType(t, []*nodev1.Operation{}, result) + require.Len(t, result, 2) + + // Verify the operations contain the expected queries (order may vary) + queries := make([]string, len(result)) + for i, op := range result { + queries[i] = op.Request.Query + } + require.ElementsMatch(t, []string{query1, query2}, queries) + }) + + t.Run("returns operations for existing feature flag when enabled with operation slice", func(t *testing.T) { + t.Parallel() + expectedOps := []*nodev1.Operation{ + {Request: &nodev1.OperationRequest{Query: "query { test1 }"}}, + {Request: &nodev1.OperationRequest{Query: "query { test2 }"}}, + } + + cache := &InMemorySwitchOverCache{ + enabled: true, + queriesForFeatureFlag: make(map[string]any), + } + cache.queriesForFeatureFlag["test-ff"] = expectedOps + + result := cache.getPlanCacheForFF("test-ff") + + require.NotNil(t, result) + require.Equal(t, expectedOps, result) }) - t.Run("returns nil for non-existent feature flag", func(t *testing.T) { + t.Run("returns empty slice for non-existent feature flag", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ + logger: zap.NewNop(), enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } result := cache.getPlanCacheForFF("non-existent") - require.Nil(t, result) + require.NotNil(t, result) + require.Empty(t, result) }) t.Run("returns nil when cache is disabled", func(t *testing.T) { @@ -187,7 +225,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ enabled: false, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test-ff"] = mockCache @@ -210,14 +248,14 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.setPlanCacheForFF("test-ff", mockCache) require.Contains(t, cache.queriesForFeatureFlag, "test-ff") // Verify it's the same cache by comparing the underlying pointer - require.Equal(t, (*ristretto.Cache[uint64, *planWithMetaData])(cache.queriesForFeatureFlag["test-ff"]), mockCache) + require.Equal(t, cache.queriesForFeatureFlag["test-ff"], mockCache) }) t.Run("does not set cache when disabled", func(t *testing.T) { @@ -231,7 +269,7 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ enabled: false, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.setPlanCacheForFF("test-ff", mockCache) @@ -243,7 +281,7 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.setPlanCacheForFF("test-ff", nil) @@ -258,7 +296,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = nil cache.queriesForFeatureFlag["ff2"] = nil @@ -285,7 +323,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag[""] = nil cache.queriesForFeatureFlag["ff1"] = nil @@ -307,7 +345,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ enabled: false, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = nil @@ -328,7 +366,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ enabled: true, - queriesForFeatureFlag: make(map[string]planCache), + queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = nil @@ -343,65 +381,3 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { require.Contains(t, cache.queriesForFeatureFlag, "ff1") }) } - -func TestSwitchoverConfig_NewSwitchoverConfig(t *testing.T) { - t.Parallel() - t.Run("creates new switchover config with initialized cache", func(t *testing.T) { - t.Parallel() - cfg := NewSwitchoverConfig() - - require.NotNil(t, cfg) - require.NotNil(t, cfg.inMemorySwitchOverCache) - require.False(t, cfg.inMemorySwitchOverCache.enabled) - require.Nil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) - }) -} - -func TestSwitchoverConfig_UpdateSwitchoverConfig(t *testing.T) { - t.Parallel() - t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { - t.Parallel() - cfg := NewSwitchoverConfig() - routerConfig := &Config{ - cacheWarmup: &config.CacheWarmupConfiguration{ - Enabled: true, - Source: config.CacheWarmupSource{ - InMemorySwitchover: config.CacheWarmupInMemorySwitchover{ - Enabled: true, - }, - }, - }, - } - - cfg.UpdateSwitchoverConfig(routerConfig) - - require.True(t, cfg.inMemorySwitchOverCache.enabled) - require.NotNil(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag) - }) -} - -func TestSwitchoverConfig_CleanupFeatureFlags(t *testing.T) { - t.Parallel() - t.Run("delegates to InMemorySwitchOverCache", func(t *testing.T) { - t.Parallel() - cfg := NewSwitchoverConfig() - cfg.inMemorySwitchOverCache.enabled = true - cfg.inMemorySwitchOverCache.queriesForFeatureFlag = make(map[string]planCache) - cfg.inMemorySwitchOverCache.queriesForFeatureFlag["ff1"] = nil - cfg.inMemorySwitchOverCache.queriesForFeatureFlag["ff2"] = nil - - routerCfg := &nodev1.RouterConfig{ - FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ - ConfigByFeatureFlagName: map[string]*nodev1.FeatureFlagRouterExecutionConfig{ - "ff1": {}, - }, - }, - } - - cfg.CleanupFeatureFlags(routerCfg) - - require.Len(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, 1) - require.Contains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff1") - require.NotContains(t, cfg.inMemorySwitchOverCache.queriesForFeatureFlag, "ff2") - }) -} diff --git a/router/core/router.go b/router/core/router.go index d74c80ae0c..084ae346d8 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1176,7 +1176,7 @@ func (r *Router) Start(ctx context.Context) error { if r.switchoverConfig == nil { // This is only applicable for tests since we do not call here via the supervisor - r.switchoverConfig = NewSwitchoverConfig() + r.switchoverConfig = NewSwitchoverConfig(r.logger) } r.switchoverConfig.UpdateSwitchoverConfig(&r.Config) diff --git a/router/core/supervisor.go b/router/core/supervisor.go index 699d2ab9fb..c6e81fb482 100644 --- a/router/core/supervisor.go +++ b/router/core/supervisor.go @@ -157,6 +157,11 @@ func (rs *RouterSupervisor) Start() error { shutdown := <-rs.shutdownChan rs.logger.Debug("Got shutdown signal", zap.Bool("shutdown", shutdown)) + + if !shutdown { + rs.router.switchoverConfig.ProcessOnConfigChangeRestart() + } + if err := rs.stopRouter(); err != nil { if errors.Is(err, context.DeadlineExceeded) { rs.logger.Warn("Router shutdown deadline exceeded. Consider increasing the shutdown delay") From eb69a26db323a3a65ba66fba1386ff79ebbbe5d0 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 19 Jan 2026 20:41:03 +0530 Subject: [PATCH 20/52] fix: make in memory switcher default when cache warmer is not enabled --- .../gen/proto/wg/cosmo/node/v1/node.pb.go | 1439 +++++++++-------- connect/src/wg/cosmo/node/v1/node_pb.ts | 6 + .../src/core/bufservices/NodeService.ts | 1 + proto/wg/cosmo/node/v1/node.proto | 1 + router-tests/cache_warmup_test.go | 33 +- router/core/cache_warmup_cdn.go | 5 +- router/core/graph_server.go | 32 +- router/core/restart_switchover_config.go | 12 +- router/core/restart_switchover_config_test.go | 167 +- router/core/router_config.go | 2 +- router/gen/proto/wg/cosmo/node/v1/node.pb.go | 1439 +++++++++-------- router/pkg/config/config.go | 18 +- router/pkg/config/config.schema.json | 5 + .../pkg/config/testdata/config_defaults.json | 8 +- router/pkg/config/testdata/config_full.json | 8 +- 15 files changed, 1669 insertions(+), 1507 deletions(-) diff --git a/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go b/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go index 30527dc201..81c54440da 100644 --- a/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go +++ b/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go @@ -796,8 +796,9 @@ type RegistrationInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AccountLimits *AccountLimits `protobuf:"bytes,1,opt,name=account_limits,json=accountLimits,proto3" json:"account_limits,omitempty"` - GraphPublicKey string `protobuf:"bytes,2,opt,name=graph_public_key,json=graphPublicKey,proto3" json:"graph_public_key,omitempty"` + AccountLimits *AccountLimits `protobuf:"bytes,1,opt,name=account_limits,json=accountLimits,proto3" json:"account_limits,omitempty"` + GraphPublicKey string `protobuf:"bytes,2,opt,name=graph_public_key,json=graphPublicKey,proto3" json:"graph_public_key,omitempty"` + IsCacheWarmerEnabled bool `protobuf:"varint,3,opt,name=is_cache_warmer_enabled,json=isCacheWarmerEnabled,proto3" json:"is_cache_warmer_enabled,omitempty"` } func (x *RegistrationInfo) Reset() { @@ -846,6 +847,13 @@ func (x *RegistrationInfo) GetGraphPublicKey() string { return "" } +func (x *RegistrationInfo) GetIsCacheWarmerEnabled() bool { + if x != nil { + return x.IsCacheWarmerEnabled + } + return false +} + type AccountLimits struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4562,7 +4570,7 @@ var file_wg_cosmo_node_v1_node_proto_rawDesc = []byte{ 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 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, 0x22, 0x84, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, @@ -4570,742 +4578,745 @@ var file_wg_cosmo_node_v1_node_proto_rawDesc = []byte{ 0x0d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x61, 0x74, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, - 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x61, 0x74, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x6c, - 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0xb8, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x53, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x48, - 0x00, 0x52, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xfc, 0x04, 0x0a, 0x13, - 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x66, 0x0a, 0x19, 0x64, 0x61, 0x74, 0x61, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x61, 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x57, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, + 0x3f, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, + 0x6e, 0x67, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x11, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x61, 0x74, 0x65, + 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb8, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x66, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, + 0x11, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0xfc, 0x04, 0x0a, 0x13, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x66, + 0x0a, 0x19, 0x64, 0x61, 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x61, + 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x57, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5f, 0x0a, 0x0e, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x15, + 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x13, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x88, 0x01, 0x01, 0x1a, 0x40, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 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, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x22, 0xfa, 0x07, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, + 0x3c, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x42, 0x0a, + 0x1e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x12, 0x51, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x71, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x51, 0x4c, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x71, 0x6c, 0x12, 0x4e, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, + 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x12, 0x48, 0x0a, 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x36, + 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x70, - 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, - 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x12, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5f, 0x0a, 0x0e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x77, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, - 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x13, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x88, 0x01, 0x01, 0x1a, 0x40, - 0x0a, 0x12, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 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, - 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xfa, 0x07, 0x0a, 0x17, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x0a, - 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x72, - 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x1e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x66, 0x72, - 0x6f, 0x6d, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, - 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, - 0x68, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x51, 0x0a, 0x0e, 0x63, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x52, 0x0d, - 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x47, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x12, 0x4e, 0x0a, - 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, - 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x48, 0x0a, - 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x33, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, - 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, - 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x12, 0x4d, - 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5b, 0x0a, - 0x11, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, - 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x6e, 0x0a, 0x15, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0a, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x06, 0x53, 0x63, 0x6f, 0x70, 0x65, - 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x6e, - 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, - 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x41, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, - 0x73, 0x22, 0xef, 0x01, 0x0a, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x37, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x12, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, - 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, - 0x73, 0x12, 0x50, 0x0a, 0x18, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, - 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6f, 0x72, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x14, 0x72, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, - 0x79, 0x4f, 0x72, 0x22, 0xbb, 0x03, 0x0a, 0x12, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x16, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6d, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1a, 0x61, 0x75, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, + 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x6e, + 0x0a, 0x15, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, + 0x0a, 0x06, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x41, + 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x76, 0x0a, 0x1d, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x46, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, + 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, + 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x18, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x62, + 0x79, 0x5f, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, + 0x6f, 0x70, 0x65, 0x73, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, 0x79, 0x4f, 0x72, 0x22, 0xbb, 0x03, 0x0a, 0x12, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x60, 0x0a, + 0x17, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x1b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, - 0x20, 0x0a, 0x1e, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, - 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, - 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x48, - 0x0a, 0x21, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x4e, 0x0a, 0x10, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x11, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, - 0x0a, 0x16, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, - 0x74, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, + 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x6d, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x1a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x76, + 0x0a, 0x1d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x1b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x20, 0x0a, 0x1e, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x54, 0x79, 0x70, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, + 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x54, 0x79, 0x70, 0x65, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x12, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x21, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x5f, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, + 0x4e, 0x0a, 0x10, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, + 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x8c, 0x01, 0x0a, 0x11, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x16, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, + 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, + 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0xed, + 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, + 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7e, + 0x0a, 0x1c, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, + 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, + 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, + 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xed, + 0x05, 0x0a, 0x12, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x73, 0x52, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0xed, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, - 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7e, 0x0a, 0x1c, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x63, 0x72, - 0x65, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xed, 0x05, 0x0a, 0x12, 0x46, 0x65, 0x74, 0x63, - 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, - 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, - 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, - 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, - 0x48, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x72, 0x6c, 0x5f, 0x65, 0x6e, 0x63, - 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x75, 0x72, 0x6c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, - 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x52, 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x5f, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3d, 0x0a, + 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, + 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, + 0x75, 0x72, 0x6c, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x72, 0x6c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x12, 0x42, 0x0a, + 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x68, 0x74, 0x74, 0x70, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x1a, 0x57, 0x0a, 0x0b, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, - 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x95, 0x01, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x3e, 0x0a, 0x1c, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x22, - 0xe2, 0x03, 0x0a, 0x18, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x12, 0x3a, 0x0a, 0x05, - 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x12, 0x56, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, - 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5c, 0x0a, - 0x19, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x52, 0x16, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x63, 0x61, 0x6c, 0x61, - 0x72, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x37, 0x0a, 0x04, 0x67, - 0x72, 0x70, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, - 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, - 0x67, 0x72, 0x70, 0x63, 0x22, 0xae, 0x01, 0x0a, 0x11, 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x07, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, + 0x6c, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x52, + 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x48, + 0x00, 0x52, 0x0c, 0x68, 0x74, 0x74, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x88, + 0x01, 0x01, 0x1a, 0x57, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, + 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x95, + 0x01, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, + 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x1c, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x74, + 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x6e, + 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x74, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, 0x03, 0x0a, 0x18, 0x44, 0x61, 0x74, 0x61, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x51, 0x4c, 0x12, 0x3a, 0x0a, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x12, + 0x56, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x0e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x13, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, - 0x2c, 0x0a, 0x10, 0x53, 0x53, 0x4c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, - 0x0a, 0x0b, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x51, 0x0a, 0x12, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x52, - 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x11, 0x74, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, - 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x65, 0x6e, 0x75, 0x6d, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, - 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x12, 0x4c, - 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, - 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x4f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, + 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x66, + 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x75, 0x70, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5c, 0x0a, 0x19, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, + 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x16, 0x63, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x53, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x73, 0x12, 0x37, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x22, 0xae, 0x01, 0x0a, 0x11, + 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x37, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, + 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, - 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, - 0x01, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x10, 0x54, - 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, + 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x0e, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, + 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, + 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xa7, 0x01, 0x0a, + 0x13, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, + 0x0e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x88, + 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x2c, 0x0a, 0x10, 0x53, 0x53, 0x4c, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, 0x0a, 0x0b, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x12, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x52, 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x11, 0x74, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x6e, 0x75, + 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, + 0x0c, 0x65, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, + 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, + 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, + 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, + 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, + 0x0e, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x6c, 0x6f, 0x6f, + 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, + 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x12, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x0d, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, - 0x4e, 0x0a, 0x11, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, - 0x45, 0x0a, 0x0f, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, + 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, + 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x10, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, - 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x46, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x4e, 0x0a, 0x11, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x45, 0x0a, 0x0f, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x9f, 0x01, - 0x0a, 0x17, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x6e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, - 0xfc, 0x01, 0x0a, 0x16, 0x4e, 0x61, 0x74, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x12, 0x5c, 0x0a, 0x14, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9b, - 0x01, 0x0a, 0x17, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x22, 0x9f, 0x01, 0x0a, - 0x17, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, - 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x5d, 0x0a, + 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x3a, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x46, 0x0a, 0x10, + 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, + 0x70, 0x70, 0x65, 0x64, 0x22, 0x9f, 0x01, 0x0a, 0x17, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xfc, 0x01, 0x0a, 0x16, 0x4e, 0x61, 0x74, 0x73, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x5c, 0x0a, 0x14, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x13, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9b, 0x01, 0x0a, 0x17, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x74, + 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, + 0x69, 0x63, 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0xa8, - 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, - 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3c, 0x0a, 0x04, 0x6e, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, - 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6b, 0x61, - 0x66, 0x6b, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x72, - 0x65, 0x64, 0x69, 0x73, 0x22, 0x56, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, - 0x3b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xd5, 0x02, 0x0a, - 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, + 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3c, 0x0a, 0x04, 0x6e, + 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, + 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6b, 0x61, 0x66, + 0x6b, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x61, 0x66, 0x6b, + 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x65, + 0x64, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, + 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x22, 0x56, 0x0a, 0x17, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, + 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x3b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, - 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, - 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x17, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x22, 0x65, - 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x16, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, - 0x0a, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, - 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x54, 0x6f, 0x22, 0x41, 0x0a, 0x15, 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x11, 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x63, 0x65, - 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, - 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, - 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x22, 0xfb, 0x02, 0x0a, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x22, 0xd5, 0x02, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3f, 0x0a, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x36, + 0x0a, 0x17, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x65, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x22, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, + 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x3a, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x76, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x17, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x56, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x16, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x22, 0x41, 0x0a, 0x15, 0x55, 0x52, 0x4c, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0a, + 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x11, + 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x06, - 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, - 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x08, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x04, + 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x6e, 0x73, + 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, + 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, 0xfb, 0x02, 0x0a, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x65, 0x0a, 0x14, 0x77, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, - 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x02, 0x52, 0x14, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, - 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x77, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x22, 0x5a, 0x0a, 0x1e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, 0x6c, 0x22, 0x22, 0x0a, 0x0e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x22, 0x4d, 0x0a, 0x0f, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x4f, 0x0a, 0x1a, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, - 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, - 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, - 0x22, 0xb5, 0x02, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x3f, 0x0a, 0x03, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, + 0x75, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x88, 0x01, 0x01, + 0x12, 0x4d, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, + 0x65, 0x0a, 0x14, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x02, 0x52, 0x14, 0x77, + 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x73, 0x65, 0x53, 0x53, + 0x45, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x17, + 0x0a, 0x15, 0x5f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x5a, 0x0a, 0x1e, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x53, 0x64, 0x6c, 0x22, 0x22, 0x0a, 0x0e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x4d, 0x0a, 0x0f, 0x53, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4f, 0x0a, 0x1a, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0xb5, 0x02, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x03, 0x61, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x61, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x6e, + 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x3d, 0x0a, 0x02, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x61, 0x6e, - 0x64, 0x12, 0x41, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, - 0x6e, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x6e, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x48, 0x01, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x02, 0x6f, 0x72, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x72, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x6e, - 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6e, 0x6f, 0x74, 0x22, 0x54, 0x0a, 0x15, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7f, - 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x72, + 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6e, 0x6f, 0x74, 0x22, + 0x54, 0x0a, 0x15, 0x43, 0x61, 0x63, 0x68, 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, - 0x8c, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x56, - 0x0a, 0x09, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x70, - 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, - 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, - 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x4b, 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x32, - 0x35, 0x36, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, - 0x68, 0x61, 0x32, 0x35, 0x36, 0x48, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, - 0x82, 0x01, 0x0a, 0x1b, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, - 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, - 0x41, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, - 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, - 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5f, 0x43, - 0x53, 0x56, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, - 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x46, 0x49, 0x45, 0x4c, - 0x44, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0e, - 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0a, - 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x52, - 0x41, 0x50, 0x48, 0x51, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x53, 0x55, - 0x42, 0x10, 0x02, 0x2a, 0x5c, 0x0a, 0x0a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, - 0x0a, 0x13, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, - 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, - 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x53, 0x10, - 0x02, 0x2a, 0x87, 0x01, 0x0a, 0x0d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x1b, 0x0a, - 0x17, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x4d, 0x55, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x4f, 0x50, - 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, - 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0x34, 0x0a, 0x09, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x55, 0x42, 0x4c, - 0x49, 0x53, 0x48, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, - 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, - 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, - 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, - 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, - 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x4e, 0x56, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, - 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, - 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, - 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x2a, 0x41, 0x0a, 0x0a, 0x48, 0x54, - 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, - 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x50, - 0x55, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, - 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x04, 0x32, 0x6e, 0x0a, - 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0c, - 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x77, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7f, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x34, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x56, 0x0a, 0x09, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x5f, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x0e, 0x70, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x4b, 0x0a, + 0x0e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0a, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x82, 0x01, 0x0a, 0x1b, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, + 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, + 0x54, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, + 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, + 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x4e, + 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, + 0x41, 0x52, 0x52, 0x41, 0x59, 0x5f, 0x43, 0x53, 0x56, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0e, 0x41, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, + 0x0c, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x00, 0x12, + 0x12, 0x0a, 0x0e, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, + 0x54, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, 0x4c, 0x10, 0x01, 0x12, 0x0a, + 0x0a, 0x06, 0x50, 0x55, 0x42, 0x53, 0x55, 0x42, 0x10, 0x02, 0x2a, 0x5c, 0x0a, 0x0a, 0x4c, 0x6f, + 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x4f, 0x4b, + 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x10, 0x01, 0x12, 0x18, + 0x0a, 0x14, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, + 0x51, 0x55, 0x49, 0x52, 0x45, 0x53, 0x10, 0x02, 0x2a, 0x87, 0x01, 0x0a, 0x0d, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x4f, 0x50, + 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, + 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, + 0x52, 0x59, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, + 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, + 0x10, 0x03, 0x2a, 0x34, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x0b, 0x0a, 0x07, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, + 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, + 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, + 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, + 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x4e, 0x56, + 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, + 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x50, 0x4c, 0x41, + 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, + 0x02, 0x2a, 0x41, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, + 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x53, 0x54, + 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x54, 0x49, 0x4f, + 0x4e, 0x53, 0x10, 0x04, 0x32, 0x6e, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0c, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xcf, 0x01, - 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x77, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x67, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6e, 0x6f, 0x64, 0x65, 0x76, 0x31, 0xa2, 0x02, - 0x03, 0x57, 0x43, 0x4e, 0xaa, 0x02, 0x10, 0x57, 0x67, 0x2e, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, - 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x57, 0x67, 0x5c, - 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x57, 0x67, 0x3a, 0x3a, - 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x3a, 0x3a, 0x4e, 0x6f, 0x64, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0xcf, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x4e, + 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x67, 0x72, 0x61, + 0x70, 0x68, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x2d, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x67, + 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6e, + 0x6f, 0x64, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x57, 0x43, 0x4e, 0xaa, 0x02, 0x10, 0x57, 0x67, + 0x2e, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x10, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x1c, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, + 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x13, 0x57, 0x67, 0x3a, 0x3a, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x3a, 0x3a, 0x4e, 0x6f, + 0x64, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/connect/src/wg/cosmo/node/v1/node_pb.ts b/connect/src/wg/cosmo/node/v1/node_pb.ts index c13e62f9b8..4ad64bd5e3 100644 --- a/connect/src/wg/cosmo/node/v1/node_pb.ts +++ b/connect/src/wg/cosmo/node/v1/node_pb.ts @@ -543,6 +543,11 @@ export class RegistrationInfo extends Message { */ graphPublicKey = ""; + /** + * @generated from field: bool is_cache_warmer_enabled = 3; + */ + isCacheWarmerEnabled = false; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -553,6 +558,7 @@ export class RegistrationInfo extends Message { static readonly fields: FieldList = proto3.util.newFieldList(() => [ { no: 1, name: "account_limits", kind: "message", T: AccountLimits }, { no: 2, name: "graph_public_key", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "is_cache_warmer_enabled", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): RegistrationInfo { diff --git a/controlplane/src/core/bufservices/NodeService.ts b/controlplane/src/core/bufservices/NodeService.ts index 77537814f2..e00ebc6136 100644 --- a/controlplane/src/core/bufservices/NodeService.ts +++ b/controlplane/src/core/bufservices/NodeService.ts @@ -55,6 +55,7 @@ export default function (opts: RouterOptions): Partial Date: Mon, 19 Jan 2026 21:05:38 +0530 Subject: [PATCH 21/52] fix: review comments --- router/core/restart_switchover_config.go | 6 ++++-- router/core/router_config.go | 3 +-- router/pkg/config/config.schema.json | 14 -------------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 5af0db8c6e..6a13b61050 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -119,8 +119,10 @@ func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { defer c.mu.Unlock() switchoverMap := make(map[string]any) - for k, data := range c.queriesForFeatureFlag { - switchoverMap[k] = convertToNodeOperation(data.(planCache)) + for k, v := range c.queriesForFeatureFlag { + if cache, ok := v.(planCache); ok { + switchoverMap[k] = convertToNodeOperation(cache) + } } c.queriesForFeatureFlag = switchoverMap } diff --git a/router/core/router_config.go b/router/core/router_config.go index a1ce62698f..541a5c469f 100644 --- a/router/core/router_config.go +++ b/router/core/router_config.go @@ -314,11 +314,10 @@ func (c *Config) Usage() map[string]any { if c.cacheWarmup != nil && c.cacheWarmup.Enabled { if c.cacheWarmup.Source.Filesystem != nil { usage["cache_warmup_source"] = "filesystem" - } else if c.cacheWarmup.InMemorySwitchoverFallback { - usage["cache_warmup_source"] = "in_memory_switchover" } else { usage["cache_warmup_source"] = "cdn" } + usage["cache_warmup_in_memory_switchover_enabled"] = c.cacheWarmup.InMemorySwitchoverFallback usage["cache_warmup_workers"] = c.cacheWarmup.Workers usage["cache_warmup_items_per_second"] = c.cacheWarmup.ItemsPerSecond usage["cache_warmup_timeout"] = c.cacheWarmup.Timeout.String() diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json index b61a7bca87..7169fb8623 100644 --- a/router/pkg/config/config.schema.json +++ b/router/pkg/config/config.schema.json @@ -2400,25 +2400,11 @@ "format": "file-path" } } - }, - "in_memory_switchover": { - "type": "object", - "description": "The in memory switchover which reuses query plans for subsequent starts.", - "additionalProperties": false, - "properties": { - "enabled": { - "type": "boolean", - "description": "Is in memory switchover enabled" - } - } } }, "oneOf": [ { "required": ["filesystem"] - }, - { - "required": ["in_memory_switchover"] } ] }, From a7adf3dfe767d8c064430bd461bd5b301cdad2c0 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 20:33:19 +0530 Subject: [PATCH 22/52] fix: updates --- router/core/restart_switchover_config.go | 32 +++------ router/core/restart_switchover_config_test.go | 67 ++----------------- router/core/router.go | 3 +- 3 files changed, 19 insertions(+), 83 deletions(-) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 6a13b61050..2655047a75 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -25,8 +25,8 @@ func NewSwitchoverConfig(logger *zap.Logger) *SwitchoverConfig { } } -func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config) { - s.inMemorySwitchOverCache.updateStateFromConfig(config) +func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config, isCosmoCacheWarmerEnabled bool) { + s.inMemorySwitchOverCache.updateStateFromConfig(config, isCosmoCacheWarmerEnabled) } func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { @@ -38,6 +38,9 @@ func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { // graph mux, because we need to initialize everything from the start // This causes problems in using the previous planCache reference as it gets closed, so we need to // copy it over before it gets closed, and we restart with config changes + + // There can be inflight requests when this is called even though it's called in the restart path, + // This is because this is called before the router instance is shutdown before being reloaded s.inMemorySwitchOverCache.processOnConfigChangeRestart() } @@ -48,14 +51,15 @@ type InMemorySwitchOverCache struct { logger *zap.Logger } -func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config) { - c.mu.Lock() - defer c.mu.Unlock() - +func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoCacheWarmerEnabled bool) { c.enabled = config.cacheWarmup != nil && + !isCosmoCacheWarmerEnabled && // We only enable in-memory switchover cache if the cosmo cache warmer is not enabled config.cacheWarmup.Enabled && config.cacheWarmup.InMemorySwitchoverFallback + c.mu.Lock() + defer c.mu.Unlock() + // If the configuration change occurred which disabled or enabled the switchover cache, we need to update the internal state if c.enabled { // Only initialize if its nil (because its a first start or it was disabled before) @@ -100,16 +104,6 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache c.queriesForFeatureFlag[featureFlagKey] = cache } -func (c *InMemorySwitchOverCache) deletePlanCacheForFF(featureFlagKey string) { - if !c.enabled { - return - } - - c.mu.Lock() - defer c.mu.Unlock() - delete(c.queriesForFeatureFlag, featureFlagKey) -} - func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { if !c.enabled { return @@ -128,11 +122,7 @@ func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { } func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { - if !c.enabled { - return - } - - if routerCfg.FeatureFlagConfigs == nil { + if !c.enabled || routerCfg.FeatureFlagConfigs == nil { return } diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 3077f97d34..4cccccd9d1 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -24,7 +24,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.True(t, cache.enabled) require.NotNil(t, cache.queriesForFeatureFlag) @@ -45,7 +45,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -68,7 +68,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.True(t, cache.enabled) require.NotNil(t, cache.queriesForFeatureFlag) @@ -89,7 +89,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -106,7 +106,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cacheWarmup: nil, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -123,7 +123,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg) + cache.updateStateFromConfig(cfg, false) require.False(t, cache.enabled) require.Nil(t, cache.queriesForFeatureFlag) @@ -370,61 +370,6 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { }) } -func TestInMemorySwitchOverCache_DeletePlanCacheForFF(t *testing.T) { - t.Parallel() - t.Run("deletes cache for feature flag when enabled", func(t *testing.T) { - t.Parallel() - mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ - MaxCost: 100, - NumCounters: 10000, - BufferItems: 64, - }) - require.NoError(t, err) - - cache := &InMemorySwitchOverCache{ - enabled: true, - queriesForFeatureFlag: make(map[string]any), - } - cache.queriesForFeatureFlag["test-ff"] = mockCache - - cache.deletePlanCacheForFF("test-ff") - - require.NotContains(t, cache.queriesForFeatureFlag, "test-ff") - }) - - t.Run("does not delete when cache is disabled", func(t *testing.T) { - t.Parallel() - mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ - MaxCost: 100, - NumCounters: 10000, - BufferItems: 64, - }) - require.NoError(t, err) - - cache := &InMemorySwitchOverCache{ - enabled: false, - queriesForFeatureFlag: make(map[string]any), - } - cache.queriesForFeatureFlag["test-ff"] = mockCache - - cache.deletePlanCacheForFF("test-ff") - - require.Contains(t, cache.queriesForFeatureFlag, "test-ff") - }) - - t.Run("deleting non-existent key does not cause error", func(t *testing.T) { - t.Parallel() - cache := &InMemorySwitchOverCache{ - enabled: true, - queriesForFeatureFlag: make(map[string]any), - } - - require.NotPanics(t, func() { - cache.deletePlanCacheForFF("non-existent") - }) - }) -} - func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { t.Parallel() t.Run("converts ristretto caches to operation slices", func(t *testing.T) { diff --git a/router/core/router.go b/router/core/router.go index 084ae346d8..0943798fb5 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1178,7 +1178,8 @@ func (r *Router) Start(ctx context.Context) error { // This is only applicable for tests since we do not call here via the supervisor r.switchoverConfig = NewSwitchoverConfig(r.logger) } - r.switchoverConfig.UpdateSwitchoverConfig(&r.Config) + + r.switchoverConfig.UpdateSwitchoverConfig(&r.Config, r.registrationInfo.IsCacheWarmerEnabled) // Start the server with the static config without polling if r.staticExecutionConfig != nil { From 6d23b7e3d4518d8ea1341ebac74f26b99ed55415 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 20:36:37 +0530 Subject: [PATCH 23/52] fix: go mod --- router-tests/go.sum | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router-tests/go.sum b/router-tests/go.sum index 0003e0fa37..7ed42c1ba6 100644 --- a/router-tests/go.sum +++ b/router-tests/go.sum @@ -351,7 +351,8 @@ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+x github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTBjW+SZK4mhxTTBVpxcqeBgWF1Rfmltbfk= github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243 h1:yNchVRa9agA6JtK/X9ZBv8BW/8sm4kl2eaFD6rh6D90= -github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4=github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= +github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= +github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= From ceabb755c60f8e199d857b475e5eeebfa24bfbd0 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 20:55:32 +0530 Subject: [PATCH 24/52] fix: update enabled --- router/core/restart_switchover_config.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 2655047a75..683cd9d782 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -2,6 +2,7 @@ package core import ( "sync" + "sync/atomic" "go.uber.org/zap" @@ -45,14 +46,14 @@ func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { } type InMemorySwitchOverCache struct { - enabled bool + enabled atomic.Bool mu sync.RWMutex queriesForFeatureFlag map[string]any logger *zap.Logger } func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoCacheWarmerEnabled bool) { - c.enabled = config.cacheWarmup != nil && + enabled := config.cacheWarmup != nil && !isCosmoCacheWarmerEnabled && // We only enable in-memory switchover cache if the cosmo cache warmer is not enabled config.cacheWarmup.Enabled && config.cacheWarmup.InMemorySwitchoverFallback @@ -60,8 +61,10 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC c.mu.Lock() defer c.mu.Unlock() + c.enabled.Store(enabled) + // If the configuration change occurred which disabled or enabled the switchover cache, we need to update the internal state - if c.enabled { + if enabled { // Only initialize if its nil (because its a first start or it was disabled before) if c.queriesForFeatureFlag == nil { c.queriesForFeatureFlag = make(map[string]any) @@ -72,7 +75,7 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC } func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { - if !c.enabled { + if !c.enabled.Load() { return nil } @@ -95,7 +98,7 @@ func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*no } func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { - if !c.enabled || cache == nil { + if !c.enabled.Load() || cache == nil { return } @@ -105,7 +108,7 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache } func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { - if !c.enabled { + if !c.enabled.Load() { return } @@ -122,7 +125,7 @@ func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { } func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { - if !c.enabled || routerCfg.FeatureFlagConfigs == nil { + if !c.enabled.Load() || routerCfg.FeatureFlagConfigs == nil { return } From ae920ef84c8184422bf72a0d713251eb71113066 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 20:58:18 +0530 Subject: [PATCH 25/52] fix: update enabled --- router/core/graph_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 67de3d38db..84f711c071 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1308,7 +1308,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.enabled) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.enabled.Load()) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { From 3cfca20f38bac9d2b49ced7e7640644d45842803 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 21:05:53 +0530 Subject: [PATCH 26/52] fix: review comments --- router/core/restart_switchover_config_test.go | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 4cccccd9d1..079bf14f9a 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -26,7 +26,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.True(t, cache.enabled) + require.True(t, cache.enabled.Load()) require.NotNil(t, cache.queriesForFeatureFlag) require.Empty(t, cache.queriesForFeatureFlag) }) @@ -34,9 +34,9 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t t.Run("disable cache from enabled state", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["test"] = nil cfg := &Config{ @@ -47,7 +47,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled) + require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -57,9 +57,9 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t existingMap["test"] = nil cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: existingMap, } + cache.enabled.Store(true) cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -70,7 +70,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.True(t, cache.enabled) + require.True(t, cache.enabled.Load()) require.NotNil(t, cache.queriesForFeatureFlag) require.Len(t, cache.queriesForFeatureFlag, 1) require.Contains(t, cache.queriesForFeatureFlag, "test") @@ -79,9 +79,9 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t t.Run("update when already disabled", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: false, queriesForFeatureFlag: nil, } + cache.enabled.Store(false) cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -91,16 +91,16 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled) + require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("nil cacheWarmup config disables cache", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cfg := &Config{ cacheWarmup: nil, @@ -108,7 +108,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled) + require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -125,7 +125,7 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled) + require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) } @@ -150,9 +150,9 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { mockCache.Wait() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["test-ff"] = mockCache result := cache.getPlanCacheForFF("test-ff") @@ -177,9 +177,9 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { } cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["test-ff"] = expectedOps result := cache.getPlanCacheForFF("test-ff") @@ -192,9 +192,9 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ logger: zap.NewNop(), - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) result := cache.getPlanCacheForFF("non-existent") @@ -212,9 +212,9 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { require.NoError(t, err) cache := &InMemorySwitchOverCache{ - enabled: false, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(false) cache.queriesForFeatureFlag["test-ff"] = mockCache result := cache.getPlanCacheForFF("test-ff") @@ -235,9 +235,9 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { require.NoError(t, err) cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.setPlanCacheForFF("test-ff", mockCache) @@ -256,9 +256,9 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { require.NoError(t, err) cache := &InMemorySwitchOverCache{ - enabled: false, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(false) cache.setPlanCacheForFF("test-ff", mockCache) @@ -268,9 +268,9 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { t.Run("does not set nil cache", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.setPlanCacheForFF("test-ff", nil) @@ -283,9 +283,9 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("removes unused feature flags", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = nil cache.queriesForFeatureFlag["ff2"] = nil cache.queriesForFeatureFlag["ff3"] = nil @@ -310,9 +310,9 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("keeps empty string feature flag", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag[""] = nil cache.queriesForFeatureFlag["ff1"] = nil @@ -332,9 +332,9 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("does nothing when cache is disabled", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: false, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(false) cache.queriesForFeatureFlag["ff1"] = nil routerCfg := &nodev1.RouterConfig{ @@ -353,9 +353,9 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("does nothing when FeatureFlagConfigs is nil", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = nil routerCfg := &nodev1.RouterConfig{ @@ -399,9 +399,9 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { mockCache2.Wait() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = mockCache1 cache.queriesForFeatureFlag["ff2"] = mockCache2 @@ -430,9 +430,9 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { require.NoError(t, err) cache := &InMemorySwitchOverCache{ - enabled: false, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(false) cache.queriesForFeatureFlag["test-ff"] = mockCache cache.processOnConfigChangeRestart() @@ -444,9 +444,9 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { t.Run("handles empty cache", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - enabled: true, queriesForFeatureFlag: make(map[string]any), } + cache.enabled.Store(true) require.NotPanics(t, func() { cache.processOnConfigChangeRestart() From d4ad3993c01bd6b927948a1805877ee74d95b18d Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 21:18:25 +0530 Subject: [PATCH 27/52] fix: review comments --- router/core/graph_server.go | 3 +- router/core/restart_switchover_config.go | 43 +++++++------ router/core/restart_switchover_config_test.go | 60 +++---------------- 3 files changed, 31 insertions(+), 75 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 84f711c071..ca544207bf 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1308,7 +1308,8 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.enabled.Load()) + storeQueryContent := opts.SwitchoverConfig.inMemorySwitchOverCache.queriesForFeatureFlag != nil + operationPlanner := NewOperationPlanner(executor, gm.planCache, storeQueryContent) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 683cd9d782..8932eb7010 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -1,10 +1,8 @@ package core import ( - "sync" - "sync/atomic" - "go.uber.org/zap" + "sync" "github.com/dgraph-io/ristretto/v2" @@ -46,7 +44,6 @@ func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { } type InMemorySwitchOverCache struct { - enabled atomic.Bool mu sync.RWMutex queriesForFeatureFlag map[string]any logger *zap.Logger @@ -61,27 +58,27 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC c.mu.Lock() defer c.mu.Unlock() - c.enabled.Store(enabled) - // If the configuration change occurred which disabled or enabled the switchover cache, we need to update the internal state if enabled { - // Only initialize if its nil (because its a first start or it was disabled before) + // Only initialize if its nil because its a first start, we dont want to override any old data in a map if c.queriesForFeatureFlag == nil { c.queriesForFeatureFlag = make(map[string]any) } + return } else { + // Reset the map to free up memory c.queriesForFeatureFlag = nil } } func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { - if !c.enabled.Load() { - return nil - } - c.mu.RLock() defer c.mu.RUnlock() + if c.queriesForFeatureFlag == nil { + return nil + } + switch cache := c.queriesForFeatureFlag[featureFlagKey].(type) { case planCache: return convertToNodeOperation(cache) @@ -98,23 +95,23 @@ func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*no } func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { - if !c.enabled.Load() || cache == nil { - return - } - c.mu.Lock() defer c.mu.Unlock() - c.queriesForFeatureFlag[featureFlagKey] = cache -} -func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { - if !c.enabled.Load() { + if c.queriesForFeatureFlag == nil || cache == nil { return } + c.queriesForFeatureFlag[featureFlagKey] = cache +} +func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { c.mu.Lock() defer c.mu.Unlock() + if c.queriesForFeatureFlag == nil { + return + } + switchoverMap := make(map[string]any) for k, v := range c.queriesForFeatureFlag { if cache, ok := v.(planCache); ok { @@ -125,13 +122,13 @@ func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { } func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { - if !c.enabled.Load() || routerCfg.FeatureFlagConfigs == nil { - return - } - c.mu.Lock() defer c.mu.Unlock() + if c.queriesForFeatureFlag == nil || routerCfg.FeatureFlagConfigs == nil { + return + } + ffNames := make(map[string]struct{}) for ffName := range routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName { ffNames[ffName] = struct{}{} diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 079bf14f9a..928180e6aa 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -26,7 +26,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.True(t, cache.enabled.Load()) require.NotNil(t, cache.queriesForFeatureFlag) require.Empty(t, cache.queriesForFeatureFlag) }) @@ -36,7 +35,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["test"] = nil cfg := &Config{ @@ -47,7 +45,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -59,7 +56,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: existingMap, } - cache.enabled.Store(true) cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -70,7 +66,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.True(t, cache.enabled.Load()) require.NotNil(t, cache.queriesForFeatureFlag) require.Len(t, cache.queriesForFeatureFlag, 1) require.Contains(t, cache.queriesForFeatureFlag, "test") @@ -81,7 +76,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: nil, } - cache.enabled.Store(false) cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -91,7 +85,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -100,7 +93,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cfg := &Config{ cacheWarmup: nil, @@ -108,7 +100,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -125,7 +116,6 @@ func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t cache.updateStateFromConfig(cfg, false) - require.False(t, cache.enabled.Load()) require.Nil(t, cache.queriesForFeatureFlag) }) } @@ -152,7 +142,6 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["test-ff"] = mockCache result := cache.getPlanCacheForFF("test-ff") @@ -179,7 +168,6 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["test-ff"] = expectedOps result := cache.getPlanCacheForFF("test-ff") @@ -194,7 +182,6 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { logger: zap.NewNop(), queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) result := cache.getPlanCacheForFF("non-existent") @@ -204,18 +191,9 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { t.Run("returns nil when cache is disabled", func(t *testing.T) { t.Parallel() - mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ - MaxCost: 100, - NumCounters: 10000, - BufferItems: 64, - }) - require.NoError(t, err) - cache := &InMemorySwitchOverCache{ - queriesForFeatureFlag: make(map[string]any), + queriesForFeatureFlag: nil, } - cache.enabled.Store(false) - cache.queriesForFeatureFlag["test-ff"] = mockCache result := cache.getPlanCacheForFF("test-ff") @@ -237,7 +215,6 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.setPlanCacheForFF("test-ff", mockCache) @@ -256,13 +233,12 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { require.NoError(t, err) cache := &InMemorySwitchOverCache{ - queriesForFeatureFlag: make(map[string]any), + queriesForFeatureFlag: nil, } - cache.enabled.Store(false) cache.setPlanCacheForFF("test-ff", mockCache) - require.NotContains(t, cache.queriesForFeatureFlag, "test-ff") + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("does not set nil cache", func(t *testing.T) { @@ -270,7 +246,6 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.setPlanCacheForFF("test-ff", nil) @@ -285,7 +260,6 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = nil cache.queriesForFeatureFlag["ff2"] = nil cache.queriesForFeatureFlag["ff3"] = nil @@ -312,7 +286,6 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag[""] = nil cache.queriesForFeatureFlag["ff1"] = nil @@ -332,10 +305,8 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("does nothing when cache is disabled", func(t *testing.T) { t.Parallel() cache := &InMemorySwitchOverCache{ - queriesForFeatureFlag: make(map[string]any), + queriesForFeatureFlag: nil, } - cache.enabled.Store(false) - cache.queriesForFeatureFlag["ff1"] = nil routerCfg := &nodev1.RouterConfig{ FeatureFlagConfigs: &nodev1.FeatureFlagRouterExecutionConfigs{ @@ -345,9 +316,8 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache.cleanupUnusedFeatureFlags(routerCfg) - // Should still have ff1 because cleanup is skipped when disabled - require.Len(t, cache.queriesForFeatureFlag, 1) - require.Contains(t, cache.queriesForFeatureFlag, "ff1") + // Should still be nil because cleanup is skipped when disabled + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("does nothing when FeatureFlagConfigs is nil", func(t *testing.T) { @@ -355,7 +325,6 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = nil routerCfg := &nodev1.RouterConfig{ @@ -401,7 +370,6 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) cache.queriesForFeatureFlag["ff1"] = mockCache1 cache.queriesForFeatureFlag["ff2"] = mockCache2 @@ -422,23 +390,14 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { t.Run("does nothing when cache is disabled", func(t *testing.T) { t.Parallel() - mockCache, err := ristretto.NewCache(&ristretto.Config[uint64, *planWithMetaData]{ - MaxCost: 100, - NumCounters: 10000, - BufferItems: 64, - }) - require.NoError(t, err) - cache := &InMemorySwitchOverCache{ - queriesForFeatureFlag: make(map[string]any), + queriesForFeatureFlag: nil, } - cache.enabled.Store(false) - cache.queriesForFeatureFlag["test-ff"] = mockCache cache.processOnConfigChangeRestart() - // Should remain as ristretto cache since processing is skipped - require.IsType(t, mockCache, cache.queriesForFeatureFlag["test-ff"]) + // Should remain nil since processing is skipped + require.Nil(t, cache.queriesForFeatureFlag) }) t.Run("handles empty cache", func(t *testing.T) { @@ -446,7 +405,6 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { cache := &InMemorySwitchOverCache{ queriesForFeatureFlag: make(map[string]any), } - cache.enabled.Store(true) require.NotPanics(t, func() { cache.processOnConfigChangeRestart() From 5d79a9e7e943befbf3332d1bfced72524a75e2ca Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 21:20:32 +0530 Subject: [PATCH 28/52] fix: feature flags didnt pass in cosmo flag status --- router/core/graph_server.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index ca544207bf..cfc6f3f678 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -292,7 +292,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC s.logger.Info("Feature flags enabled", zap.Strings("flags", maps.Keys(featureFlagConfigMap))) } - multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, switchoverConfig) + multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, switchoverConfig, cosmoCacheWarmerEnabled) if err != nil { return nil, fmt.Errorf("failed to build feature flag handler: %w", err) } @@ -443,6 +443,7 @@ func (s *graphServer) buildMultiGraphHandler( baseMux *chi.Mux, featureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig, switchoverConfig *SwitchoverConfig, + cosmoCacheWarmerEnabled bool, ) (http.HandlerFunc, error) { if len(featureFlagConfigs) == 0 { return baseMux.ServeHTTP, nil @@ -453,11 +454,12 @@ func (s *graphServer) buildMultiGraphHandler( // Build all the muxes for the feature flags in serial to avoid any race conditions for featureFlagName, executionConfig := range featureFlagConfigs { gm, err := s.buildGraphMux(ctx, BuildGraphMuxOptions{ - FeatureFlagName: featureFlagName, - RouterConfigVersion: executionConfig.GetVersion(), - EngineConfig: executionConfig.GetEngineConfig(), - ConfigSubgraphs: executionConfig.Subgraphs, - SwitchoverConfig: switchoverConfig, + FeatureFlagName: featureFlagName, + RouterConfigVersion: executionConfig.GetVersion(), + EngineConfig: executionConfig.GetEngineConfig(), + ConfigSubgraphs: executionConfig.Subgraphs, + SwitchoverConfig: switchoverConfig, + CosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, }) if err != nil { return nil, fmt.Errorf("failed to build mux for feature flag '%s': %w", featureFlagName, err) From 7f099f5f7d6a48f0115548e25cc635a3fb58b34f Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 21:31:10 +0530 Subject: [PATCH 29/52] fix: nil pointer --- router/core/router.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router/core/router.go b/router/core/router.go index e9addd9baa..515a7e6feb 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -1180,7 +1180,8 @@ func (r *Router) Start(ctx context.Context) error { r.switchoverConfig = NewSwitchoverConfig(r.logger) } - r.switchoverConfig.UpdateSwitchoverConfig(&r.Config, r.registrationInfo.IsCacheWarmerEnabled) + isCacheWarmerEnabled := r.registrationInfo != nil && r.registrationInfo.IsCacheWarmerEnabled + r.switchoverConfig.UpdateSwitchoverConfig(&r.Config, isCacheWarmerEnabled) // Start the server with the static config without polling if r.staticExecutionConfig != nil { From f382e46b333028bdcc51f53bb6b70915f53c8d21 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 20 Jan 2026 21:35:55 +0530 Subject: [PATCH 30/52] fix: review comments --- router/core/graph_server.go | 3 +-- router/core/restart_switchover_config.go | 11 ++++++++++ router/core/restart_switchover_config_test.go | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index cfc6f3f678..3254f27b9a 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1310,8 +1310,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - storeQueryContent := opts.SwitchoverConfig.inMemorySwitchOverCache.queriesForFeatureFlag != nil - operationPlanner := NewOperationPlanner(executor, gm.planCache, storeQueryContent) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.IsEnabled()) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 8932eb7010..9b8bd3a595 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -71,6 +71,13 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC } } +func (c *InMemorySwitchOverCache) IsEnabled() bool { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.queriesForFeatureFlag != nil +} + func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { c.mu.RLock() defer c.mu.RUnlock() @@ -147,6 +154,10 @@ func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.Ro func convertToNodeOperation(data planCache) []*nodev1.Operation { items := make([]*nodev1.Operation, 0) + + // Ensure any buffered writes have been applied + data.Wait() + data.IterValues(func(v *planWithMetaData) (stop bool) { items = append(items, &nodev1.Operation{ Request: &nodev1.OperationRequest{Query: v.content}, diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 928180e6aa..9b14eae496 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -413,3 +413,25 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { require.Empty(t, cache.queriesForFeatureFlag) }) } + +func TestInMemorySwitchOverCache_IsEnabled(t *testing.T) { + t.Parallel() + t.Run("returns true when cache is enabled", func(t *testing.T) { + t.Parallel() + cache := &InMemorySwitchOverCache{ + queriesForFeatureFlag: make(map[string]any), + } + + require.True(t, cache.IsEnabled()) + }) + + t.Run("returns false when cache is disabled", func(t *testing.T) { + t.Parallel() + cache := &InMemorySwitchOverCache{ + queriesForFeatureFlag: nil, + } + + require.False(t, cache.IsEnabled()) + }) + +} From 9a3451549b882546cca20d66d6f39b3b7fa3e4b1 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 15:52:14 +0530 Subject: [PATCH 31/52] fix: use the new ristretto version --- router-tests/go.mod | 3 +-- router-tests/go.sum | 4 ++-- router/go.mod | 4 +--- router/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/router-tests/go.mod b/router-tests/go.mod index 9b42d82d21..8af7b136d9 100644 --- a/router-tests/go.mod +++ b/router-tests/go.mod @@ -63,7 +63,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/dgraph-io/ristretto/v2 v2.4.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/cli v28.2.2+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -204,7 +204,6 @@ replace ( // Use what is best for your personal workflow. See CONTRIBUTING.md for more information replace ( - github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c github.com/wundergraph/cosmo/demo => ../demo github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects => ../demo/pkg/subgraphs/projects github.com/wundergraph/cosmo/router => ../router diff --git a/router-tests/go.sum b/router-tests/go.sum index 7ed42c1ba6..c546c44af1 100644 --- a/router-tests/go.sum +++ b/router-tests/go.sum @@ -65,6 +65,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -352,8 +354,6 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243 h1:yNchVRa9agA6JtK/X9ZBv8BW/8sm4kl2eaFD6rh6D90= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= -github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= -github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 h1:FnBeRrxr7OU4VvAzt5X7s6266i6cSVkkFPS0TuXWbIg= github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= diff --git a/router/go.mod b/router/go.mod index cf8aebe31c..4f3b96ed46 100644 --- a/router/go.mod +++ b/router/go.mod @@ -63,7 +63,7 @@ require ( github.com/alicebob/miniredis/v2 v2.34.0 github.com/caarlos0/env/v11 v11.3.1 github.com/cep21/circuit/v4 v4.0.0 - github.com/dgraph-io/ristretto/v2 v2.0.0 + github.com/dgraph-io/ristretto/v2 v2.4.0 github.com/expr-lang/expr v1.17.7 github.com/goccy/go-json v0.10.3 github.com/google/go-containerregistry v0.20.3 @@ -195,5 +195,3 @@ replace ( // Use what is best for your personal workflow. See CONTRIBUTING.md for more information //replace github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2 - -replace github.com/dgraph-io/ristretto/v2 => github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c diff --git a/router/go.sum b/router/go.sum index 5d57436d4b..0138c90e83 100644 --- a/router/go.sum +++ b/router/go.sum @@ -54,6 +54,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/ristretto/v2 v2.4.0 h1:I/w09yLjhdcVD2QV192UJcq8dPBaAJb9pOuMyNy0XlU= +github.com/dgraph-io/ristretto/v2 v2.4.0/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -322,8 +324,6 @@ github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083 h1:8/D7f8gKxTB github.com/wundergraph/astjson v0.0.0-20250106123708-be463c97e083/go.mod h1:eOTL6acwctsN4F3b7YE+eE2t8zcJ/doLm9sZzsxxxrE= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243 h1:yNchVRa9agA6JtK/X9ZBv8BW/8sm4kl2eaFD6rh6D90= github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.243/go.mod h1:mX25ASEQiKamxaFSK6NZihh0oDCigIuzro30up4mFH4= -github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c h1:NHsm70rt2oJON5EiEODrv7f2jCTv8Tipb40DXUjWGIY= -github.com/wundergraph/ristretto/v2 v2.0.0-20260118191717-5112a101c70c/go.mod h1:0KsrXtXvnv0EqnzyowllbVJB8yBonswa2lTCK2gGo9E= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= From 42c8c8123af4c4ea0e2efa8ba657c86475ca70cc Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 17:26:25 +0530 Subject: [PATCH 32/52] fix: formatting --- router-tests/cache_warmup_test.go | 24 +++++++------------ router/core/cache_warmup_cdn.go | 3 +-- router/core/cache_warmup_plans.go | 1 + router/core/restart_switchover_config.go | 3 +-- router/core/restart_switchover_config_test.go | 4 +--- 5 files changed, 13 insertions(+), 22 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index bd5f649e01..7fb9037863 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -10,24 +10,18 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/wundergraph/cosmo/router-tests/testenv" + "github.com/wundergraph/cosmo/router/core" + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" + "github.com/wundergraph/cosmo/router/pkg/config" "github.com/wundergraph/cosmo/router/pkg/controlplane/configpoller" - + "github.com/wundergraph/cosmo/router/pkg/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" - - nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" - "go.opentelemetry.io/otel/sdk/metric/metricdata" - - "github.com/wundergraph/cosmo/router/pkg/otel" - - "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.uber.org/zap" - - "github.com/wundergraph/cosmo/router-tests/testenv" - "github.com/wundergraph/cosmo/router/core" - "github.com/wundergraph/cosmo/router/pkg/config" ) func TestCacheWarmup(t *testing.T) { @@ -1141,13 +1135,13 @@ engine: listenString1 := "after1" updateConfig(t, xEnv, ctx, listenString1, getConfigString(listenString1)) res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{Query: `query { hello }`}) - assert.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) // Verify cache persisted on restart listenString2 := "after2" updateConfig(t, xEnv, ctx, listenString2, getConfigString(listenString2)) res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{Query: `query { hello }`}) - assert.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + require.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) }) require.NoError(t, err) diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index dc07e635c3..9582d7f9fe 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -10,8 +10,6 @@ import ( "net/url" nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" - "google.golang.org/protobuf/encoding/protojson" - "github.com/wundergraph/cosmo/router/internal/httpclient" "github.com/wundergraph/cosmo/router/internal/jwt" "go.opentelemetry.io/otel/codes" @@ -19,6 +17,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "google.golang.org/protobuf/encoding/protojson" ) var _ CacheWarmupSource = (*CDNSource)(nil) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index 55469ea8b0..e2f98ee037 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -2,6 +2,7 @@ package core import ( "context" + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" "go.uber.org/zap" ) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 9b8bd3a595..d7bc895a92 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -1,12 +1,11 @@ package core import ( - "go.uber.org/zap" "sync" "github.com/dgraph-io/ristretto/v2" - nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" + "go.uber.org/zap" ) type planCache = *ristretto.Cache[uint64, *planWithMetaData] diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 9b14eae496..42be015b5d 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -3,13 +3,11 @@ package core import ( "testing" - "go.uber.org/zap" - "github.com/dgraph-io/ristretto/v2" "github.com/stretchr/testify/require" - nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" "github.com/wundergraph/cosmo/router/pkg/config" + "go.uber.org/zap" ) func TestInMemorySwitchOverCache_UpdateInMemorySwitchOverCacheForConfigChanges(t *testing.T) { From ef33a6c663c07bbf5180343caffcf86f36b16160 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 17:48:21 +0530 Subject: [PATCH 33/52] fix: review comments --- router/core/restart_switchover_config.go | 13 ++++--------- router/core/restart_switchover_config_test.go | 6 +++--- router/core/supervisor.go | 2 +- router/pkg/config/config.go | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index d7bc895a92..1694f96e88 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -31,7 +31,7 @@ func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } -func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { +func (s *SwitchoverConfig) ProcessOnConfigChangeRouterInstanceRestart() { // For cases of router config changes (not execution config), we shut down before creating the // graph mux, because we need to initialize everything from the start // This causes problems in using the previous planCache reference as it gets closed, so we need to @@ -39,7 +39,7 @@ func (s *SwitchoverConfig) ProcessOnConfigChangeRestart() { // There can be inflight requests when this is called even though it's called in the restart path, // This is because this is called before the router instance is shutdown before being reloaded - s.inMemorySwitchOverCache.processOnConfigChangeRestart() + s.inMemorySwitchOverCache.extractQueriesAndOverridePlanCache() } type InMemorySwitchOverCache struct { @@ -110,7 +110,7 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache c.queriesForFeatureFlag[featureFlagKey] = cache } -func (c *InMemorySwitchOverCache) processOnConfigChangeRestart() { +func (c *InMemorySwitchOverCache) extractQueriesAndOverridePlanCache() { c.mu.Lock() defer c.mu.Unlock() @@ -135,17 +135,12 @@ func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.Ro return } - ffNames := make(map[string]struct{}) - for ffName := range routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName { - ffNames[ffName] = struct{}{} - } - for ffName := range c.queriesForFeatureFlag { // Skip the base which is "" if ffName == "" { continue } - if _, exists := ffNames[ffName]; !exists { + if _, exists := routerCfg.FeatureFlagConfigs.ConfigByFeatureFlagName[ffName]; !exists { delete(c.queriesForFeatureFlag, ffName) } } diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 42be015b5d..21198bbaab 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -371,7 +371,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { cache.queriesForFeatureFlag["ff1"] = mockCache1 cache.queriesForFeatureFlag["ff2"] = mockCache2 - cache.processOnConfigChangeRestart() + cache.extractQueriesAndOverridePlanCache() // Verify both caches have been converted to operation slices require.IsType(t, []*nodev1.Operation{}, cache.queriesForFeatureFlag["ff1"]) @@ -392,7 +392,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { queriesForFeatureFlag: nil, } - cache.processOnConfigChangeRestart() + cache.extractQueriesAndOverridePlanCache() // Should remain nil since processing is skipped require.Nil(t, cache.queriesForFeatureFlag) @@ -405,7 +405,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { } require.NotPanics(t, func() { - cache.processOnConfigChangeRestart() + cache.extractQueriesAndOverridePlanCache() }) require.Empty(t, cache.queriesForFeatureFlag) diff --git a/router/core/supervisor.go b/router/core/supervisor.go index c6e81fb482..df59821fe8 100644 --- a/router/core/supervisor.go +++ b/router/core/supervisor.go @@ -159,7 +159,7 @@ func (rs *RouterSupervisor) Start() error { rs.logger.Debug("Got shutdown signal", zap.Bool("shutdown", shutdown)) if !shutdown { - rs.router.switchoverConfig.ProcessOnConfigChangeRestart() + rs.router.switchoverConfig.ProcessOnConfigChangeRouterInstanceRestart() } if err := rs.stopRouter(); err != nil { diff --git a/router/pkg/config/config.go b/router/pkg/config/config.go index c3163eed61..e9409a9ed4 100644 --- a/router/pkg/config/config.go +++ b/router/pkg/config/config.go @@ -987,7 +987,7 @@ type CacheWarmupConfiguration struct { Workers int `yaml:"workers" envDefault:"8" env:"CACHE_WARMUP_WORKERS"` ItemsPerSecond int `yaml:"items_per_second" envDefault:"50" env:"CACHE_WARMUP_ITEMS_PER_SECOND"` Timeout time.Duration `yaml:"timeout" envDefault:"30s" env:"CACHE_WARMUP_TIMEOUT"` - InMemorySwitchoverFallback bool `yaml:"in_memory_switchover_fallback" envDefault:"true" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_FALLBACK_ENABLED"` + InMemorySwitchoverFallback bool `yaml:"in_memory_switchover_fallback" envDefault:"true" env:"CACHE_WARMUP_IN_MEMORY_SWITCHOVER_FALLBACK"` } type MCPConfiguration struct { From e0734f5d2ac2e941734378c11ee0e7d071d355d6 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 19:05:36 +0530 Subject: [PATCH 34/52] fix: review comments --- router/core/cache_warmup_plans.go | 7 ++++ router/core/graph_server.go | 44 ++++++++++++++++-------- router/core/restart_switchover_config.go | 19 +++++++--- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index e2f98ee037..d4d5810de3 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -9,14 +9,21 @@ import ( var _ CacheWarmupSource = (*PlanSource)(nil) +// PlanSource is a very basic cache warmup source that relies on the caller of this type to pass in the +// queries to be used for cache warming directly type PlanSource struct { queries []*nodev1.Operation } +// NewPlanSource creates a new PlanSource with the given queries from the caller func NewPlanSource(switchoverCacheWarmerQueries []*nodev1.Operation) *PlanSource { + if switchoverCacheWarmerQueries == nil { + switchoverCacheWarmerQueries = make([]*nodev1.Operation, 0) + } return &PlanSource{queries: switchoverCacheWarmerQueries} } +// LoadItems loads the items from the plan source when called by the cache warmer func (c *PlanSource) LoadItems(_ context.Context, _ *zap.Logger) ([]*nodev1.Operation, error) { return c.queries, nil } diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 3254f27b9a..1d9727aa0a 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -120,8 +120,16 @@ func (b BuildGraphMuxOptions) IsBaseGraph() bool { return b.FeatureFlagName == "" } +// BuildMultiGraphHandlerOptions contains the configuration options for building a multi-graph handler. +type BuildMultiGraphHandlerOptions struct { + BaseMux *chi.Mux + FeatureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig + SwitchoverConfig *SwitchoverConfig + CosmoCacheWarmerEnabled bool +} + // newGraphServer creates a new server instance. -func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc, switchoverConfig *SwitchoverConfig) (*graphServer, error) { +func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterConfig, proxy ProxyFunc) (*graphServer, error) { /* Older versions of composition will not populate a compatibility version. * Currently, all "old" router execution configurations are compatible as there have been no breaking * changes. @@ -280,7 +288,7 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC EngineConfig: routerConfig.GetEngineConfig(), ConfigSubgraphs: routerConfig.GetSubgraphs(), RoutingUrlGroupings: routingUrlGroupings, - SwitchoverConfig: switchoverConfig, + SwitchoverConfig: r.switchoverConfig, CosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, }) if err != nil { @@ -292,7 +300,12 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC s.logger.Info("Feature flags enabled", zap.Strings("flags", maps.Keys(featureFlagConfigMap))) } - multiGraphHandler, err := s.buildMultiGraphHandler(ctx, gm.mux, featureFlagConfigMap, switchoverConfig, cosmoCacheWarmerEnabled) + multiGraphHandler, err := s.buildMultiGraphHandler(ctx, BuildMultiGraphHandlerOptions{ + BaseMux: gm.mux, + FeatureFlagConfigs: featureFlagConfigMap, + SwitchoverConfig: r.switchoverConfig, + CosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, + }) if err != nil { return nil, fmt.Errorf("failed to build feature flag handler: %w", err) } @@ -440,26 +453,23 @@ func getRoutingUrlGroupingForCircuitBreakers( func (s *graphServer) buildMultiGraphHandler( ctx context.Context, - baseMux *chi.Mux, - featureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig, - switchoverConfig *SwitchoverConfig, - cosmoCacheWarmerEnabled bool, + opts BuildMultiGraphHandlerOptions, ) (http.HandlerFunc, error) { - if len(featureFlagConfigs) == 0 { - return baseMux.ServeHTTP, nil + if len(opts.FeatureFlagConfigs) == 0 { + return opts.BaseMux.ServeHTTP, nil } - featureFlagToMux := make(map[string]*chi.Mux, len(featureFlagConfigs)) + featureFlagToMux := make(map[string]*chi.Mux, len(opts.FeatureFlagConfigs)) // Build all the muxes for the feature flags in serial to avoid any race conditions - for featureFlagName, executionConfig := range featureFlagConfigs { + for featureFlagName, executionConfig := range opts.FeatureFlagConfigs { gm, err := s.buildGraphMux(ctx, BuildGraphMuxOptions{ FeatureFlagName: featureFlagName, RouterConfigVersion: executionConfig.GetVersion(), EngineConfig: executionConfig.GetEngineConfig(), ConfigSubgraphs: executionConfig.Subgraphs, - SwitchoverConfig: switchoverConfig, - CosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, + SwitchoverConfig: opts.SwitchoverConfig, + CosmoCacheWarmerEnabled: opts.CosmoCacheWarmerEnabled, }) if err != nil { return nil, fmt.Errorf("failed to build mux for feature flag '%s': %w", featureFlagName, err) @@ -486,7 +496,7 @@ func (s *graphServer) buildMultiGraphHandler( return } - baseMux.ServeHTTP(w, r) + opts.BaseMux.ServeHTTP(w, r) }, nil } @@ -1365,7 +1375,11 @@ func (s *graphServer) buildGraphMux( warmupConfig.Source = NewFileSystemSource(&FileSystemSourceConfig{ RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) - // We want to enable this only whenever there is no registering with cosmo + // Enable in-memory switchover fallback when: + // - Router has cache warmer with inMemorySwitchoverFallback enabled, AND + // - Either: + // - Using static execution config (not Cosmo): s.selfRegister == nil + // - OR Cosmo cache warmer is disabled: !opts.CosmoCacheWarmerEnabled case s.cacheWarmup.InMemorySwitchoverFallback && (s.selfRegister == nil || !opts.CosmoCacheWarmerEnabled): // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries // and reset the plan cache to the new plan cache for this start afterwords diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 1694f96e88..c97f61205d 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -23,10 +23,13 @@ func NewSwitchoverConfig(logger *zap.Logger) *SwitchoverConfig { } } +// UpdateSwitchoverConfig updates the switchover config based on the provided config. func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config, isCosmoCacheWarmerEnabled bool) { s.inMemorySwitchOverCache.updateStateFromConfig(config, isCosmoCacheWarmerEnabled) } +// CleanupFeatureFlags cleans up anything related to unused feature flags due to being now excluded +// from the execution config func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } @@ -42,12 +45,14 @@ func (s *SwitchoverConfig) ProcessOnConfigChangeRouterInstanceRestart() { s.inMemorySwitchOverCache.extractQueriesAndOverridePlanCache() } +// InMemorySwitchOverCache is a store that stores either queries or references to the planner cache for use with the cache warmer type InMemorySwitchOverCache struct { mu sync.RWMutex queriesForFeatureFlag map[string]any logger *zap.Logger } +// updateStateFromConfig updates the internal state of the in-memory switchover cache based on the provided config func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoCacheWarmerEnabled bool) { enabled := config.cacheWarmup != nil && !isCosmoCacheWarmerEnabled && // We only enable in-memory switchover cache if the cosmo cache warmer is not enabled @@ -70,6 +75,7 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC } } +// IsEnabled returns whether the in-memory switchover cache is enabled func (c *InMemorySwitchOverCache) IsEnabled() bool { c.mu.RLock() defer c.mu.RUnlock() @@ -77,6 +83,7 @@ func (c *InMemorySwitchOverCache) IsEnabled() bool { return c.queriesForFeatureFlag != nil } +// getPlanCacheForFF gets the plan cache in the []*nodev1.Operation format for a specific feature flag key func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { c.mu.RLock() defer c.mu.RUnlock() @@ -90,16 +97,17 @@ func (c *InMemorySwitchOverCache) getPlanCacheForFF(featureFlagKey string) []*no return convertToNodeOperation(cache) case []*nodev1.Operation: return cache + // This would occur during the first start (we add this case to specifically log any other cases) case nil: - // This would occur during the first start - return make([]*nodev1.Operation, 0) + return nil + // This should not happen as we cannot have any types other than the above default: - // This should not happen as we cannot have any types other than the above c.logger.Error("unexpected type") - return make([]*nodev1.Operation, 0) + return nil } } +// setPlanCacheForFF sets the plan cache for a specific feature flag key func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { c.mu.Lock() defer c.mu.Unlock() @@ -110,6 +118,7 @@ func (c *InMemorySwitchOverCache) setPlanCacheForFF(featureFlagKey string, cache c.queriesForFeatureFlag[featureFlagKey] = cache } +// extractQueriesAndOverridePlanCache extracts the queries from the plan cache and overrides the internal map func (c *InMemorySwitchOverCache) extractQueriesAndOverridePlanCache() { c.mu.Lock() defer c.mu.Unlock() @@ -127,6 +136,8 @@ func (c *InMemorySwitchOverCache) extractQueriesAndOverridePlanCache() { c.queriesForFeatureFlag = switchoverMap } +// cleanupUnusedFeatureFlags removes any feature flags from the in-memory switchover cache +// this is useful in case where the updated execution config excludes a feature flag func (c *InMemorySwitchOverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { c.mu.Lock() defer c.mu.Unlock() From 11158f6a45ce7e7f4d086e18b2e1e6ce057a424b Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 19:13:08 +0530 Subject: [PATCH 35/52] fix: review comments --- router/core/router.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/core/router.go b/router/core/router.go index 515a7e6feb..cc73c81ec9 100644 --- a/router/core/router.go +++ b/router/core/router.go @@ -597,7 +597,7 @@ func NewRouter(opts ...Option) (*Router, error) { // newGraphServer creates a new server. func (r *Router) newServer(ctx context.Context, cfg *nodev1.RouterConfig) error { - server, err := newGraphServer(ctx, r, cfg, r.proxy, r.switchoverConfig) + server, err := newGraphServer(ctx, r, cfg, r.proxy) if err != nil { r.logger.Error("Failed to create graph server. Keeping the old server", zap.Error(err)) return err From 54f24c1b4a52ae0cfe6dceb0e11f09a5eb6e5aaa Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 19:21:13 +0530 Subject: [PATCH 36/52] fix: tests --- router/core/restart_switchover_config_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 21198bbaab..489e59d8ba 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -182,9 +182,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { } result := cache.getPlanCacheForFF("non-existent") - - require.NotNil(t, result) - require.Empty(t, result) + require.Nil(t, result) }) t.Run("returns nil when cache is disabled", func(t *testing.T) { From fd683575382ec1a73bb881623a42e669309f7f57 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 22 Jan 2026 22:41:20 +0530 Subject: [PATCH 37/52] fix: review comments --- router-tests/cache_warmup_test.go | 2 ++ router/core/graph_server.go | 40 ++++++++++++------------ router/core/restart_switchover_config.go | 8 ++--- router/core/supervisor.go | 2 +- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 7fb9037863..d7351e968b 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -1094,6 +1094,8 @@ func TestInMemorySwitchoverCaching(t *testing.T) { }) t.Run("Successfully persists cache across config change restarts", func(t *testing.T) { + t.Parallel() + updateConfig := func(t *testing.T, xEnv *testenv.Environment, ctx context.Context, listenString string, config string) { f, err := os.Create(filepath.Join(xEnv.GetRouterProcessCwd(), "config.yaml")) require.NoError(t, err) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 1d9727aa0a..925d3e7084 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -120,12 +120,12 @@ func (b BuildGraphMuxOptions) IsBaseGraph() bool { return b.FeatureFlagName == "" } -// BuildMultiGraphHandlerOptions contains the configuration options for building a multi-graph handler. -type BuildMultiGraphHandlerOptions struct { - BaseMux *chi.Mux - FeatureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig - SwitchoverConfig *SwitchoverConfig - CosmoCacheWarmerEnabled bool +// buildMultiGraphHandlerOptions contains the configuration options for building a multi-graph handler. +type buildMultiGraphHandlerOptions struct { + baseMux *chi.Mux + featureFlagConfigs map[string]*nodev1.FeatureFlagRouterExecutionConfig + switchoverConfig *SwitchoverConfig + cosmoCacheWarmerEnabled bool } // newGraphServer creates a new server instance. @@ -300,11 +300,11 @@ func newGraphServer(ctx context.Context, r *Router, routerConfig *nodev1.RouterC s.logger.Info("Feature flags enabled", zap.Strings("flags", maps.Keys(featureFlagConfigMap))) } - multiGraphHandler, err := s.buildMultiGraphHandler(ctx, BuildMultiGraphHandlerOptions{ - BaseMux: gm.mux, - FeatureFlagConfigs: featureFlagConfigMap, - SwitchoverConfig: r.switchoverConfig, - CosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, + multiGraphHandler, err := s.buildMultiGraphHandler(ctx, buildMultiGraphHandlerOptions{ + baseMux: gm.mux, + featureFlagConfigs: featureFlagConfigMap, + switchoverConfig: r.switchoverConfig, + cosmoCacheWarmerEnabled: cosmoCacheWarmerEnabled, }) if err != nil { return nil, fmt.Errorf("failed to build feature flag handler: %w", err) @@ -453,23 +453,23 @@ func getRoutingUrlGroupingForCircuitBreakers( func (s *graphServer) buildMultiGraphHandler( ctx context.Context, - opts BuildMultiGraphHandlerOptions, + opts buildMultiGraphHandlerOptions, ) (http.HandlerFunc, error) { - if len(opts.FeatureFlagConfigs) == 0 { - return opts.BaseMux.ServeHTTP, nil + if len(opts.featureFlagConfigs) == 0 { + return opts.baseMux.ServeHTTP, nil } - featureFlagToMux := make(map[string]*chi.Mux, len(opts.FeatureFlagConfigs)) + featureFlagToMux := make(map[string]*chi.Mux, len(opts.featureFlagConfigs)) // Build all the muxes for the feature flags in serial to avoid any race conditions - for featureFlagName, executionConfig := range opts.FeatureFlagConfigs { + for featureFlagName, executionConfig := range opts.featureFlagConfigs { gm, err := s.buildGraphMux(ctx, BuildGraphMuxOptions{ FeatureFlagName: featureFlagName, RouterConfigVersion: executionConfig.GetVersion(), EngineConfig: executionConfig.GetEngineConfig(), ConfigSubgraphs: executionConfig.Subgraphs, - SwitchoverConfig: opts.SwitchoverConfig, - CosmoCacheWarmerEnabled: opts.CosmoCacheWarmerEnabled, + SwitchoverConfig: opts.switchoverConfig, + CosmoCacheWarmerEnabled: opts.cosmoCacheWarmerEnabled, }) if err != nil { return nil, fmt.Errorf("failed to build mux for feature flag '%s': %w", featureFlagName, err) @@ -496,7 +496,7 @@ func (s *graphServer) buildMultiGraphHandler( return } - opts.BaseMux.ServeHTTP(w, r) + opts.baseMux.ServeHTTP(w, r) }, nil } @@ -1379,7 +1379,7 @@ func (s *graphServer) buildGraphMux( // - Router has cache warmer with inMemorySwitchoverFallback enabled, AND // - Either: // - Using static execution config (not Cosmo): s.selfRegister == nil - // - OR Cosmo cache warmer is disabled: !opts.CosmoCacheWarmerEnabled + // - OR Cosmo cache warmer is disabled: !opts.cosmoCacheWarmerEnabled case s.cacheWarmup.InMemorySwitchoverFallback && (s.selfRegister == nil || !opts.CosmoCacheWarmerEnabled): // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries // and reset the plan cache to the new plan cache for this start afterwords diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index c97f61205d..e48118fbf8 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -34,7 +34,7 @@ func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) } -func (s *SwitchoverConfig) ProcessOnConfigChangeRouterInstanceRestart() { +func (s *SwitchoverConfig) OnRouterConfigReload() { // For cases of router config changes (not execution config), we shut down before creating the // graph mux, because we need to initialize everything from the start // This causes problems in using the previous planCache reference as it gets closed, so we need to @@ -69,10 +69,10 @@ func (c *InMemorySwitchOverCache) updateStateFromConfig(config *Config, isCosmoC c.queriesForFeatureFlag = make(map[string]any) } return - } else { - // Reset the map to free up memory - c.queriesForFeatureFlag = nil } + + // Reset the map to free up memory + c.queriesForFeatureFlag = nil } // IsEnabled returns whether the in-memory switchover cache is enabled diff --git a/router/core/supervisor.go b/router/core/supervisor.go index df59821fe8..577bbcb902 100644 --- a/router/core/supervisor.go +++ b/router/core/supervisor.go @@ -159,7 +159,7 @@ func (rs *RouterSupervisor) Start() error { rs.logger.Debug("Got shutdown signal", zap.Bool("shutdown", shutdown)) if !shutdown { - rs.router.switchoverConfig.ProcessOnConfigChangeRouterInstanceRestart() + rs.router.switchoverConfig.OnRouterConfigReload() } if err := rs.stopRouter(); err != nil { From 4fa6007dccc4d1c98669f177fba6f45ca5127d7e Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 19:58:42 +0530 Subject: [PATCH 38/52] fix: review comments --- .../gen/proto/wg/cosmo/node/v1/node.pb.go | 1439 ++++++++--------- connect/src/wg/cosmo/node/v1/node_pb.ts | 6 - .../src/core/bufservices/NodeService.ts | 1 - proto/wg/cosmo/node/v1/node.proto | 1 - router-tests/cache_warmup_test.go | 14 +- router/core/cache_warmup_cdn.go | 20 +- router/core/graph_server.go | 61 +- router/core/restart_switchover_config.go | 27 +- router/core/restart_switchover_config_test.go | 60 +- router/core/router.go | 3 +- router/core/router_config.go | 2 +- router/gen/proto/wg/cosmo/node/v1/node.pb.go | 1439 ++++++++--------- router/pkg/config/config.go | 17 +- 13 files changed, 1534 insertions(+), 1556 deletions(-) diff --git a/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go b/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go index 81c54440da..30527dc201 100644 --- a/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go +++ b/connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go @@ -796,9 +796,8 @@ type RegistrationInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AccountLimits *AccountLimits `protobuf:"bytes,1,opt,name=account_limits,json=accountLimits,proto3" json:"account_limits,omitempty"` - GraphPublicKey string `protobuf:"bytes,2,opt,name=graph_public_key,json=graphPublicKey,proto3" json:"graph_public_key,omitempty"` - IsCacheWarmerEnabled bool `protobuf:"varint,3,opt,name=is_cache_warmer_enabled,json=isCacheWarmerEnabled,proto3" json:"is_cache_warmer_enabled,omitempty"` + AccountLimits *AccountLimits `protobuf:"bytes,1,opt,name=account_limits,json=accountLimits,proto3" json:"account_limits,omitempty"` + GraphPublicKey string `protobuf:"bytes,2,opt,name=graph_public_key,json=graphPublicKey,proto3" json:"graph_public_key,omitempty"` } func (x *RegistrationInfo) Reset() { @@ -847,13 +846,6 @@ func (x *RegistrationInfo) GetGraphPublicKey() string { return "" } -func (x *RegistrationInfo) GetIsCacheWarmerEnabled() bool { - if x != nil { - return x.IsCacheWarmerEnabled - } - return false -} - type AccountLimits struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4570,7 +4562,7 @@ var file_wg_cosmo_node_v1_node_proto_rawDesc = []byte{ 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 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, 0x22, 0xbb, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x65, 0x22, 0x84, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, @@ -4578,745 +4570,742 @@ var file_wg_cosmo_node_v1_node_proto_rawDesc = []byte{ 0x0d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x17, 0x69, 0x73, 0x5f, 0x63, - 0x61, 0x63, 0x68, 0x65, 0x5f, 0x77, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, - 0x3f, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, - 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, - 0x6e, 0x67, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x11, 0x74, - 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x61, 0x74, 0x65, - 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb8, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x66, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, - 0x11, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, - 0x66, 0x6f, 0x22, 0xfc, 0x04, 0x0a, 0x13, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x66, - 0x0a, 0x19, 0x64, 0x61, 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x61, - 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x57, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5f, 0x0a, 0x0e, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x15, - 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x13, 0x67, - 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x88, 0x01, 0x01, 0x1a, 0x40, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 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, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x67, 0x72, 0x61, 0x70, - 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x22, 0xfa, 0x07, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, - 0x3c, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x42, 0x0a, - 0x1e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, - 0x70, 0x61, 0x74, 0x68, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x12, 0x51, 0x0a, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x67, 0x72, 0x61, 0x70, - 0x68, 0x71, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x51, 0x4c, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x47, 0x72, 0x61, - 0x70, 0x68, 0x71, 0x6c, 0x12, 0x4e, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x12, 0x48, 0x0a, 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x36, - 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x61, 0x74, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, + 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x61, 0x74, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x53, 0x65, 0x6c, + 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0xb8, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x53, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x48, + 0x00, 0x52, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x6e, 0x66, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xfc, 0x04, 0x0a, 0x13, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x66, 0x0a, 0x19, 0x64, 0x61, 0x74, 0x61, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x64, 0x61, 0x74, 0x61, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x57, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, + 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x54, + 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x12, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5f, 0x0a, 0x0e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, - 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x6e, - 0x0a, 0x15, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, - 0x0a, 0x06, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x41, - 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x1a, 0x41, 0x75, 0x74, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, + 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x13, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x88, 0x01, 0x01, 0x1a, 0x40, + 0x0a, 0x12, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 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, + 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0xfa, 0x07, 0x0a, 0x17, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x0a, + 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x09, 0x72, + 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x0b, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a, 0x63, 0x68, 0x69, 0x6c, + 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x1e, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x66, 0x72, + 0x6f, 0x6d, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, + 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, + 0x68, 0x46, 0x72, 0x6f, 0x6d, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x51, 0x0a, 0x0e, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x52, 0x0d, + 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x47, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x12, 0x4e, 0x0a, + 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x52, + 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x48, 0x0a, + 0x0a, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x33, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, + 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x73, + 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x12, 0x4d, + 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5b, 0x0a, + 0x11, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x11, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, + 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x6e, 0x0a, 0x15, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0a, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x06, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x6e, + 0x64, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x41, 0x6e, 0x64, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x22, 0xef, 0x01, 0x0a, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x37, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x12, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, + 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x12, 0x50, 0x0a, 0x18, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, + 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6f, 0x72, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x14, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, + 0x79, 0x4f, 0x72, 0x22, 0xbb, 0x03, 0x0a, 0x12, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x16, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6d, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x46, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, - 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x4f, 0x72, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x18, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x62, - 0x79, 0x5f, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, - 0x6f, 0x70, 0x65, 0x73, 0x52, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4f, 0x72, - 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, 0x79, 0x4f, 0x72, 0x22, 0xbb, 0x03, 0x0a, 0x12, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x60, 0x0a, - 0x17, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, - 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x16, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x6d, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x1a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x76, - 0x0a, 0x1d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x1b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x20, 0x0a, 0x1e, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x76, 0x0a, 0x1d, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, - 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x54, 0x79, 0x70, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, - 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x54, 0x79, 0x70, 0x65, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x12, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x21, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x5f, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, - 0x4e, 0x0a, 0x10, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, - 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x8c, 0x01, 0x0a, 0x11, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x16, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, - 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0xed, - 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, - 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, - 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, - 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7e, - 0x0a, 0x1c, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, - 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, - 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, - 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xed, - 0x05, 0x0a, 0x12, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, - 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x48, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3d, 0x0a, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, - 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, - 0x75, 0x72, 0x6c, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x72, 0x6c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x12, 0x42, 0x0a, - 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, - 0x6c, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, + 0x1b, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, + 0x20, 0x0a, 0x1e, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, + 0x22, 0xc5, 0x01, 0x0a, 0x09, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x48, + 0x0a, 0x21, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x4e, 0x0a, 0x10, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x11, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, + 0x0a, 0x16, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, + 0x74, 0x65, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x61, 0x74, 0x65, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0xed, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, + 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, + 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7e, 0x0a, 0x1c, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x63, 0x72, + 0x65, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xed, 0x05, 0x0a, 0x12, 0x46, 0x65, 0x74, 0x63, + 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, + 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, + 0x48, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x72, 0x6c, 0x5f, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, + 0x75, 0x72, 0x6c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x37, 0x0a, + 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x04, 0x6d, 0x74, 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x52, 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x5f, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x52, - 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x48, - 0x00, 0x52, 0x0c, 0x68, 0x74, 0x74, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x88, - 0x01, 0x01, 0x1a, 0x57, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, - 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x95, - 0x01, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, - 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x1c, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x74, - 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x6e, - 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, - 0x74, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, 0x03, 0x0a, 0x18, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x51, 0x4c, 0x12, 0x3a, 0x0a, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x12, - 0x56, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x68, 0x74, 0x74, 0x70, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x1a, 0x57, 0x0a, 0x0b, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, + 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x95, 0x01, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x3e, 0x0a, 0x1c, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x22, + 0xe2, 0x03, 0x0a, 0x18, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x12, 0x3a, 0x0a, 0x05, + 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x65, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x12, 0x56, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x50, 0x0a, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, + 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5c, 0x0a, + 0x19, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x52, 0x16, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x63, 0x61, 0x6c, 0x61, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x37, 0x0a, 0x04, 0x67, + 0x72, 0x70, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, + 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, + 0x67, 0x72, 0x70, 0x63, 0x22, 0xae, 0x01, 0x0a, 0x11, 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x07, 0x6d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x66, - 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x75, 0x70, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5c, 0x0a, 0x19, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x73, - 0x63, 0x61, 0x6c, 0x61, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x16, 0x63, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x53, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x73, 0x12, 0x37, 0x0a, 0x04, 0x67, 0x72, 0x70, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x67, 0x72, 0x70, 0x63, 0x22, 0xae, 0x01, 0x0a, 0x11, - 0x47, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x37, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, - 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x0e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x13, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, + 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, + 0x2c, 0x0a, 0x10, 0x53, 0x53, 0x4c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, + 0x0a, 0x0b, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x51, 0x0a, 0x12, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0x4e, 0x0a, 0x0e, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, - 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1c, - 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0xa7, 0x01, 0x0a, - 0x13, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, - 0x0e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x88, - 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x2c, 0x0a, 0x10, 0x53, 0x53, 0x4c, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, 0x0a, 0x0b, 0x47, 0x52, 0x50, 0x43, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x12, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x52, 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x11, 0x74, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x6e, 0x75, - 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, - 0x0c, 0x65, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, - 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, - 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, - 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, - 0x0e, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x6c, 0x6f, 0x6f, - 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, - 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x12, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x0d, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, + 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0e, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x52, + 0x0a, 0x13, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, + 0x11, 0x74, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, + 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x65, 0x6e, 0x75, 0x6d, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, + 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x12, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, + 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, + 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, + 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, + 0x01, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x10, 0x54, + 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x70, - 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x70, 0x63, 0x12, 0x18, 0x0a, 0x07, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x10, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x73, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, + 0x4e, 0x0a, 0x11, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, + 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x61, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, + 0x45, 0x0a, 0x0f, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x12, 0x4e, 0x0a, 0x11, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x45, 0x0a, 0x0f, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, + 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x46, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x5d, 0x0a, - 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x3a, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x46, 0x0a, 0x10, - 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, - 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x22, 0x9f, 0x01, 0x0a, 0x17, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xfc, 0x01, 0x0a, 0x16, 0x4e, 0x61, 0x74, 0x73, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x5c, 0x0a, 0x14, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x13, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9b, 0x01, 0x0a, 0x17, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x74, - 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, - 0x69, 0x63, 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x22, 0x9f, 0x01, + 0x0a, 0x17, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x49, 0x6e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, + 0xfc, 0x01, 0x0a, 0x16, 0x4e, 0x61, 0x74, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x12, 0x5c, 0x0a, 0x14, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9b, + 0x01, 0x0a, 0x17, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x22, 0x9f, 0x01, 0x0a, + 0x17, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x1a, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x77, + 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x18, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, - 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3c, 0x0a, 0x04, 0x6e, - 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, - 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6b, 0x61, 0x66, - 0x6b, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x61, 0x66, 0x6b, - 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x65, - 0x64, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, - 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x22, 0x56, 0x0a, 0x17, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x3b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0xa8, + 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3c, 0x0a, 0x04, 0x6e, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x74, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x6e, 0x61, + 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6b, 0x61, + 0x66, 0x6b, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x65, 0x64, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, + 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x72, + 0x65, 0x64, 0x69, 0x73, 0x22, 0x56, 0x0a, 0x17, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, + 0x3b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, + 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xd5, 0x02, 0x0a, + 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, + 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x22, 0xd5, 0x02, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3f, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, - 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x36, - 0x0a, 0x17, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x65, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x22, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, - 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x3a, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x76, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x17, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x16, 0x44, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, - 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x22, 0x41, 0x0a, 0x15, 0x55, 0x52, 0x4c, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0a, - 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x11, - 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, + 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x17, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x22, 0x65, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x19, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x16, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, + 0x0a, 0x0e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x5f, + 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x54, 0x6f, 0x22, 0x41, 0x0a, 0x15, 0x55, 0x52, 0x4c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x11, 0x4d, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x04, 0x63, 0x65, + 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, + 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, + 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x22, 0xfb, 0x02, 0x0a, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3b, 0x0a, 0x04, - 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x69, 0x6e, 0x73, - 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, - 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x22, 0xfb, 0x02, 0x0a, 0x20, 0x47, 0x72, + 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x06, + 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, - 0x75, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x88, 0x01, 0x01, - 0x12, 0x4d, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, - 0x65, 0x0a, 0x14, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, - 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x02, 0x52, 0x14, 0x77, - 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x73, 0x65, 0x53, 0x53, - 0x45, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x17, - 0x0a, 0x15, 0x5f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x5a, 0x0a, 0x1e, 0x47, 0x72, 0x61, 0x70, 0x68, - 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x53, 0x64, 0x6c, 0x22, 0x22, 0x0a, 0x0e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x4d, 0x0a, 0x0f, 0x53, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4f, 0x0a, 0x1a, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0xb5, 0x02, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x03, 0x61, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x61, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x6e, - 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x88, 0x01, - 0x01, 0x12, 0x3d, 0x0a, 0x02, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x65, 0x0a, 0x14, 0x77, 0x65, 0x62, 0x73, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, + 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x02, 0x52, 0x14, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x73, 0x65, 0x53, 0x53, 0x45, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x77, 0x65, 0x62, 0x73, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x22, 0x5a, 0x0a, 0x1e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x4c, 0x46, 0x65, 0x64, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x64, 0x6c, 0x22, 0x22, 0x0a, 0x0e, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x22, 0x4d, 0x0a, 0x0f, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x4f, 0x0a, 0x1a, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, + 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, + 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, + 0x22, 0xb5, 0x02, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x3f, 0x0a, 0x03, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x72, - 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6e, 0x6f, 0x74, 0x22, - 0x54, 0x0a, 0x15, 0x43, 0x61, 0x63, 0x68, 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x61, 0x6e, + 0x64, 0x12, 0x41, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x02, 0x69, + 0x6e, 0x88, 0x01, 0x01, 0x12, 0x44, 0x0a, 0x03, 0x6e, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x01, 0x52, 0x03, 0x6e, 0x6f, 0x74, 0x88, 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x02, 0x6f, 0x72, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6f, 0x72, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x6e, + 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6e, 0x6f, 0x74, 0x22, 0x54, 0x0a, 0x15, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x57, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7f, + 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7f, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x34, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x67, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, + 0x8c, 0x01, 0x0a, 0x10, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x3b, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x56, + 0x0a, 0x09, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x70, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, + 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, + 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x4b, 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x32, + 0x35, 0x36, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, + 0x68, 0x61, 0x32, 0x35, 0x36, 0x48, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, + 0x82, 0x01, 0x0a, 0x1b, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, + 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, + 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, + 0x41, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, + 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, + 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5f, 0x43, + 0x53, 0x56, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, + 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x46, 0x49, 0x45, 0x4c, + 0x44, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0e, + 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x52, + 0x41, 0x50, 0x48, 0x51, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x53, 0x55, + 0x42, 0x10, 0x02, 0x2a, 0x5c, 0x0a, 0x0a, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, + 0x0a, 0x13, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, + 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x53, 0x10, + 0x02, 0x2a, 0x87, 0x01, 0x0a, 0x0d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x1b, 0x0a, + 0x17, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x4d, 0x55, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x4f, 0x50, + 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, + 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x2a, 0x34, 0x0a, 0x09, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x55, 0x42, 0x4c, + 0x49, 0x53, 0x48, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, + 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, + 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, + 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, + 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, + 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x4e, 0x56, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, + 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, + 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, + 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x2a, 0x41, 0x0a, 0x0a, 0x48, 0x54, + 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, + 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x50, + 0x55, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, + 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x04, 0x32, 0x6e, 0x0a, + 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0c, + 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x56, 0x0a, 0x09, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x5f, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x67, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x0e, 0x70, - 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x4b, 0x0a, - 0x0e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, - 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x48, 0x61, 0x73, 0x68, - 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0a, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x82, 0x01, 0x0a, 0x1b, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, - 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, - 0x54, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, - 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, - 0x4c, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x4e, - 0x44, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x53, 0x5f, - 0x41, 0x52, 0x52, 0x41, 0x59, 0x5f, 0x43, 0x53, 0x56, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0e, 0x41, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x10, 0x0a, - 0x0c, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x00, 0x12, - 0x12, 0x0a, 0x0e, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x41, 0x52, 0x47, 0x55, 0x4d, 0x45, 0x4e, - 0x54, 0x10, 0x01, 0x2a, 0x35, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, - 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x52, 0x41, 0x50, 0x48, 0x51, 0x4c, 0x10, 0x01, 0x12, 0x0a, - 0x0a, 0x06, 0x50, 0x55, 0x42, 0x53, 0x55, 0x42, 0x10, 0x02, 0x2a, 0x5c, 0x0a, 0x0a, 0x4c, 0x6f, - 0x6f, 0x6b, 0x75, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x4f, 0x4b, - 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x4c, 0x56, 0x45, 0x10, 0x01, 0x12, 0x18, - 0x0a, 0x14, 0x4c, 0x4f, 0x4f, 0x4b, 0x55, 0x50, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, - 0x51, 0x55, 0x49, 0x52, 0x45, 0x53, 0x10, 0x02, 0x2a, 0x87, 0x01, 0x0a, 0x0d, 0x4f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x4f, 0x50, - 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x50, - 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, - 0x52, 0x59, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, - 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, - 0x10, 0x03, 0x2a, 0x34, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x0b, 0x0a, 0x07, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, - 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x42, - 0x53, 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, - 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, - 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x4e, 0x56, - 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, - 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x50, 0x4c, 0x41, - 0x43, 0x45, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, - 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, - 0x02, 0x2a, 0x41, 0x0a, 0x0a, 0x48, 0x54, 0x54, 0x50, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, - 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4f, 0x53, 0x54, - 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x54, 0x49, 0x4f, - 0x4e, 0x53, 0x10, 0x04, 0x32, 0x6e, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0c, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x6c, 0x66, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0xcf, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x67, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x4e, - 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x67, 0x72, 0x61, - 0x70, 0x68, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x2d, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x67, - 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6e, - 0x6f, 0x64, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x57, 0x43, 0x4e, 0xaa, 0x02, 0x10, 0x57, 0x67, - 0x2e, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x10, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, - 0x31, 0xe2, 0x02, 0x1c, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, - 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x13, 0x57, 0x67, 0x3a, 0x3a, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x3a, 0x3a, 0x4e, 0x6f, - 0x64, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xcf, 0x01, + 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x67, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x49, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x77, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x67, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6e, 0x6f, 0x64, 0x65, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x57, 0x43, 0x4e, 0xaa, 0x02, 0x10, 0x57, 0x67, 0x2e, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x57, 0x67, 0x5c, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x57, 0x67, 0x5c, + 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x5c, 0x4e, 0x6f, 0x64, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x57, 0x67, 0x3a, 0x3a, + 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x3a, 0x3a, 0x4e, 0x6f, 0x64, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/connect/src/wg/cosmo/node/v1/node_pb.ts b/connect/src/wg/cosmo/node/v1/node_pb.ts index 4ad64bd5e3..c13e62f9b8 100644 --- a/connect/src/wg/cosmo/node/v1/node_pb.ts +++ b/connect/src/wg/cosmo/node/v1/node_pb.ts @@ -543,11 +543,6 @@ export class RegistrationInfo extends Message { */ graphPublicKey = ""; - /** - * @generated from field: bool is_cache_warmer_enabled = 3; - */ - isCacheWarmerEnabled = false; - constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -558,7 +553,6 @@ export class RegistrationInfo extends Message { static readonly fields: FieldList = proto3.util.newFieldList(() => [ { no: 1, name: "account_limits", kind: "message", T: AccountLimits }, { no: 2, name: "graph_public_key", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 3, name: "is_cache_warmer_enabled", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): RegistrationInfo { diff --git a/controlplane/src/core/bufservices/NodeService.ts b/controlplane/src/core/bufservices/NodeService.ts index e00ebc6136..77537814f2 100644 --- a/controlplane/src/core/bufservices/NodeService.ts +++ b/controlplane/src/core/bufservices/NodeService.ts @@ -55,7 +55,6 @@ export default function (opts: RouterOptions): Partial Date: Mon, 26 Jan 2026 20:12:20 +0530 Subject: [PATCH 39/52] fix: review comments --- router/pkg/config/config.schema.json | 4 ++-- router/pkg/config/testdata/config_defaults.json | 7 +++++-- router/pkg/config/testdata/config_full.json | 7 +++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json index 574ba5adff..934cd18960 100644 --- a/router/pkg/config/config.schema.json +++ b/router/pkg/config/config.schema.json @@ -2431,9 +2431,9 @@ "minimum": "1s" } }, - "in_memory_switchover_fallback": { + "in_memory_fallback": { "type": "boolean", - "description": "Enable in-memory switchover fallback. When enabled, the router will cache query plans in memory and reuse them on restarts. This is useful when deploying new router configurations without downtime. The default value is true.", + "description": "Enable in-memory fallback. When enabled, the router will cache query plans in memory and reuse them on schema changes and hot config reloads. This is useful when deploying new router configurations without downtime. The default value is true.", "default": true } } diff --git a/router/pkg/config/testdata/config_defaults.json b/router/pkg/config/testdata/config_defaults.json index a055f32e1d..72b65b81b5 100644 --- a/router/pkg/config/testdata/config_defaults.json +++ b/router/pkg/config/testdata/config_defaults.json @@ -312,12 +312,15 @@ "CacheWarmup": { "Enabled": false, "Source": { - "Filesystem": null + "Filesystem": null, + "CdnSource": { + "Enabled": true + } }, "Workers": 8, "ItemsPerSecond": 50, "Timeout": 30000000000, - "InMemorySwitchoverFallback": true + "InMemoryFallback": true }, "RouterConfigPath": "", "RouterRegistration": true, diff --git a/router/pkg/config/testdata/config_full.json b/router/pkg/config/testdata/config_full.json index 66cf6ad41d..815fb5c6e5 100644 --- a/router/pkg/config/testdata/config_full.json +++ b/router/pkg/config/testdata/config_full.json @@ -661,12 +661,15 @@ "CacheWarmup": { "Enabled": false, "Source": { - "Filesystem": null + "Filesystem": null, + "CdnSource": { + "Enabled": true + } }, "Workers": 8, "ItemsPerSecond": 50, "Timeout": 30000000000, - "InMemorySwitchoverFallback": true + "InMemoryFallback": true }, "RouterConfigPath": "latest.json", "RouterRegistration": true, From e3715922fe056c58e4b8e3d5502236770048bd29 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 20:13:51 +0530 Subject: [PATCH 40/52] fix: review comments --- router-tests/cache_warmup_test.go | 2 +- router/core/cache_warmup_cdn.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index e59c61a1f8..1b2c1e6f5a 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -1117,7 +1117,7 @@ readiness_check_path: "/` + listenString + `" cache_warmup: enabled: true - in_memory_switchover_fallback: true + in_memory_fallback: true engine: debug: diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index 0ca625fd80..70062ea925 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -76,7 +76,7 @@ func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations }() } - operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/eee.json", c.organizationID, c.federatedGraphID) + operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/operations.json", c.organizationID, c.federatedGraphID) operationURL := c.cdnURL.ResolveReference(&url.URL{Path: operationsPath}) log.Debug("Loading cache warmup config", zap.String("url", operationURL.String())) From 335c0f1e0c80a8d011d335617d9222200fe20642 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 20:21:34 +0530 Subject: [PATCH 41/52] fix: review comments --- router/core/graph_server.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 9cfc4fe48a..1285642ea2 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1375,15 +1375,19 @@ func (s *graphServer) buildGraphMux( // and reset the plan cache to the new plan cache for this start afterwords warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) - default: - fallbackSource := NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) - opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) - + case s.Config.cacheWarmup.Source.CdnSource.Enabled: + var fallbackSource *PlanSource + if s.cacheWarmup.InMemoryFallback { + fallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) + opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) + } cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger, fallbackSource) if err != nil { return nil, fmt.Errorf("failed to create cdn source: %w", err) } warmupConfig.Source = cdnSource + default: + return nil, fmt.Errorf("unexpected cache warmer source provided") } err = WarmupCaches(ctx, warmupConfig) From 2fd47931e2ac4b83db938e69100eb86fb09e3cb0 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 20:57:16 +0530 Subject: [PATCH 42/52] fix: review comments --- router-tests/cache_warmup_test.go | 33 ++++++++++++++++++++++++++++ router/core/cache_warmup_cdn.go | 2 +- router/pkg/config/config.schema.json | 15 +++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 1b2c1e6f5a..25ca0403b6 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -619,6 +619,11 @@ func TestCacheWarmup(t *testing.T) { RouterOptions: []core.Option{ core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), }, AssertCacheMetrics: &testenv.CacheMetricsAssertions{ @@ -678,6 +683,11 @@ func TestCacheWarmup(t *testing.T) { RouterOptions: []core.Option{ core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), }, AssertCacheMetrics: &testenv.CacheMetricsAssertions{ @@ -721,6 +731,11 @@ func TestCacheWarmup(t *testing.T) { RouterOptions: []core.Option{ core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), }, AssertCacheMetrics: &testenv.CacheMetricsAssertions{ @@ -754,6 +769,11 @@ func TestCacheWarmup(t *testing.T) { RouterOptions: []core.Option{ core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), }, AssertCacheMetrics: &testenv.CacheMetricsAssertions{ @@ -929,6 +949,11 @@ func TestInMemorySwitchoverCaching(t *testing.T) { core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, InMemoryFallback: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), core.WithConfigVersionHeader(true), }, @@ -1019,6 +1044,11 @@ func TestInMemorySwitchoverCaching(t *testing.T) { core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ Enabled: true, InMemoryFallback: false, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, }), core.WithConfigVersionHeader(true), }, @@ -1118,6 +1148,9 @@ readiness_check_path: "/` + listenString + `" cache_warmup: enabled: true in_memory_fallback: true + source: + cdn: + enabled: true engine: debug: diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index 70062ea925..6e7c8d7c1b 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -76,7 +76,7 @@ func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations }() } - operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/operations.json", c.organizationID, c.federatedGraphID) + operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/aa.json", c.organizationID, c.federatedGraphID) operationURL := c.cdnURL.ResolveReference(&url.URL{Path: operationsPath}) log.Debug("Loading cache warmup config", zap.String("url", operationURL.String())) diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json index 934cd18960..6f44cdaf77 100644 --- a/router/pkg/config/config.schema.json +++ b/router/pkg/config/config.schema.json @@ -2405,11 +2405,26 @@ "format": "file-path" } } + }, + "cdn": { + "type": "object", + "description": "The CDN source of the cache warmup items.", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable or disable the CDN source for cache warmup.", + "default": true + } + } } }, "oneOf": [ { "required": ["filesystem"] + }, + { + "required": ["cdn"] } ] }, From 9308bdd2668926a8bfb303c379634d827e0c2837 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 21:36:15 +0530 Subject: [PATCH 43/52] fix: review comments --- router-tests/cache_warmup_test.go | 115 +++++++++++++++++++++++++++++- router/core/cache_warmup_cdn.go | 2 +- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/router-tests/cache_warmup_test.go b/router-tests/cache_warmup_test.go index 25ca0403b6..50213d0561 100644 --- a/router-tests/cache_warmup_test.go +++ b/router-tests/cache_warmup_test.go @@ -3,6 +3,7 @@ package integration import ( "context" "net/http" + "net/http/httptest" "os" "path/filepath" "syscall" @@ -24,6 +25,12 @@ import ( "go.uber.org/zap" ) +type fakeSelfRegister struct{} + +func (*fakeSelfRegister) Register(ctx context.Context) (*nodev1.RegistrationInfo, error) { + return nil, nil +} + func TestCacheWarmup(t *testing.T) { t.Parallel() @@ -1123,6 +1130,112 @@ func TestInMemorySwitchoverCaching(t *testing.T) { }) }) + t.Run("Verify fallback is used when cdn source is enabled but cdn returns 404 internally", func(t *testing.T) { + t.Parallel() + + // Create a temporary file for the router config + configFile := t.TempDir() + "/config.json" + + // Initial config with just the employees subgraph + writeTestConfig(t, "initial", configFile) + + var impl *fakeSelfRegister = nil + + testenv.Run(t, &testenv.Config{ + CdnSever: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + })), + RouterOptions: []core.Option{ + core.WithSelfRegistration(impl), + core.WithConfigVersionHeader(true), + core.WithExecutionConfig(&core.ExecutionConfig{ + Path: configFile, + Watch: true, + WatchInterval: 100 * time.Millisecond, + }), + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: true, + InMemoryFallback: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, + }), + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + require.Equal(t, 200, res.Response.StatusCode) + require.Equal(t, "initial", res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + writeTestConfig(t, "updated", configFile) + + require.EventuallyWithT(t, func(t *assert.CollectT) { + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + assert.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) + assert.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + }, 2*time.Second, 100*time.Millisecond) + }) + }) + + t.Run("Verify fallback is used when cdn source is enabled but cdn returns unauthorized internally", func(t *testing.T) { + t.Parallel() + + // Create a temporary file for the router config + configFile := t.TempDir() + "/config.json" + + // Initial config with just the employees subgraph + writeTestConfig(t, "initial", configFile) + + var impl *fakeSelfRegister = nil + + testenv.Run(t, &testenv.Config{ + CdnSever: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusUnauthorized) + })), + RouterOptions: []core.Option{ + core.WithSelfRegistration(impl), + core.WithConfigVersionHeader(true), + core.WithExecutionConfig(&core.ExecutionConfig{ + Path: configFile, + Watch: true, + WatchInterval: 100 * time.Millisecond, + }), + core.WithCacheWarmupConfig(&config.CacheWarmupConfiguration{ + Enabled: true, + InMemoryFallback: true, + Source: config.CacheWarmupSource{ + CdnSource: config.CacheWarmupCDNSource{ + Enabled: true, + }, + }, + }), + }, + }, func(t *testing.T, xEnv *testenv.Environment) { + res := xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + require.Equal(t, 200, res.Response.StatusCode) + require.Equal(t, "initial", res.Response.Header.Get("X-Router-Config-Version")) + require.Equal(t, "MISS", res.Response.Header.Get("x-wg-execution-plan-cache")) + + writeTestConfig(t, "updated", configFile) + + require.EventuallyWithT(t, func(t *assert.CollectT) { + res = xEnv.MakeGraphQLRequestOK(testenv.GraphQLRequest{ + Query: `query { hello }`, + }) + assert.Equal(t, "updated", res.Response.Header.Get("X-Router-Config-Version")) + assert.Equal(t, "HIT", res.Response.Header.Get("x-wg-execution-plan-cache")) + }, 2*time.Second, 100*time.Millisecond) + }) + }) + t.Run("Successfully persists cache across config change restarts", func(t *testing.T) { t.Parallel() @@ -1150,7 +1263,7 @@ cache_warmup: in_memory_fallback: true source: cdn: - enabled: true + enabled: false engine: debug: diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index 6e7c8d7c1b..70062ea925 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -76,7 +76,7 @@ func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations }() } - operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/aa.json", c.organizationID, c.federatedGraphID) + operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/operations.json", c.organizationID, c.federatedGraphID) operationURL := c.cdnURL.ResolveReference(&url.URL{Path: operationsPath}) log.Debug("Loading cache warmup config", zap.String("url", operationURL.String())) From f96e1f1ea40e6621cada8fae1a875fa97ffdcccd Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 21:39:44 +0530 Subject: [PATCH 44/52] fix: review comments --- router/core/cache_warmup_cdn.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index 70062ea925..b6b777065b 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -67,7 +67,8 @@ func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations // Defer fallback to PlanSource if items are nil if c.fallbackSource != nil { defer func() { - if operations == nil { + // If there were no operations loaded from CDN, use the fallbackSource + if len(operations) == 0 { if err != nil { log.Error("Falling back to PlanSource due to error loading cache warmup config from CDN", zap.Error(err)) } From ab75a5a435760b9c36bc36fd933f153ec829c814 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 21:46:00 +0530 Subject: [PATCH 45/52] fix: review comments --- router/core/restart_switchover_config_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index b5116525ad..bcf71fba50 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -22,7 +22,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.NotNil(t, cache.queriesForFeatureFlag) require.Empty(t, cache.queriesForFeatureFlag) @@ -41,7 +41,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.Nil(t, cache.queriesForFeatureFlag) }) From 172df6640628ddd7c90e90572a42bfa01f4ff452 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Mon, 26 Jan 2026 21:46:25 +0530 Subject: [PATCH 46/52] fix: review comments --- router/core/restart_switchover_config_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index bcf71fba50..81c74ad5d1 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -62,7 +62,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.NotNil(t, cache.queriesForFeatureFlag) require.Len(t, cache.queriesForFeatureFlag, 1) @@ -81,7 +81,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -96,7 +96,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t cacheWarmup: nil, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.Nil(t, cache.queriesForFeatureFlag) }) @@ -112,7 +112,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t }, } - cache.updateStateFromConfig(cfg, false) + cache.updateStateFromConfig(cfg) require.Nil(t, cache.queriesForFeatureFlag) }) From c3d23367f782e7e275ebcac07424d5f3111c0f2e Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Tue, 27 Jan 2026 02:23:22 +0530 Subject: [PATCH 47/52] fix: update comments --- router/core/graph_server.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index 1285642ea2..a26a105a1a 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1366,16 +1366,18 @@ func (s *graphServer) buildGraphMux( RootPath: s.Config.cacheWarmup.Source.Filesystem.Path, }) // Enable in-memory switchover fallback when: - // - Router has cache warmer with inMemorySwitchoverFallback enabled, AND + // - Router has cache warmer with inMemoryFallback enabled, AND // - Either: // - Using static execution config (not Cosmo): s.selfRegister == nil - // - OR Cosmo cache warmer is disabled: !opts.cosmoCacheWarmerEnabled + // - OR CDN cache warmer is explictly disabled case s.cacheWarmup.InMemoryFallback && (s.selfRegister == nil || !s.Config.cacheWarmup.Source.CdnSource.Enabled): // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries // and reset the plan cache to the new plan cache for this start afterwords warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) case s.Config.cacheWarmup.Source.CdnSource.Enabled: + // We use the in-memory cache as a fallback if enabled + // This is useful for when an issue occurs with the CDN when retrieving the required manifest var fallbackSource *PlanSource if s.cacheWarmup.InMemoryFallback { fallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) From 0f98b1d4bea04c159196867b129da4cdf314a6f0 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Thu, 29 Jan 2026 20:51:06 +0530 Subject: [PATCH 48/52] fix: review comments --- router/core/cache_warmup.go | 54 +++++++++++++++++++----- router/core/cache_warmup_cdn.go | 17 +------- router/core/cache_warmup_plans.go | 3 ++ router/core/graph_server.go | 9 ++-- router/core/restart_switchover_config.go | 4 +- 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/router/core/cache_warmup.go b/router/core/cache_warmup.go index b914567291..9c7620b4d0 100644 --- a/router/core/cache_warmup.go +++ b/router/core/cache_warmup.go @@ -34,6 +34,7 @@ type CacheWarmupProcessor interface { type CacheWarmupConfig struct { Log *zap.Logger Source CacheWarmupSource + FallbackSource CacheWarmupSource Workers int ItemsPerSecond int Timeout time.Duration @@ -45,6 +46,7 @@ func WarmupCaches(ctx context.Context, cfg *CacheWarmupConfig) (err error) { w := &cacheWarmup{ log: cfg.Log.With(zap.String("component", "cache_warmup")), source: cfg.Source, + fallbackSource: cfg.FallbackSource, workers: cfg.Workers, itemsPerSecond: cfg.ItemsPerSecond, timeout: cfg.Timeout, @@ -92,6 +94,7 @@ func WarmupCaches(ctx context.Context, cfg *CacheWarmupConfig) (err error) { type cacheWarmup struct { log *zap.Logger source CacheWarmupSource + fallbackSource CacheWarmupSource workers int itemsPerSecond int timeout time.Duration @@ -104,20 +107,12 @@ func (w *cacheWarmup) run(ctx context.Context) (int, error) { ctx, cancel := context.WithTimeout(ctx, w.timeout) defer cancel() - items, err := w.source.LoadItems(ctx, w.log) - if err != nil { + items, err := w.getItems(ctx) + // In case a provider returns err with > 0 items, we check for err != nil also + if len(items) == 0 || err != nil { return 0, err } - if len(items) == 0 { - w.log.Debug("No items to process") - return 0, nil - } - - w.log.Info("Starting processing", - zap.Int("items", len(items)), - ) - defaultClientInfo := &nodev1.ClientInfo{} done := ctx.Done() @@ -197,6 +192,43 @@ func (w *cacheWarmup) run(ctx context.Context) (int, error) { return len(items), nil } +func (w *cacheWarmup) getItems(ctx context.Context) (items []*nodev1.Operation, err error) { + // Defer fallback to PlanSource if items are nil + if w.fallbackSource != nil { + defer func() { + // If there were no operations loaded from CDN, use the fallbackSource + if len(items) == 0 { + fallbackItems, fallbackErr := w.fallbackSource.LoadItems(ctx, w.log) + + // Only override existing items from main source if the fallback source returned items WITHOUT error + if len(fallbackItems) > 0 && fallbackErr == nil { + if err != nil { + w.log.Error("Falling back to PlanSource due to error loading cache warmup config from CDN", zap.Error(err)) + } + items = fallbackItems + err = fallbackErr + } + } + }() + } + + items, err = w.source.LoadItems(ctx, w.log) + if err != nil { + return nil, err + } + + if len(items) == 0 { + w.log.Debug("No items to process") + return nil, nil + } + + w.log.Info("Starting processing", + zap.Int("items", len(items)), + ) + + return items, nil +} + type CacheWarmupPlanningProcessorOptions struct { OperationProcessor *OperationProcessor OperationPlanner *OperationPlanner diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index b6b777065b..993b83afc8 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -32,10 +32,9 @@ type CDNSource struct { // from the token, already url-escaped organizationID string httpClient *http.Client - fallbackSource *PlanSource } -func NewCDNSource(endpoint, token string, logger *zap.Logger, fallbackSource *PlanSource) (*CDNSource, error) { +func NewCDNSource(endpoint, token string, logger *zap.Logger) (*CDNSource, error) { u, err := url.Parse(endpoint) if err != nil { return nil, err @@ -56,7 +55,6 @@ func NewCDNSource(endpoint, token string, logger *zap.Logger, fallbackSource *Pl federatedGraphID: claims.FederatedGraphID, organizationID: claims.OrganizationID, httpClient: httpclient.NewRetryableHTTPClient(logger), - fallbackSource: fallbackSource, }, nil } @@ -64,19 +62,6 @@ func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations span := trace.SpanFromContext(ctx) defer span.End() - // Defer fallback to PlanSource if items are nil - if c.fallbackSource != nil { - defer func() { - // If there were no operations loaded from CDN, use the fallbackSource - if len(operations) == 0 { - if err != nil { - log.Error("Falling back to PlanSource due to error loading cache warmup config from CDN", zap.Error(err)) - } - operations, err = c.fallbackSource.LoadItems(ctx, log) - } - }() - } - operationsPath := fmt.Sprintf("/%s/%s/cache_warmup/operations.json", c.organizationID, c.federatedGraphID) operationURL := c.cdnURL.ResolveReference(&url.URL{Path: operationsPath}) diff --git a/router/core/cache_warmup_plans.go b/router/core/cache_warmup_plans.go index d4d5810de3..d5bd939a77 100644 --- a/router/core/cache_warmup_plans.go +++ b/router/core/cache_warmup_plans.go @@ -25,5 +25,8 @@ func NewPlanSource(switchoverCacheWarmerQueries []*nodev1.Operation) *PlanSource // LoadItems loads the items from the plan source when called by the cache warmer func (c *PlanSource) LoadItems(_ context.Context, _ *zap.Logger) ([]*nodev1.Operation, error) { + if c == nil { + return nil, nil + } return c.queries, nil } diff --git a/router/core/graph_server.go b/router/core/graph_server.go index a26a105a1a..bd23a50d54 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1371,19 +1371,18 @@ func (s *graphServer) buildGraphMux( // - Using static execution config (not Cosmo): s.selfRegister == nil // - OR CDN cache warmer is explictly disabled case s.cacheWarmup.InMemoryFallback && (s.selfRegister == nil || !s.Config.cacheWarmup.Source.CdnSource.Enabled): - // We first utilize the plan cache (if it was already set, so not on first starts) to create a list of queries - // and reset the plan cache to the new plan cache for this start afterwords + // We first utilize the existing plan cache (if it was already set, i.e., not on the first start) to create a list of queries + // and then reset the plan cache to the new plan cache for this start afterwards. warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) case s.Config.cacheWarmup.Source.CdnSource.Enabled: // We use the in-memory cache as a fallback if enabled // This is useful for when an issue occurs with the CDN when retrieving the required manifest - var fallbackSource *PlanSource if s.cacheWarmup.InMemoryFallback { - fallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) + warmupConfig.FallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) } - cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger, fallbackSource) + cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) if err != nil { return nil, fmt.Errorf("failed to create cdn source: %w", err) } diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 591cf867cc..36c662285f 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -135,8 +135,8 @@ func (c *InMemorySwitchoverCache) extractQueriesAndOverridePlanCache() { c.queriesForFeatureFlag = switchoverMap } -// cleanupUnusedFeatureFlags removes any feature flags from the in-memory switchover cache -// this is useful in case where the updated execution config excludes a feature flag +// cleanupUnusedFeatureFlags removes any feature flags that were removed from the execution config +// after a schema / execution config change func (c *InMemorySwitchoverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { c.mu.Lock() defer c.mu.Unlock() From e511bef37ec71286a774a323983d7394cc6560fd Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Fri, 30 Jan 2026 00:30:20 +0530 Subject: [PATCH 49/52] fix: review comments --- router/core/operation_planner.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/router/core/operation_planner.go b/router/core/operation_planner.go index 8048a1abb6..12ff2f6929 100644 --- a/router/core/operation_planner.go +++ b/router/core/operation_planner.go @@ -25,15 +25,15 @@ type planWithMetaData struct { } type OperationPlanner struct { - sf singleflight.Group - planCache ExecutionPlanCache[uint64, *planWithMetaData] - executor *Executor - trackUsageInfo bool - storeContent bool + sf singleflight.Group + planCache ExecutionPlanCache[uint64, *planWithMetaData] + executor *Executor + trackUsageInfo bool + operationContent bool } type operationPlannerOpts struct { - storeContent bool + operationContent bool } type ExecutionPlanCache[K any, V any] interface { @@ -49,10 +49,10 @@ type ExecutionPlanCache[K any, V any] interface { func NewOperationPlanner(executor *Executor, planCache ExecutionPlanCache[uint64, *planWithMetaData], storeContent bool) *OperationPlanner { return &OperationPlanner{ - planCache: planCache, - executor: executor, - trackUsageInfo: executor.TrackUsageInfo, - storeContent: storeContent, + planCache: planCache, + executor: executor, + trackUsageInfo: executor.TrackUsageInfo, + operationContent: storeContent, } } @@ -90,7 +90,7 @@ func (p *OperationPlanner) preparePlan(ctx *operationContext, opts operationPlan schemaDocument: p.executor.RouterSchema, } - if opts.storeContent { + if opts.operationContent { out.content = ctx.Content() } @@ -119,7 +119,7 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions skipCache := options.TraceOptions.Enable || options.ExecutionOptions.IncludeQueryPlanInResponse if skipCache { - prepared, err := p.preparePlan(opContext, operationPlannerOpts{storeContent: false}) + prepared, err := p.preparePlan(opContext, operationPlannerOpts{operationContent: false}) if err != nil { return err } @@ -147,7 +147,7 @@ func (p *OperationPlanner) plan(opContext *operationContext, options PlanOptions // this ensures that we only prepare the plan once for this operation ID operationIDStr := strconv.FormatUint(operationID, 10) sharedPreparedPlan, err, _ := p.sf.Do(operationIDStr, func() (interface{}, error) { - prepared, err := p.preparePlan(opContext, operationPlannerOpts{storeContent: p.storeContent}) + prepared, err := p.preparePlan(opContext, operationPlannerOpts{operationContent: p.operationContent}) if err != nil { return nil, err } From 91b9bfcd03d0977d937b41d0bd0cb0b62e606508 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Fri, 30 Jan 2026 14:57:48 +0530 Subject: [PATCH 50/52] fix: revert cdn --- router/core/cache_warmup_cdn.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/router/core/cache_warmup_cdn.go b/router/core/cache_warmup_cdn.go index 993b83afc8..526e618d87 100644 --- a/router/core/cache_warmup_cdn.go +++ b/router/core/cache_warmup_cdn.go @@ -5,11 +5,12 @@ import ( "context" "errors" "fmt" + nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" + "google.golang.org/protobuf/encoding/protojson" "io" "net/http" "net/url" - nodev1 "github.com/wundergraph/cosmo/router/gen/proto/wg/cosmo/node/v1" "github.com/wundergraph/cosmo/router/internal/httpclient" "github.com/wundergraph/cosmo/router/internal/jwt" "go.opentelemetry.io/otel/codes" @@ -17,7 +18,6 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" - "google.golang.org/protobuf/encoding/protojson" ) var _ CacheWarmupSource = (*CDNSource)(nil) @@ -58,7 +58,7 @@ func NewCDNSource(endpoint, token string, logger *zap.Logger) (*CDNSource, error }, nil } -func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) (operations []*nodev1.Operation, err error) { +func (c *CDNSource) LoadItems(ctx context.Context, log *zap.Logger) ([]*nodev1.Operation, error) { span := trace.SpanFromContext(ctx) defer span.End() From c10b5bfbe23a37601c6d8246368d792848673378 Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Fri, 30 Jan 2026 16:36:36 +0530 Subject: [PATCH 51/52] fix: review comments --- router/core/cache_warmup.go | 58 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/router/core/cache_warmup.go b/router/core/cache_warmup.go index 9c7620b4d0..9472f0ab91 100644 --- a/router/core/cache_warmup.go +++ b/router/core/cache_warmup.go @@ -107,12 +107,26 @@ func (w *cacheWarmup) run(ctx context.Context) (int, error) { ctx, cancel := context.WithTimeout(ctx, w.timeout) defer cancel() - items, err := w.getItems(ctx) - // In case a provider returns err with > 0 items, we check for err != nil also + items, err := w.source.LoadItems(ctx, w.log) + + // Try fallback if no items were loaded OR there was an error loading from main source if len(items) == 0 || err != nil { + items, err = w.loadFromFallbackSource(ctx, err) + } + + if err != nil { return 0, err } + if len(items) == 0 { + w.log.Debug("No items to process") + return 0, nil + } + + w.log.Info("Starting processing", + zap.Int("items", len(items)), + ) + defaultClientInfo := &nodev1.ClientInfo{} done := ctx.Done() @@ -192,41 +206,23 @@ func (w *cacheWarmup) run(ctx context.Context) (int, error) { return len(items), nil } -func (w *cacheWarmup) getItems(ctx context.Context) (items []*nodev1.Operation, err error) { - // Defer fallback to PlanSource if items are nil - if w.fallbackSource != nil { - defer func() { - // If there were no operations loaded from CDN, use the fallbackSource - if len(items) == 0 { - fallbackItems, fallbackErr := w.fallbackSource.LoadItems(ctx, w.log) - - // Only override existing items from main source if the fallback source returned items WITHOUT error - if len(fallbackItems) > 0 && fallbackErr == nil { - if err != nil { - w.log.Error("Falling back to PlanSource due to error loading cache warmup config from CDN", zap.Error(err)) - } - items = fallbackItems - err = fallbackErr - } - } - }() +func (w *cacheWarmup) loadFromFallbackSource(ctx context.Context, mainErr error) ([]*nodev1.Operation, error) { + if w.fallbackSource == nil { + return nil, mainErr } - items, err = w.source.LoadItems(ctx, w.log) + fallbackItems, err := w.fallbackSource.LoadItems(ctx, w.log) if err != nil { - return nil, err + // If fallback source also failed, log the fallback error and return the original error + w.log.Error("Failed to load cache warmup config from fallback source", zap.Error(err)) + return nil, mainErr } - if len(items) == 0 { - w.log.Debug("No items to process") - return nil, nil + // In case we went to the fallback because the main source had an error, log the original error + if mainErr != nil { + w.log.Error("Falling back to PlanSource due to error loading cache warmup config from CDN", zap.Error(mainErr)) } - - w.log.Info("Starting processing", - zap.Int("items", len(items)), - ) - - return items, nil + return fallbackItems, nil } type CacheWarmupPlanningProcessorOptions struct { From 4ef640cb0a38afcb0dea38a06e1fc5604579c16b Mon Sep 17 00:00:00 2001 From: Milinda Dias Date: Sun, 1 Feb 2026 01:16:57 +0530 Subject: [PATCH 52/52] fix: review comments --- router/core/graph_server.go | 10 ++--- router/core/restart_switchover_config.go | 26 +++++------ router/core/restart_switchover_config_test.go | 44 +++++++++---------- router/pkg/config/config.schema.json | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/router/core/graph_server.go b/router/core/graph_server.go index bd23a50d54..ccaf1e56c7 100644 --- a/router/core/graph_server.go +++ b/router/core/graph_server.go @@ -1310,7 +1310,7 @@ func (s *graphServer) buildGraphMux( ComplexityLimits: s.securityConfiguration.ComplexityLimits, }) - operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemorySwitchOverCache.IsEnabled()) + operationPlanner := NewOperationPlanner(executor, gm.planCache, opts.SwitchoverConfig.inMemoryPlanCacheFallback.IsEnabled()) // We support the MCP only on the base graph. Feature flags are not supported yet. if opts.IsBaseGraph() && s.mcpServer != nil { @@ -1373,14 +1373,14 @@ func (s *graphServer) buildGraphMux( case s.cacheWarmup.InMemoryFallback && (s.selfRegister == nil || !s.Config.cacheWarmup.Source.CdnSource.Enabled): // We first utilize the existing plan cache (if it was already set, i.e., not on the first start) to create a list of queries // and then reset the plan cache to the new plan cache for this start afterwards. - warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) - opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) + warmupConfig.Source = NewPlanSource(opts.SwitchoverConfig.inMemoryPlanCacheFallback.getPlanCacheForFF(opts.FeatureFlagName)) + opts.SwitchoverConfig.inMemoryPlanCacheFallback.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) case s.Config.cacheWarmup.Source.CdnSource.Enabled: // We use the in-memory cache as a fallback if enabled // This is useful for when an issue occurs with the CDN when retrieving the required manifest if s.cacheWarmup.InMemoryFallback { - warmupConfig.FallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemorySwitchOverCache.getPlanCacheForFF(opts.FeatureFlagName)) - opts.SwitchoverConfig.inMemorySwitchOverCache.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) + warmupConfig.FallbackSource = NewPlanSource(opts.SwitchoverConfig.inMemoryPlanCacheFallback.getPlanCacheForFF(opts.FeatureFlagName)) + opts.SwitchoverConfig.inMemoryPlanCacheFallback.setPlanCacheForFF(opts.FeatureFlagName, gm.planCache) } cdnSource, err := NewCDNSource(s.Config.cdnConfig.URL, s.graphApiToken, s.logger) if err != nil { diff --git a/router/core/restart_switchover_config.go b/router/core/restart_switchover_config.go index 36c662285f..bad7e98c4c 100644 --- a/router/core/restart_switchover_config.go +++ b/router/core/restart_switchover_config.go @@ -12,12 +12,12 @@ type planCache = *ristretto.Cache[uint64, *planWithMetaData] // SwitchoverConfig This file describes any configuration which should persist or be shared across router restarts type SwitchoverConfig struct { - inMemorySwitchOverCache *InMemorySwitchoverCache + inMemoryPlanCacheFallback *InMemoryPlanCacheFallback } func NewSwitchoverConfig(logger *zap.Logger) *SwitchoverConfig { return &SwitchoverConfig{ - inMemorySwitchOverCache: &InMemorySwitchoverCache{ + inMemoryPlanCacheFallback: &InMemoryPlanCacheFallback{ logger: logger, }, } @@ -25,13 +25,13 @@ func NewSwitchoverConfig(logger *zap.Logger) *SwitchoverConfig { // UpdateSwitchoverConfig updates the switchover config based on the provided config. func (s *SwitchoverConfig) UpdateSwitchoverConfig(config *Config) { - s.inMemorySwitchOverCache.updateStateFromConfig(config) + s.inMemoryPlanCacheFallback.updateStateFromConfig(config) } // CleanupFeatureFlags cleans up anything related to unused feature flags due to being now excluded // from the execution config func (s *SwitchoverConfig) CleanupFeatureFlags(routerCfg *nodev1.RouterConfig) { - s.inMemorySwitchOverCache.cleanupUnusedFeatureFlags(routerCfg) + s.inMemoryPlanCacheFallback.cleanupUnusedFeatureFlags(routerCfg) } func (s *SwitchoverConfig) OnRouterConfigReload() { @@ -42,18 +42,18 @@ func (s *SwitchoverConfig) OnRouterConfigReload() { // There can be inflight requests when this is called even though it's called in the restart path, // This is because this is called before the router instance is shutdown before being reloaded - s.inMemorySwitchOverCache.extractQueriesAndOverridePlanCache() + s.inMemoryPlanCacheFallback.extractQueriesAndOverridePlanCache() } -// InMemorySwitchoverCache is a store that stores either queries or references to the planner cache for use with the cache warmer -type InMemorySwitchoverCache struct { +// InMemoryPlanCacheFallback is a store that stores either queries or references to the planner cache for use with the cache warmer +type InMemoryPlanCacheFallback struct { mu sync.RWMutex queriesForFeatureFlag map[string]any logger *zap.Logger } // updateStateFromConfig updates the internal state of the in-memory switchover cache based on the provided config -func (c *InMemorySwitchoverCache) updateStateFromConfig(config *Config) { +func (c *InMemoryPlanCacheFallback) updateStateFromConfig(config *Config) { enabled := config.cacheWarmup != nil && config.cacheWarmup.Enabled && config.cacheWarmup.InMemoryFallback @@ -75,7 +75,7 @@ func (c *InMemorySwitchoverCache) updateStateFromConfig(config *Config) { } // IsEnabled returns whether the in-memory switchover cache is enabled -func (c *InMemorySwitchoverCache) IsEnabled() bool { +func (c *InMemoryPlanCacheFallback) IsEnabled() bool { c.mu.RLock() defer c.mu.RUnlock() @@ -83,7 +83,7 @@ func (c *InMemorySwitchoverCache) IsEnabled() bool { } // getPlanCacheForFF gets the plan cache in the []*nodev1.Operation format for a specific feature flag key -func (c *InMemorySwitchoverCache) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { +func (c *InMemoryPlanCacheFallback) getPlanCacheForFF(featureFlagKey string) []*nodev1.Operation { c.mu.RLock() defer c.mu.RUnlock() @@ -107,7 +107,7 @@ func (c *InMemorySwitchoverCache) getPlanCacheForFF(featureFlagKey string) []*no } // setPlanCacheForFF sets the plan cache for a specific feature flag key -func (c *InMemorySwitchoverCache) setPlanCacheForFF(featureFlagKey string, cache planCache) { +func (c *InMemoryPlanCacheFallback) setPlanCacheForFF(featureFlagKey string, cache planCache) { c.mu.Lock() defer c.mu.Unlock() @@ -118,7 +118,7 @@ func (c *InMemorySwitchoverCache) setPlanCacheForFF(featureFlagKey string, cache } // extractQueriesAndOverridePlanCache extracts the queries from the plan cache and overrides the internal map -func (c *InMemorySwitchoverCache) extractQueriesAndOverridePlanCache() { +func (c *InMemoryPlanCacheFallback) extractQueriesAndOverridePlanCache() { c.mu.Lock() defer c.mu.Unlock() @@ -137,7 +137,7 @@ func (c *InMemorySwitchoverCache) extractQueriesAndOverridePlanCache() { // cleanupUnusedFeatureFlags removes any feature flags that were removed from the execution config // after a schema / execution config change -func (c *InMemorySwitchoverCache) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { +func (c *InMemoryPlanCacheFallback) cleanupUnusedFeatureFlags(routerCfg *nodev1.RouterConfig) { c.mu.Lock() defer c.mu.Unlock() diff --git a/router/core/restart_switchover_config_test.go b/router/core/restart_switchover_config_test.go index 81c74ad5d1..33105a240e 100644 --- a/router/core/restart_switchover_config_test.go +++ b/router/core/restart_switchover_config_test.go @@ -14,7 +14,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t t.Parallel() t.Run("enable cache from disabled state", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{} + cache := &InMemoryPlanCacheFallback{} cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ Enabled: true, @@ -30,7 +30,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t t.Run("disable cache from enabled state", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test"] = nil @@ -51,7 +51,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t existingMap := make(map[string]any) existingMap["test"] = nil - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: existingMap, } @@ -71,7 +71,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t t.Run("update when already disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } @@ -88,7 +88,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t t.Run("nil cacheWarmup config disables cache", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } @@ -103,7 +103,7 @@ func TestInMemorySwitchoverCache_UpdateInMemorySwitchoverCacheForConfigChanges(t t.Run("cacheWarmup enabled but InMemoryFallback disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{} + cache := &InMemoryPlanCacheFallback{} cfg := &Config{ cacheWarmup: &config.CacheWarmupConfiguration{ @@ -137,7 +137,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { mockCache.Set(2, &planWithMetaData{content: query2}, 1) mockCache.Wait() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test-ff"] = mockCache @@ -163,7 +163,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { {Request: &nodev1.OperationRequest{Query: "query { test2 }"}}, } - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["test-ff"] = expectedOps @@ -176,7 +176,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { t.Run("returns empty slice for non-existent feature flag", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ logger: zap.NewNop(), queriesForFeatureFlag: make(map[string]any), } @@ -187,7 +187,7 @@ func TestInMemorySwitchOverCache_GetPlanCacheForFF(t *testing.T) { t.Run("returns nil when cache is disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } @@ -208,7 +208,7 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { }) require.NoError(t, err) - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } @@ -228,7 +228,7 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { }) require.NoError(t, err) - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } @@ -239,7 +239,7 @@ func TestInMemorySwitchOverCache_SetPlanCacheForFF(t *testing.T) { t.Run("does not set nil cache", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } @@ -253,7 +253,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Parallel() t.Run("removes unused feature flags", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = nil @@ -279,7 +279,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("keeps empty string feature flag", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag[""] = nil @@ -300,7 +300,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("does nothing when cache is disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } @@ -318,7 +318,7 @@ func TestInMemorySwitchOverCache_CleanupUnusedFeatureFlags(t *testing.T) { t.Run("does nothing when FeatureFlagConfigs is nil", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = nil @@ -363,7 +363,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { mockCache2.Set(2, &planWithMetaData{content: query2}, 1) mockCache2.Wait() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } cache.queriesForFeatureFlag["ff1"] = mockCache1 @@ -386,7 +386,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { t.Run("does nothing when cache is disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } @@ -398,7 +398,7 @@ func TestInMemorySwitchOverCache_ProcessOnConfigChangeRestart(t *testing.T) { t.Run("handles empty cache", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } @@ -414,7 +414,7 @@ func TestInMemorySwitchOverCache_IsEnabled(t *testing.T) { t.Parallel() t.Run("returns true when cache is enabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: make(map[string]any), } @@ -423,7 +423,7 @@ func TestInMemorySwitchOverCache_IsEnabled(t *testing.T) { t.Run("returns false when cache is disabled", func(t *testing.T) { t.Parallel() - cache := &InMemorySwitchoverCache{ + cache := &InMemoryPlanCacheFallback{ queriesForFeatureFlag: nil, } diff --git a/router/pkg/config/config.schema.json b/router/pkg/config/config.schema.json index 6f44cdaf77..fe09b965a9 100644 --- a/router/pkg/config/config.schema.json +++ b/router/pkg/config/config.schema.json @@ -2448,7 +2448,7 @@ }, "in_memory_fallback": { "type": "boolean", - "description": "Enable in-memory fallback. When enabled, the router will cache query plans in memory and reuse them on schema changes and hot config reloads. This is useful when deploying new router configurations without downtime. The default value is true.", + "description": "Enable in-memory fallback. When enabled, the router will reuse the cached query plans in memory and use it to rewarm the cache on schema changes and hot config reloads. The default value is true.", "default": true } }