From bb076cf56c6862ea8ff9183c5a42bd5547bed8e1 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 21 Aug 2025 11:29:27 -0700 Subject: [PATCH 1/6] [WIP] Fallback & parallel requests --- data/reporter_http.go | 4 ++-- observation/gateway.pb.go | 14 ++++++++++++-- proto/path/gateway.proto | 8 ++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/data/reporter_http.go b/data/reporter_http.go index 461efcd99..17c705585 100644 --- a/data/reporter_http.go +++ b/data/reporter_http.go @@ -42,8 +42,8 @@ type DataReporterHTTP struct { func (drh *DataReporterHTTP) Publish(observations *observation.RequestResponseObservations) { logger := drh.hydrateLogger(observations) - // TODO_MVP(@adshmh): Replace this with the new DataRecord struct once the data pipeline is updated. - // convert to legacy-formatted data record + // TODO_MVP(@adshmh): Replace this with the new DataRecord struct once + // the data pipeline is updated. convert to legacy-formatted data record legacyDataRecord := buildLegacyDataRecord(logger, observations) // Marshal the data record. diff --git a/observation/gateway.pb.go b/observation/gateway.pb.go index 3ef6da62d..80e8e36ea 100644 --- a/observation/gateway.pb.go +++ b/observation/gateway.pb.go @@ -37,6 +37,10 @@ const ( RequestType_REQUEST_TYPE_ORGANIC RequestType = 1 // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. RequestType_REQUEST_TYPE_SYNTHETIC RequestType = 2 + // Parallel: Service request sent by PATH for internal purposes. + RequestType_REQUEST_TYPE_PARALLEL RequestType = 4 + // Fallback: Service request sent by PATH for internal purposes. + RequestType_REQUEST_TYPE_FALLBACK RequestType = 5 ) // Enum value maps for RequestType. @@ -45,11 +49,15 @@ var ( 0: "REQUEST_TYPE_UNSPECIFIED", 1: "REQUEST_TYPE_ORGANIC", 2: "REQUEST_TYPE_SYNTHETIC", + 4: "REQUEST_TYPE_PARALLEL", + 5: "REQUEST_TYPE_FALLBACK", } RequestType_value = map[string]int32{ "REQUEST_TYPE_UNSPECIFIED": 0, "REQUEST_TYPE_ORGANIC": 1, "REQUEST_TYPE_SYNTHETIC": 2, + "REQUEST_TYPE_PARALLEL": 4, + "REQUEST_TYPE_FALLBACK": 5, } ) @@ -400,11 +408,13 @@ const file_path_gateway_proto_rawDesc = "" + "\x0enum_successful\x18\x02 \x01(\x05R\rnumSuccessful\x12\x1d\n" + "\n" + "num_failed\x18\x03 \x01(\x05R\tnumFailed\x12!\n" + - "\fnum_canceled\x18\x04 \x01(\x05R\vnumCanceled*a\n" + + "\fnum_canceled\x18\x04 \x01(\x05R\vnumCanceled*\x97\x01\n" + "\vRequestType\x12\x1c\n" + "\x18REQUEST_TYPE_UNSPECIFIED\x10\x00\x12\x18\n" + "\x14REQUEST_TYPE_ORGANIC\x10\x01\x12\x1a\n" + - "\x16REQUEST_TYPE_SYNTHETIC\x10\x02*\xa8\x01\n" + + "\x16REQUEST_TYPE_SYNTHETIC\x10\x02\x12\x19\n" + + "\x15REQUEST_TYPE_PARALLEL\x10\x04\x12\x19\n" + + "\x15REQUEST_TYPE_FALLBACK\x10\x05*\xa8\x01\n" + "\x17GatewayRequestErrorKind\x12*\n" + "&GATEWAY_REQUEST_ERROR_KIND_UNSPECIFIED\x10\x00\x121\n" + "-GATEWAY_REQUEST_ERROR_KIND_MISSING_SERVICE_ID\x10\x01\x12.\n" + diff --git a/proto/path/gateway.proto b/proto/path/gateway.proto index 7b34b2548..a960452d2 100644 --- a/proto/path/gateway.proto +++ b/proto/path/gateway.proto @@ -15,10 +15,18 @@ import "path/auth.proto"; // import RequestAuth message. // 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. enum RequestType { REQUEST_TYPE_UNSPECIFIED = 0; + // Organic: Service request sent by a user. REQUEST_TYPE_ORGANIC = 1; + // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. REQUEST_TYPE_SYNTHETIC = 2; + + // Parallel: Service request sent by PATH for internal purposes. + REQUEST_TYPE_PARALLEL = 4; + + // Fallback: Service request sent by PATH for internal purposes. + REQUEST_TYPE_FALLBACK = 5; } enum GatewayRequestErrorKind { From dab1dfd0a82a239e383156f3aded3da0a6aee73e Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 22 Aug 2025 16:28:19 -0700 Subject: [PATCH 2/6] Checkpoint --- .serena/memories/metrics_patterns.md | 22 ++++++++++++++-------- data/reporter_http.go | 4 ++-- proto/path/gateway.proto | 5 +++++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.serena/memories/metrics_patterns.md b/.serena/memories/metrics_patterns.md index 62d9d4d58..e1aef97c8 100644 --- a/.serena/memories/metrics_patterns.md +++ b/.serena/memories/metrics_patterns.md @@ -3,30 +3,34 @@ ## Current Prometheus Metrics Setup ### Structure -- **Central metrics files**: - - `metrics/gateway.go` - Gateway-level metrics (requests, duration, response size) - - `metrics/server.go` - Prometheus metrics server setup - - `metrics/prometheus_reporter.go` - Metrics reporter interface - - `cmd/metrics.go` - Metrics server initialization -### Protocol-specific metrics +**Central metrics files:** +- `metrics/gateway.go` - Gateway-level metrics (requests, duration, response size) +- `metrics/server.go` - Prometheus metrics server setup +- `metrics/prometheus_reporter.go` - Metrics reporter interface +- `cmd/metrics.go` - Metrics server initialization + +**Protocol-specific metrics:** - `metrics/protocol/shannon/metrics.go` - Shannon protocol metrics -### QoS-specific metrics +**QoS-specific metrics:** - `metrics/qos/evm/metrics.go` - EVM QoS metrics - `metrics/qos/solana/metrics.go` - Solana QoS metrics ## Pattern Analysis ### Common Constants + - All metrics files use `pathProcess = "path"` as the subsystem name - Each file defines specific metric name constants (e.g., `requestsTotal`, `relaysTotalMetric`) ### Registration Pattern + - Each metrics file has an `init()` function that calls `prometheus.MustRegister()` for its metrics - Metrics are defined as package-level variables using `prometheus.NewCounterVec`, `prometheus.NewHistogramVec` ### Metric Definition Structure + ```go var myMetric = prometheus.NewCounterVec( prometheus.CounterOpts{ @@ -39,11 +43,13 @@ var myMetric = prometheus.NewCounterVec( ``` ### Publishing Pattern + - Each metrics file has a `PublishMetrics()` function - Uses `prometheus.Labels{}` to set label values - Calls `.With(labels).Inc()` or `.Observe(value)` on metrics ## Version Handling + - Project uses git-based versioning: `git describe --tags --always --dirty` - No existing version metric found in current setup -- Build process uses ldflags in `makefiles/release.mk` \ No newline at end of file +- Build process uses ldflags in `makefiles/release.mk` diff --git a/data/reporter_http.go b/data/reporter_http.go index 17c705585..461efcd99 100644 --- a/data/reporter_http.go +++ b/data/reporter_http.go @@ -42,8 +42,8 @@ type DataReporterHTTP struct { func (drh *DataReporterHTTP) Publish(observations *observation.RequestResponseObservations) { logger := drh.hydrateLogger(observations) - // TODO_MVP(@adshmh): Replace this with the new DataRecord struct once - // the data pipeline is updated. convert to legacy-formatted data record + // TODO_MVP(@adshmh): Replace this with the new DataRecord struct once the data pipeline is updated. + // convert to legacy-formatted data record legacyDataRecord := buildLegacyDataRecord(logger, observations) // Marshal the data record. diff --git a/proto/path/gateway.proto b/proto/path/gateway.proto index a960452d2..24756ef90 100644 --- a/proto/path/gateway.proto +++ b/proto/path/gateway.proto @@ -13,6 +13,7 @@ import "path/auth.proto"; // import RequestAuth message. // As of PR #72, it is one of: // 1. Organic: a real user sent a service request to a PATH instance // 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. +// Next free index: 6 enum RequestType { REQUEST_TYPE_UNSPECIFIED = 0; @@ -22,6 +23,10 @@ enum RequestType { // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. REQUEST_TYPE_SYNTHETIC = 2; + // Reserved for future use + reserved 3; + reserved "REQUEST_TYPE_RESERVED_3"; + // Parallel: Service request sent by PATH for internal purposes. REQUEST_TYPE_PARALLEL = 4; From 368c83ffba40348ab1e8f9839769b068e0f504e4 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 22 Aug 2025 17:00:48 -0700 Subject: [PATCH 3/6] Checkpoint --- gateway/http_request_context.go | 17 +++++++++++++++++ gateway/http_request_context_handle_request.go | 3 +++ observation/gateway.pb.go | 16 ++++++++++++++-- observation/protocol/shannon.pb.go | 1 + proto/path/gateway.proto | 8 ++------ 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/gateway/http_request_context.go b/gateway/http_request_context.go index 8a5eed1de..3582ccea3 100644 --- a/gateway/http_request_context.go +++ b/gateway/http_request_context.go @@ -375,6 +375,23 @@ func (rc *requestContext) updateProtocolObservations(protocolContextSetupErrorOb rc.logger.Debug().Msgf("%d protocol contexts were built for the request, but only using the first one for observations", len(rc.protocolContexts)) observations := rc.protocolContexts[0].GetObservations() rc.protocolObservations = &observations + + // Check if a fallback endpoint was used and update request type accordingly + // Only update if not already set as PARALLEL (which takes precedence) + if rc.gatewayObservations.RequestType != observation.RequestType_REQUEST_TYPE_PARALLEL { + if shannonObs := observations.GetShannon(); shannonObs != nil { + for _, reqObs := range shannonObs.GetObservations() { + if httpObs := reqObs.GetHttpObservations(); httpObs != nil { + for _, obs := range httpObs.GetEndpointObservations() { + if obs.GetIsFallbackEndpoint() { + rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_FALLBACK + break + } + } + } + } + } + } return } diff --git a/gateway/http_request_context_handle_request.go b/gateway/http_request_context_handle_request.go index e8818636e..78464a644 100644 --- a/gateway/http_request_context_handle_request.go +++ b/gateway/http_request_context_handle_request.go @@ -10,6 +10,7 @@ import ( "github.com/pokt-network/poktroll/pkg/polylog" shannonmetrics "github.com/buildwithgrove/path/metrics/protocol/shannon" + "github.com/buildwithgrove/path/observation" "github.com/buildwithgrove/path/protocol" ) @@ -60,6 +61,8 @@ func (rc *requestContext) HandleRelayRequest() error { // If we have multiple protocol contexts, send parallel requests if isParallel { logger.Debug().Msgf("Handling %d parallel relay requests", len(rc.protocolContexts)) + // Update request type to PARALLEL for parallel requests + rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_PARALLEL return rc.handleParallelRelayRequests() } diff --git a/observation/gateway.pb.go b/observation/gateway.pb.go index 9b382c52a..1e15c2fae 100644 --- a/observation/gateway.pb.go +++ b/observation/gateway.pb.go @@ -29,6 +29,8 @@ const ( // As of PR #72, it is one of: // 1. Organic: a real user sent a service request to a PATH instance // 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. +// +// Next free index: 6 type RequestType int32 const ( @@ -37,6 +39,10 @@ const ( RequestType_REQUEST_TYPE_ORGANIC RequestType = 1 // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. RequestType_REQUEST_TYPE_SYNTHETIC RequestType = 2 + // Parallel: Service request sent by PATH for internal purposes. + RequestType_REQUEST_TYPE_PARALLEL RequestType = 3 + // Fallback: Service request sent by PATH for internal purposes. + RequestType_REQUEST_TYPE_FALLBACK RequestType = 4 ) // Enum value maps for RequestType. @@ -45,11 +51,15 @@ var ( 0: "REQUEST_TYPE_UNSPECIFIED", 1: "REQUEST_TYPE_ORGANIC", 2: "REQUEST_TYPE_SYNTHETIC", + 3: "REQUEST_TYPE_PARALLEL", + 4: "REQUEST_TYPE_FALLBACK", } RequestType_value = map[string]int32{ "REQUEST_TYPE_UNSPECIFIED": 0, "REQUEST_TYPE_ORGANIC": 1, "REQUEST_TYPE_SYNTHETIC": 2, + "REQUEST_TYPE_PARALLEL": 3, + "REQUEST_TYPE_FALLBACK": 4, } ) @@ -414,11 +424,13 @@ const file_path_gateway_proto_rawDesc = "" + "\x0enum_successful\x18\x02 \x01(\x05R\rnumSuccessful\x12\x1d\n" + "\n" + "num_failed\x18\x03 \x01(\x05R\tnumFailed\x12!\n" + - "\fnum_canceled\x18\x04 \x01(\x05R\vnumCanceled*a\n" + + "\fnum_canceled\x18\x04 \x01(\x05R\vnumCanceled*\x97\x01\n" + "\vRequestType\x12\x1c\n" + "\x18REQUEST_TYPE_UNSPECIFIED\x10\x00\x12\x18\n" + "\x14REQUEST_TYPE_ORGANIC\x10\x01\x12\x1a\n" + - "\x16REQUEST_TYPE_SYNTHETIC\x10\x02*\x9e\x02\n" + + "\x16REQUEST_TYPE_SYNTHETIC\x10\x02\x12\x19\n" + + "\x15REQUEST_TYPE_PARALLEL\x10\x03\x12\x19\n" + + "\x15REQUEST_TYPE_FALLBACK\x10\x04*\x9e\x02\n" + "\x17GatewayRequestErrorKind\x12*\n" + "&GATEWAY_REQUEST_ERROR_KIND_UNSPECIFIED\x10\x00\x121\n" + "-GATEWAY_REQUEST_ERROR_KIND_MISSING_SERVICE_ID\x10\x01\x12.\n" + diff --git a/observation/protocol/shannon.pb.go b/observation/protocol/shannon.pb.go index 4198c9873..5e4066d3f 100644 --- a/observation/protocol/shannon.pb.go +++ b/observation/protocol/shannon.pb.go @@ -783,6 +783,7 @@ func (x *ShannonWebsocketMessageObservation) GetIsFallbackEndpoint() bool { // ShannonRequestObservations represents observations collected during the processing // of a single Shannon protocol relay request. +// Next free field: 6 type ShannonRequestObservations struct { state protoimpl.MessageState `protogen:"open.v1"` // Service ID (i.e. chain ID) for which the observation was made diff --git a/proto/path/gateway.proto b/proto/path/gateway.proto index 1e2eb93bd..c20f26a81 100644 --- a/proto/path/gateway.proto +++ b/proto/path/gateway.proto @@ -23,15 +23,11 @@ enum RequestType { // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. REQUEST_TYPE_SYNTHETIC = 2; - // Reserved for future use - reserved 3; - reserved "REQUEST_TYPE_RESERVED_3"; - // Parallel: Service request sent by PATH for internal purposes. - REQUEST_TYPE_PARALLEL = 4; + REQUEST_TYPE_PARALLEL = 3; // Fallback: Service request sent by PATH for internal purposes. - REQUEST_TYPE_FALLBACK = 5; + REQUEST_TYPE_FALLBACK = 4; } enum GatewayRequestErrorKind { From 39ea9a2e5e40672623ae9b0446f5ae32cb6a9583 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 22 Aug 2025 17:35:16 -0700 Subject: [PATCH 4/6] Checkpoint --- gateway/http_request_context.go | 17 ----------------- gateway/http_request_context_handle_request.go | 6 ++++-- gateway/observation.go | 2 +- observation/gateway.pb.go | 9 +++++---- proto/path/gateway.proto | 2 +- protocol/shannon/context.go | 4 ++++ 6 files changed, 15 insertions(+), 25 deletions(-) diff --git a/gateway/http_request_context.go b/gateway/http_request_context.go index 3582ccea3..8a5eed1de 100644 --- a/gateway/http_request_context.go +++ b/gateway/http_request_context.go @@ -375,23 +375,6 @@ func (rc *requestContext) updateProtocolObservations(protocolContextSetupErrorOb rc.logger.Debug().Msgf("%d protocol contexts were built for the request, but only using the first one for observations", len(rc.protocolContexts)) observations := rc.protocolContexts[0].GetObservations() rc.protocolObservations = &observations - - // Check if a fallback endpoint was used and update request type accordingly - // Only update if not already set as PARALLEL (which takes precedence) - if rc.gatewayObservations.RequestType != observation.RequestType_REQUEST_TYPE_PARALLEL { - if shannonObs := observations.GetShannon(); shannonObs != nil { - for _, reqObs := range shannonObs.GetObservations() { - if httpObs := reqObs.GetHttpObservations(); httpObs != nil { - for _, obs := range httpObs.GetEndpointObservations() { - if obs.GetIsFallbackEndpoint() { - rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_FALLBACK - break - } - } - } - } - } - } return } diff --git a/gateway/http_request_context_handle_request.go b/gateway/http_request_context_handle_request.go index 78464a644..b4e1b4fbd 100644 --- a/gateway/http_request_context_handle_request.go +++ b/gateway/http_request_context_handle_request.go @@ -61,8 +61,6 @@ func (rc *requestContext) HandleRelayRequest() error { // If we have multiple protocol contexts, send parallel requests if isParallel { logger.Debug().Msgf("Handling %d parallel relay requests", len(rc.protocolContexts)) - // Update request type to PARALLEL for parallel requests - rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_PARALLEL return rc.handleParallelRelayRequests() } @@ -87,6 +85,10 @@ func (rc *requestContext) handleSingleRelayRequest() error { // handleParallelRelayRequests orchestrates parallel relay requests and returns the first successful response. func (rc *requestContext) handleParallelRelayRequests() error { + // Only the gateway context can trigger parallel requests. + // We update the request type accordingly here. + rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_PARALLEL + metrics := ¶llelRequestMetrics{ numRequestsToAttempt: len(rc.protocolContexts), overallStartTime: time.Now(), diff --git a/gateway/observation.go b/gateway/observation.go index d3d8d0528..b684ca2af 100644 --- a/gateway/observation.go +++ b/gateway/observation.go @@ -67,7 +67,7 @@ const ( // regionEuropeNorth1 = "europe-north1" // Europe North region ) -// ---------- User Requests ---------- +// ---------- User (i.e. Organic) Requests ---------- // getUserRequestGatewayObservations returns gateway-level observations for an organic, i.e. from a user, request. func getUserRequestGatewayObservations(httpReq *http.Request) *observation.GatewayObservations { diff --git a/observation/gateway.pb.go b/observation/gateway.pb.go index 1e15c2fae..12775b28d 100644 --- a/observation/gateway.pb.go +++ b/observation/gateway.pb.go @@ -10,12 +10,13 @@ package observation import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" unsafe "unsafe" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -30,7 +31,7 @@ const ( // 1. Organic: a real user sent a service request to a PATH instance // 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. // -// Next free index: 6 +// Next free index: 5 type RequestType int32 const ( diff --git a/proto/path/gateway.proto b/proto/path/gateway.proto index c20f26a81..0a2b49ddd 100644 --- a/proto/path/gateway.proto +++ b/proto/path/gateway.proto @@ -13,7 +13,7 @@ import "path/auth.proto"; // import RequestAuth message. // As of PR #72, it is one of: // 1. Organic: a real user sent a service request to a PATH instance // 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. -// Next free index: 6 +// Next free index: 5 enum RequestType { REQUEST_TYPE_UNSPECIFIED = 0; diff --git a/protocol/shannon/context.go b/protocol/shannon/context.go index cfbcbc695..31cbe2386 100644 --- a/protocol/shannon/context.go +++ b/protocol/shannon/context.go @@ -18,6 +18,7 @@ import ( sdk "github.com/pokt-network/shannon-sdk" "github.com/buildwithgrove/path/gateway" + "github.com/buildwithgrove/path/observation" protocolobservations "github.com/buildwithgrove/path/observation/protocol" "github.com/buildwithgrove/path/protocol" ) @@ -180,6 +181,9 @@ func (rc *requestContext) executeRelayRequest(payload protocol.Payload) (protoco // - Used when endpoint is explicitly configured as a fallback endpoint case selectedEndpoint.IsFallback(): rc.logger.Debug().Msg("Executing fallback relay") + // Update request type to PARALLEL for parallel requests + rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_PARALLEL + return rc.sendFallbackRelay(selectedEndpoint, payload) // ** Priority 2: Check Network conditions ** From cae1e4afebaf0490584f348af87499c1deb97830 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 22 Aug 2025 17:46:17 -0700 Subject: [PATCH 5/6] Added TODOs --- gateway/http_request_context_handle_request.go | 12 ++++++++---- proto/path/gateway.proto | 13 ++++++------- protocol/shannon/context.go | 4 ++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/gateway/http_request_context_handle_request.go b/gateway/http_request_context_handle_request.go index b4e1b4fbd..f9712fb19 100644 --- a/gateway/http_request_context_handle_request.go +++ b/gateway/http_request_context_handle_request.go @@ -60,6 +60,8 @@ func (rc *requestContext) HandleRelayRequest() error { // If we have multiple protocol contexts, send parallel requests if isParallel { + // TODO_CONSIDERATION: Should only organic requests ever have the option to be parallelized? + // This will require a reconsideration of this feature, how observation are managed, etc... logger.Debug().Msgf("Handling %d parallel relay requests", len(rc.protocolContexts)) return rc.handleParallelRelayRequests() } @@ -71,9 +73,11 @@ func (rc *requestContext) HandleRelayRequest() error { // handleSingleRelayRequest handles a single relay request (original behavior) func (rc *requestContext) handleSingleRelayRequest() error { - // Send the service request payload, through the protocol context, to the selected endpoint. // In this code path, we are always guaranteed to have exactly one protocol context. - endpointResponse, err := rc.protocolContexts[0].HandleServiceRequest(rc.qosCtx.GetServicePayload()) + protocolRequestContext := rc.protocolContexts[0] + + // Send the service request payload, through the protocol context, to the selected endpoint. + endpointResponse, err := protocolRequestContext.HandleServiceRequest(rc.qosCtx.GetServicePayload()) if err != nil { rc.logger.Warn().Err(err).Msg("Failed to send a single relay request.") return err @@ -139,13 +143,13 @@ func (rc *requestContext) launchParallelRequests(ctx context.Context, logger pol func (rc *requestContext) executeOneOfParallelRequests( ctx context.Context, logger polylog.Logger, - protocolCtx ProtocolRequestContext, + protocolRequestCtx ProtocolRequestContext, index int, resultChan chan<- parallelRelayResult, qosContextMutex *sync.Mutex, ) { startTime := time.Now() - endpointResponse, err := protocolCtx.HandleServiceRequest(rc.qosCtx.GetServicePayload()) + endpointResponse, err := protocolRequestCtx.HandleServiceRequest(rc.qosCtx.GetServicePayload()) duration := time.Since(startTime) result := parallelRelayResult{ diff --git a/proto/path/gateway.proto b/proto/path/gateway.proto index 0a2b49ddd..540e0544e 100644 --- a/proto/path/gateway.proto +++ b/proto/path/gateway.proto @@ -10,23 +10,22 @@ import "google/protobuf/timestamp.proto"; import "path/auth.proto"; // import RequestAuth message. // RequestType captures the origin of the request. -// As of PR #72, it is one of: -// 1. Organic: a real user sent a service request to a PATH instance -// 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. // Next free index: 5 enum RequestType { REQUEST_TYPE_UNSPECIFIED = 0; - // Organic: Service request sent by a user. + // Organic: A real user sent a service request to a PATH instance REQUEST_TYPE_ORGANIC = 1; - // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. + // Synthetic: Internal infrastructure generated the service request for simulation and data purposes. REQUEST_TYPE_SYNTHETIC = 2; - // Parallel: Service request sent by PATH for internal purposes. + // Parallel: PATH sent the service request for higher redundancy REQUEST_TYPE_PARALLEL = 3; - // Fallback: Service request sent by PATH for internal purposes. + // Fallback: PATH sent the service request for higher redundancy + // TODO_TECHDEBT(@adshmh): Use this when fallback endpoints are part of the gateway context. + // DUe to the current structure of the code, there is not clean way to apply this type to the RPC observations.. REQUEST_TYPE_FALLBACK = 4; } diff --git a/protocol/shannon/context.go b/protocol/shannon/context.go index 31cbe2386..c89b1269e 100644 --- a/protocol/shannon/context.go +++ b/protocol/shannon/context.go @@ -93,6 +93,7 @@ type requestContext struct { httpClient *httpClientWithDebugMetrics // fallbackEndpoints is used to retrieve a fallback endpoint by an endpoint address. + // TODO_TECHDEBT(@adshmh): This should be part of the gateway context and not the protocol specific request context. fallbackEndpoints map[protocol.EndpointAddr]endpoint } @@ -174,6 +175,9 @@ func (rc *requestContext) executeRelayRequest(payload protocol.Payload) (protoco selectedEndpoint := rc.getSelectedEndpoint() rc.hydratedLogger("executeRelayRequest") + // TODO_TECHDEBT(@adshmh): This should be handled by the gateway context. + // Fallback logic is not "shannon specific". It should apply to any protocol we ever support. + // The separation of concerns leaked throughout development and must be updated. switch { // ** Priority 1: Check Endpoint type ** // Direct fallback endpoint From 3cdf9178dc0ffe211c2a8226aca5efe65d5216ce Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Mon, 25 Aug 2025 11:23:18 -0700 Subject: [PATCH 6/6] Remove minor techdebt item --- observation/gateway.pb.go | 21 +++++++++------------ protocol/shannon/context.go | 4 +--- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/observation/gateway.pb.go b/observation/gateway.pb.go index 12775b28d..65fe0ab4e 100644 --- a/observation/gateway.pb.go +++ b/observation/gateway.pb.go @@ -10,13 +10,12 @@ package observation import ( - reflect "reflect" - sync "sync" - unsafe "unsafe" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" ) const ( @@ -27,22 +26,20 @@ const ( ) // RequestType captures the origin of the request. -// As of PR #72, it is one of: -// 1. Organic: a real user sent a service request to a PATH instance -// 2. Synthetic: internal infrastructure generated the service request for simulation and data purposes. -// // Next free index: 5 type RequestType int32 const ( RequestType_REQUEST_TYPE_UNSPECIFIED RequestType = 0 - // Organic: Service request sent by a user. + // Organic: A real user sent a service request to a PATH instance RequestType_REQUEST_TYPE_ORGANIC RequestType = 1 - // Synthetic: Service request sent by the endpoint hydrator: see gateway/hydrator.go. + // Synthetic: Internal infrastructure generated the service request for simulation and data purposes. RequestType_REQUEST_TYPE_SYNTHETIC RequestType = 2 - // Parallel: Service request sent by PATH for internal purposes. + // Parallel: PATH sent the service request for higher redundancy RequestType_REQUEST_TYPE_PARALLEL RequestType = 3 - // Fallback: Service request sent by PATH for internal purposes. + // Fallback: PATH sent the service request for higher redundancy + // TODO_TECHDEBT(@adshmh): Use this when fallback endpoints are part of the gateway context. + // DUe to the current structure of the code, there is not clean way to apply this type to the RPC observations.. RequestType_REQUEST_TYPE_FALLBACK RequestType = 4 ) diff --git a/protocol/shannon/context.go b/protocol/shannon/context.go index c89b1269e..a32addf0c 100644 --- a/protocol/shannon/context.go +++ b/protocol/shannon/context.go @@ -18,7 +18,6 @@ import ( sdk "github.com/pokt-network/shannon-sdk" "github.com/buildwithgrove/path/gateway" - "github.com/buildwithgrove/path/observation" protocolobservations "github.com/buildwithgrove/path/observation/protocol" "github.com/buildwithgrove/path/protocol" ) @@ -185,8 +184,7 @@ func (rc *requestContext) executeRelayRequest(payload protocol.Payload) (protoco // - Used when endpoint is explicitly configured as a fallback endpoint case selectedEndpoint.IsFallback(): rc.logger.Debug().Msg("Executing fallback relay") - // Update request type to PARALLEL for parallel requests - rc.gatewayObservations.RequestType = observation.RequestType_REQUEST_TYPE_PARALLEL + // TODO_TECHDEBT(@adshmh): Find a place to ensure fallback RPC type is set. return rc.sendFallbackRelay(selectedEndpoint, payload)