( ctx context.Context, method string, attempt func(common.Upstream) error, )
| 207 | } |
| 208 | |
| 209 | func (qe *EvmQueryExecutor) tryQueryUpstreams( |
| 210 | ctx context.Context, |
| 211 | method string, |
| 212 | attempt func(common.Upstream) error, |
| 213 | ) (handled bool, err error) { |
| 214 | var upstreams []common.Upstream |
| 215 | if qe.network.policyEngine != nil { |
| 216 | // Query-shim requests aren't bound to a single finality bucket |
| 217 | // (a range covers both finalized and unfinalized blocks), so |
| 218 | // route them through the wildcard slot. Networks configured |
| 219 | // with `EvalPerFinality: true` should set explicit per-method |
| 220 | // policies if they want finality-aware routing for queries. |
| 221 | upstreams = qe.network.policyEngine.GetOrdered(qe.network.Id(), method, "*") |
| 222 | } |
| 223 | if len(upstreams) == 0 { |
| 224 | // Cold-start fallback: engine hasn't published a cache yet. |
| 225 | for _, u := range qe.network.upstreamsRegistry.GetNetworkUpstreams(ctx, qe.network.Id()) { |
| 226 | upstreams = append(upstreams, u) |
| 227 | } |
| 228 | } |
| 229 | if len(upstreams) == 0 { |
| 230 | qe.logger.Debug().Str("method", method).Msgf("no upstreams available for query method") |
| 231 | return false, nil |
| 232 | } |
| 233 | |
| 234 | for _, ups := range upstreams { |
| 235 | if !qe.supportsQueryMethods(ups) { |
| 236 | qe.logger.Trace().Str("upstreamId", ups.Id()).Str("method", method).Msgf("upstream does not support query streaming, skipping") |
| 237 | continue |
| 238 | } |
| 239 | |
| 240 | qe.logger.Debug().Str("upstreamId", ups.Id()).Str("method", method).Msgf("attempting native query pipe-through to upstream") |
| 241 | |
| 242 | err := attempt(ups) |
| 243 | if err == nil { |
| 244 | qe.logger.Debug().Str("upstreamId", ups.Id()).Str("method", method).Msgf("native query pipe-through succeeded") |
| 245 | return true, nil |
| 246 | } |
| 247 | if qe.canRetryQueryStream(err) { |
| 248 | qe.logger.Debug().Err(err).Str("upstreamId", ups.Id()).Str("method", method).Msgf("query pipe-through failed before page emission, trying next upstream") |
| 249 | continue |
| 250 | } |
| 251 | qe.logger.Debug().Err(err).Str("upstreamId", ups.Id()).Str("method", method).Msgf("query pipe-through failed after page emission, cannot retry") |
| 252 | return true, err |
| 253 | } |
| 254 | |
| 255 | return false, nil |
| 256 | } |
| 257 | |
| 258 | func (qe *EvmQueryExecutor) canRetryQueryStream(err error) bool { |
| 259 | if err == nil { |
no test coverage detected