Documentation
¶
Overview ¶
Package heuristic provides lightweight response analysis to detect errors before full JSON parsing, enabling faster retry decisions.
The package implements a tiered analysis approach:
- Tier 1: Structural checks (empty, HTML, non-JSON)
- Tier 2: Protocol-specific success indicators
- Tier 3: Common error pattern detection
This allows the gateway to quickly identify likely-error responses and trigger retries without the latency cost of full JSON parsing.
Index ¶
- func ErrorContainsArchivalPattern(errStr string) bool
- func HasErrorField(prefix []byte) bool
- func IsArchivalRelatedError(pattern string) bool
- func IsCapabilityLimitationError(pattern string) bool
- func IsJSONRPCLikeSuccess(prefix []byte) bool
- func QuickErrorCheck(contentLower []byte) bool
- func ShouldRetry(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, ...) bool
- type AnalysisResult
- func Analyze(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, ...) AnalysisResult
- func AnalyzeQuick(responseBytes []byte, httpStatusCode int) AnalysisResult
- func CheckRequestIDMismatch(responsePrefix []byte, requestID string) *AnalysisResult
- func IndicatorAnalysisToResult(ir IndicatorResult) AnalysisResult
- func ProtocolAnalysis(prefix []byte, fullLength int, rpcType sharedtypes.RPCType, ...) AnalysisResult
- func StructuralAnalysis(responseBytes []byte) AnalysisResult
- type Analyzer
- type AnalyzerConfig
- type ErrorCategory
- type IndicatorResult
- type ResponseAnalyzer
- func (ra *ResponseAnalyzer) Analyze(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, ...) AnalysisResult
- func (ra *ResponseAnalyzer) AnalyzeQuick(responseBytes []byte, httpStatusCode int) AnalysisResult
- func (ra *ResponseAnalyzer) ShouldRetry(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, ...) bool
- type ResponseStructure
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ErrorContainsArchivalPattern ¶
ErrorContainsArchivalPattern checks if an error string contains any archival-related or capability-limitation pattern. This is a fallback for when the structured heuristic AnalysisResult is not available (e.g., protocol-layer errors propagated through the hedge_failed path).
func HasErrorField ¶
HasErrorField checks if the response prefix contains an error field. Works for both JSON-RPC and REST responses.
func IsArchivalRelatedError ¶
IsArchivalRelatedError returns true if the indicator pattern is an archival/pruning error. These errors are expected from non-archival nodes and should NOT trigger domain-level circuit breaking — the domain isn't broken, it just doesn't have historical state. Retrying on a different (archival-capable) supplier is correct, but punishing the domain for a capability mismatch causes death spirals where all domains get locked out.
func IsCapabilityLimitationError ¶
IsCapabilityLimitationError returns true if the pattern indicates a node capability limitation rather than a broken domain. These include archival errors AND other capability mismatches like Tron lite fullnodes that can't serve certain API calls. The request should retry on a different supplier but should NOT circuit-break the domain.
func IsJSONRPCLikeSuccess ¶
IsJSONRPCLikeSuccess provides a quick check for JSON-RPC success. This is a simplified version for callers who just need a boolean.
func QuickErrorCheck ¶
QuickErrorCheck performs a fast check for obvious error indicators. This is a simplified version that only checks the most common patterns. Use this when you need maximum speed and can tolerate some false negatives.
Cost: O(n) single pass Time: ~1-2μs for 512 byte content
func ShouldRetry ¶
func ShouldRetry(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, jsonrpcMethod string) bool
ShouldRetry returns the retry recommendation using the default analyzer.
Types ¶
type AnalysisResult ¶
type AnalysisResult struct {
// ShouldRetry indicates whether the response suggests a retry is warranted.
ShouldRetry bool
// Confidence represents how confident the analysis is (0.0 to 1.0).
// Higher values indicate more certainty that the response is an error.
Confidence float64
// Reason provides a machine-readable classification of why retry is suggested.
Reason string
// Structure contains the structural classification of the response.
Structure ResponseStructure
// Details provides additional human-readable context for debugging.
Details string
// MatchedPattern is the specific error pattern that matched (from Tier 3 indicator analysis).
// Empty for non-indicator results.
MatchedPattern string
}
AnalysisResult contains the outcome of heuristic response analysis.
func Analyze ¶
func Analyze(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, jsonrpcMethod string) AnalysisResult
Analyze performs heuristic analysis using the default analyzer.
func AnalyzeQuick ¶
func AnalyzeQuick(responseBytes []byte, httpStatusCode int) AnalysisResult
AnalyzeQuick performs a fast heuristic check using the default analyzer.
func CheckRequestIDMismatch ¶ added in v1.0.16
func CheckRequestIDMismatch(responsePrefix []byte, requestID string) *AnalysisResult
CheckRequestIDMismatch detects fabricated responses by comparing the response ID to the original request ID. JSON-RPC 2.0 spec requires the response ID to match the request ID. A response with "id":null when the request had a real ID proves the response was fabricated by the supplier's relay miner, not the actual node.
Returns an AnalysisResult if a mismatch is detected, nil otherwise.
func IndicatorAnalysisToResult ¶
func IndicatorAnalysisToResult(ir IndicatorResult) AnalysisResult
IndicatorAnalysisToResult converts an IndicatorResult to an AnalysisResult.
func ProtocolAnalysis ¶
func ProtocolAnalysis(prefix []byte, fullLength int, rpcType sharedtypes.RPCType, jsonrpcMethod string) AnalysisResult
ProtocolAnalysis performs Tier 2 protocol-specific analysis. It checks whether the response contains expected success indicators for the given RPC type.
Parameters:
- prefix: First N bytes of the response (typically 512)
- fullLength: Total length of the response
- rpcType: The protocol type for specific validation
Cost: O(n) where n is prefix length Time: ~1-3μs for 512 byte prefix
func StructuralAnalysis ¶
func StructuralAnalysis(responseBytes []byte) AnalysisResult
StructuralAnalysis performs Tier 1 analysis and returns a result. This is the entry point for structural-only analysis.
type Analyzer ¶
type Analyzer interface {
// Analyze performs heuristic analysis on a response to determine if it's likely an error.
// Parameters:
// - responseBytes: The raw response payload
// - httpStatusCode: The HTTP status code from the endpoint
// - rpcType: The RPC type for protocol-specific analysis
// - jsonrpcMethod: The JSON-RPC method name for method-aware checks (e.g., "eth_blockNumber").
// Empty string means unknown/non-JSON-RPC — method-aware checks are skipped.
//
// Returns an AnalysisResult with retry recommendation and confidence level.
Analyze(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, jsonrpcMethod string) AnalysisResult
}
Analyzer defines the interface for heuristic response analysis.
type AnalyzerConfig ¶
type AnalyzerConfig struct {
// MaxPrefixBytes is the maximum number of bytes to inspect for heuristics.
// Default: 512 bytes. Larger values may catch more edge cases but cost more CPU.
MaxPrefixBytes int
// ConfidenceThreshold is the minimum confidence level to suggest retry.
// Default: 0.5. Set higher for fewer false positives, lower for more aggressive retries.
ConfidenceThreshold float64
// EnableTier3 controls whether error indicator pattern matching is performed.
// Default: true. Disable if you want only structural and protocol checks.
EnableTier3 bool
}
AnalyzerConfig holds configuration options for the response analyzer.
func DefaultConfig ¶
func DefaultConfig() AnalyzerConfig
DefaultConfig returns the default analyzer configuration.
type ErrorCategory ¶
type ErrorCategory int
ErrorCategory represents the type of error detected.
const ( // CategoryNone indicates no error pattern was detected. CategoryNone ErrorCategory = iota // CategoryHTTPError indicates an HTTP-level error message. CategoryHTTPError // CategoryConnectionError indicates a connection/network error. CategoryConnectionError // CategoryRateLimit indicates rate limiting. CategoryRateLimit // CategoryAuthError indicates authentication/authorization error. CategoryAuthError // CategoryServiceError indicates a service-level error. CategoryServiceError // CategoryBlockchainError indicates a blockchain-specific error. CategoryBlockchainError // CategoryProtocolError indicates a protocol-level error. CategoryProtocolError )
func (ErrorCategory) String ¶
func (ec ErrorCategory) String() string
String returns a human-readable representation of the ErrorCategory.
type IndicatorResult ¶
type IndicatorResult struct {
// Found indicates whether an error pattern was detected.
Found bool
// Category is the type of error detected.
Category ErrorCategory
// Pattern is the specific pattern that matched.
Pattern string
// Confidence is how confident we are this indicates an error.
Confidence float64
}
IndicatorResult contains the result of error indicator analysis.
func IndicatorAnalysis ¶
func IndicatorAnalysis(content []byte, alreadyLowercased bool) IndicatorResult
IndicatorAnalysis performs Tier 3 error indicator pattern matching. It searches for known error patterns in the response content.
Parameters:
- content: Response content to analyze (should be lowercased for efficiency)
- alreadyLowercased: Set to true if content is already lowercase
Cost: O(n*m) where n is content length and m is number of patterns Time: ~3-10μs for 512 byte content
type ResponseAnalyzer ¶
type ResponseAnalyzer struct {
// contains filtered or unexported fields
}
ResponseAnalyzer implements the Analyzer interface using a tiered approach. It combines structural, protocol-specific, and indicator-based analysis to determine if a response is likely an error.
func NewAnalyzer ¶
func NewAnalyzer(config AnalyzerConfig) *ResponseAnalyzer
NewAnalyzer creates a new ResponseAnalyzer with the given configuration.
func NewDefaultAnalyzer ¶
func NewDefaultAnalyzer() *ResponseAnalyzer
NewDefaultAnalyzer creates a new ResponseAnalyzer with default configuration.
func (*ResponseAnalyzer) Analyze ¶
func (ra *ResponseAnalyzer) Analyze(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, jsonrpcMethod string) AnalysisResult
Analyze performs comprehensive heuristic analysis on a response. It uses a tiered approach, short-circuiting as soon as a definitive result is found:
- HTTP Status Check (free) - 4xx/5xx always indicates error
- Tier 1: Structural Analysis - Empty, HTML, non-JSON
- Tier 2: Protocol Analysis - JSON-RPC result/error fields
- Tier 3: Indicator Analysis - Error pattern matching
Returns an AnalysisResult with retry recommendation and confidence.
func (*ResponseAnalyzer) AnalyzeQuick ¶
func (ra *ResponseAnalyzer) AnalyzeQuick(responseBytes []byte, httpStatusCode int) AnalysisResult
AnalyzeQuick performs a fast heuristic check with minimal processing. Use this when you need maximum speed and can accept lower accuracy.
This performs:
- HTTP status check
- Empty/first-byte check
- Quick error pattern scan
Cost: O(n) single pass on prefix Time: ~2-5μs
func (*ResponseAnalyzer) ShouldRetry ¶
func (ra *ResponseAnalyzer) ShouldRetry(responseBytes []byte, httpStatusCode int, rpcType sharedtypes.RPCType, jsonrpcMethod string) bool
ShouldRetry is a convenience method that returns just the retry decision.
type ResponseStructure ¶
type ResponseStructure int
ResponseStructure classifies the structural type of a response.
const ( // StructureValid indicates the response has valid JSON structure. StructureValid ResponseStructure = iota // StructureEmpty indicates an empty response (0 bytes). StructureEmpty // StructureHTML indicates the response is HTML (likely an error page). StructureHTML // StructureXML indicates the response is XML (unexpected for JSON APIs). StructureXML // StructureNonJSON indicates the response is plain text (not JSON). StructureNonJSON // StructureMalformed indicates the response starts like JSON but appears malformed. StructureMalformed )
func ClassifyStructure ¶
func ClassifyStructure(responseBytes []byte) ResponseStructure
ClassifyStructure performs Tier 1 structural analysis on the response. It determines what type of content the response contains based on its structure, without parsing the full content.
Cost: O(1) - only inspects first few bytes Time: < 1μs typically
func (ResponseStructure) String ¶
func (rs ResponseStructure) String() string
String returns a human-readable representation of the ResponseStructure.