private void maybeRetry(List<FastHit> skippedHits, Result result, String summaryClass) throws InterruptedException {
        int numSkipped = skippedHits.size();
        var query = result.getQuery();
        double absoluteRetryLimit = query.properties().getInteger(Dispatcher.docsumRetryLimit, 10);
        double retryLimitFactor = query.properties().getDouble(Dispatcher.docsumRetryFactor, 0.5);
        double retryLimit = Math.min(absoluteRetryLimit, retryLimitFactor * numHitsToFill + 1);
        if (numSkipped < retryLimit) {
            result.getQuery().trace(false, 1, "Retry summary fetching for " + numSkipped + " empty docsums (of " + numHitsToFill + " hits)");
            ListMap<Integer, FastHit> retryMap = new ListMap<>();
            for (Integer nodeId : resourcePool.knownNodeIds()) {
                for (var hit : skippedHits) {
                    if (hit.getDistributionKey() != nodeId) {
                        retryMap.put(nodeId, hit);
                    }
                }
            }
            // no retry if there is only one node
            if (retryMap.size() > 0) {
                if (shouldLogRetry()) {
                    log.log(Level.WARNING, "Retry docsum fetch for " + numSkipped + " hits (" + numOkFilledHits + " ok hits)");
                }
                summaryNeedsQuery = true;
                sendFillRequestByNode(result, summaryClass, retryMap);
                while (outstandingResponses > 0 && numOkFilledHits < numHitsToFill) {
                    var responseAndHits = getNextResponse(query.getTimeLeft());
                    if (responseAndHits == null) {
                        if (shouldLogRetryTimeout()) {
                            log.log(Level.WARNING, "Timed out waiting for summary data. " + outstandingResponses + " responses outstanding.");
                        }
                        break;
                    }
                    processOneResponse(result, responseAndHits, summaryClass, true);
                    outstandingResponses--;
                }
                skippedHits.removeIf(hit -> !partialSummaryHandler.needFill(hit));
            }
        } else {
            result.getQuery().trace(false, 1, "Summary fetching got " + numSkipped + " empty docsums (of " + numHitsToFill + " hits), no retry");
            if (shouldLogNoRetry()) {
                log.log(Level.WARNING, "Docsum fetch failed for " + numSkipped + " hits (" + numOkFilledHits + " ok hits), no retry");
            }
        }
    }
Send a docsums request to a node. Responses will be added to the given receiver.
container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcProtobufFillInvoker.java