@Override protected void decode(ChannelHandlerContext ctx, RESPONSE msg, List<Object> out) throws Exception { if (currentDecodingState == DecodingState.INITIAL) { currentRequest = sentRequestQueue.poll(); currentDecodingState = DecodingState.STARTED; if (currentRequest != null) { Long st = sentRequestTimings.poll(); if (st != null) { currentOpTime = System.nanoTime() - st; } else { currentOpTime = -1; } } if (traceEnabled) { LOGGER.trace("{}Started decoding of {}", logIdent(ctx, endpoint), currentRequest); } } try { CouchbaseResponse response = decodeResponse(ctx, msg); if (response != null) { publishResponse(response, currentRequest.observable()); if (currentDecodingState == DecodingState.FINISHED) { if (currentRequest != null && currentOpTime >= 0 && env() != null && env().networkLatencyMetricsCollector().isEnabled()) { NetworkLatencyMetricsIdentifier identifier = new NetworkLatencyMetricsIdentifier( remoteHostname, serviceType().toString(), currentRequest.getClass().getSimpleName(), response.status().toString()); env().networkLatencyMetricsCollector().record(identifier, currentOpTime); } } } } catch (CouchbaseException e) { currentRequest.observable().onError(e); } catch (Exception e) { currentRequest.observable().onError(new CouchbaseException(e)); } if (currentDecodingState == DecodingState.FINISHED) { if (traceEnabled) { LOGGER.trace("{}Finished decoding of {}", logIdent(ctx, endpoint), currentRequest); } currentRequest = null; currentDecodingState = DecodingState.INITIAL; } }
/** * Override to customize the behavior when a keep alive has been responded to. * * <p>The default behavior is to log the event and the response status at trace level. * * @param ctx the channel context. * @param keepAliveResponse the keep alive request that was sent when keep alive was triggered */ protected void onKeepAliveResponse( ChannelHandlerContext ctx, CouchbaseResponse keepAliveResponse) { if (traceEnabled) { LOGGER.trace( logIdent(ctx, endpoint) + "keepAlive was answered, status " + keepAliveResponse.status()); } }
/** * Publishes a response with the attached observable. * * @param response the response to publish. * @param observable pushing into the event sink. */ protected void publishResponse( final CouchbaseResponse response, final Subject<CouchbaseResponse, CouchbaseResponse> observable) { if (response.status() != ResponseStatus.RETRY && observable != null) { final Scheduler.Worker worker = env().scheduler().createWorker(); worker.schedule( new Action0() { @Override public void call() { try { observable.onNext(response); observable.onCompleted(); } catch (Exception ex) { LOGGER.warn("Caught exception while onNext on observable", ex); observable.onError(ex); } finally { worker.unsubscribe(); } } }); } else { responseBuffer.publishEvent(ResponseHandler.RESPONSE_TRANSLATOR, response, observable); } }