@Override public void onResponseComplete(Exception exception) { long responseCompleteStartTime = System.currentTimeMillis(); try { if (responseCompleteCalled.compareAndSet(false, true)) { logger.trace("Finished responding to current request on channel {}", ctx.channel()); nettyMetrics.requestCompletionRate.mark(); if (exception == null) { if (!maybeWriteResponseMetadata(responseMetadata, responseMetadataWriteListener)) { // There were other writes. Let ChunkedWriteHandler finish if it has been kicked off. chunkedWriteHandler.resumeTransfer(); } } else { log(exception); if (request != null) { request.getMetricsTracker().markFailure(); } // need to set writeFuture as failed in case writes have started or chunks have been // queued. if (!writeFuture.isDone()) { writeFuture.setFailure(exception); } if (!maybeSendErrorResponse(exception)) { completeRequest(true); } } } else if (exception != null) { // this is probably an attempt to force close the channel *after* the response is already // complete. log(exception); if (!writeFuture.isDone()) { writeFuture.setFailure(exception); } completeRequest(true); } long responseFinishProcessingTime = System.currentTimeMillis() - responseCompleteStartTime; nettyMetrics.responseFinishProcessingTimeInMs.update(responseFinishProcessingTime); if (request != null) { request .getMetricsTracker() .nioMetricsTracker .addToResponseProcessingTime(responseFinishProcessingTime); } } catch (Exception e) { logger.error("Swallowing exception encountered during onResponseComplete tasks", e); nettyMetrics.responseCompleteTasksError.inc(); if (!writeFuture.isDone()) { writeFuture.setFailure(exception); } completeRequest(true); } }
@Override public Future<Long> write(ByteBuffer src, Callback<Long> callback) { long writeProcessingStartTime = System.currentTimeMillis(); if (!responseMetadataWritten.get()) { maybeWriteResponseMetadata(responseMetadata, responseMetadataWriteListener); } Chunk chunk = new Chunk(src, callback); chunksToWriteCount.incrementAndGet(); chunksToWrite.add(chunk); if (!isOpen()) { // the isOpen() check is not before addition to the queue because chunks need to be // acknowledged in the order // they were received. If we don't add it to the queue and clean up, chunks may be // acknowledged out of order. logger.debug("Scheduling a chunk cleanup on channel {}", ctx.channel()); writeFuture.addListener(cleanupCallback); } else { chunkedWriteHandler.resumeTransfer(); } long writeProcessingTime = System.currentTimeMillis() - writeProcessingStartTime; nettyMetrics.writeProcessingTimeInMs.update(writeProcessingTime); if (request != null) { request .getMetricsTracker() .nioMetricsTracker .addToResponseProcessingTime(writeProcessingTime); } return chunk.future; }
/** Closes the request associated with this NettyResponseChannel. */ private void closeRequest() { if (request != null && request.isOpen()) { request.getMetricsTracker().nioMetricsTracker.markRequestCompleted(); request.close(); } }