private void send(Response response, String typeUrl) { String nonce = Long.toString(streamNonce.getAndIncrement()); DiscoveryResponse discoveryResponse = DiscoveryResponse.newBuilder() .setVersionInfo(response.version()) .addAllResources(response.resources().stream().map(Any::pack).collect(Collectors.toList())) .setTypeUrl(typeUrl) .setNonce(nonce) .build(); LOGGER.info("[{}] response {} with nonce {} version {}", streamId, typeUrl, nonce, response.version()); callbacks.forEach(cb -> cb.onStreamResponse(streamId, response.request(), discoveryResponse)); // Store the latest response *before* we send the response. This ensures that by the time the request // is processed the map is guaranteed to be updated. Doing it afterwards leads to a race conditions // which may see the incoming request arrive before the map is updated, failing the nonce check erroneously. latestResponse.put(typeUrl, discoveryResponse); try { responseObserver.onNext(discoveryResponse); } catch (StatusRuntimeException e) { if (!Status.CANCELLED.getCode().equals(e.getStatus().getCode())) { throw e; } } } }