use of com.couchbase.client.core.retry.RetryReason in project couchbase-jvm-clients by couchbase.
the class ChunkedMessageHandler method maybeCompleteResponseWithFailure.
private void maybeCompleteResponseWithFailure() {
if (!currentRequest.completed()) {
final CouchbaseException cause = chunkResponseParser.decodingFailure().orElseGet(() -> chunkResponseParser.error().orElseGet(() -> new CouchbaseException("Request failed, but no more information available")));
Optional<RetryReason> qualifies = qualifiesForRetry(cause);
if (qualifies.isPresent()) {
RetryOrchestrator.maybeRetry(ioContext, currentRequest, qualifies.get());
} else {
currentRequest.fail(cause);
}
} else {
ioContext.environment().orphanReporter().report(currentRequest);
}
}
use of com.couchbase.client.core.retry.RetryReason in project couchbase-jvm-clients by couchbase.
the class KeyValueMessageHandler method decode.
/**
* Main method to start dispatching the decode.
*
* @param ctx the channel handler context from netty.
* @param response the response to decode and handle.
*/
private void decode(final ChannelHandlerContext ctx, final ByteBuf response) {
int opaque = MemcacheProtocol.opaque(response);
KeyValueRequest<Response> request = writtenRequests.remove(opaque);
if (request == null) {
handleUnknownResponseReceived(ctx, response);
return;
}
long serverTime = MemcacheProtocol.parseServerDurationFromResponse(response);
request.context().serverLatency(serverTime);
long start = writtenRequestDispatchTimings.remove(opaque);
request.context().dispatchLatency(System.nanoTime() - start);
RequestSpan dispatchSpan = writtenRequestDispatchSpans.remove(opaque);
if (dispatchSpan != null) {
if (!isInternalTracer) {
TracingUtils.setServerDurationAttribute(dispatchSpan, serverTime);
}
dispatchSpan.end();
}
short statusCode = MemcacheProtocol.status(response);
ResponseStatus status = MemcacheProtocol.decodeStatus(statusCode);
ErrorMap.ErrorCode errorCode = status != ResponseStatus.SUCCESS ? decodeErrorCode(statusCode) : null;
if (errorCode != null) {
request.errorCode(errorCode);
}
boolean errorUnknown = false;
if (status == ResponseStatus.UNKNOWN) {
errorUnknown = true;
if (errorCode != null) {
ioContext.environment().eventBus().publish(new KeyValueErrorMapCodeHandledEvent(ioContext, errorCode));
status = handleErrorCode(ctx, errorCode);
}
ioContext.environment().eventBus().publish(new UnknownResponseStatusReceivedEvent(ioContext, statusCode));
}
if (status == ResponseStatus.NOT_MY_VBUCKET) {
handleNotMyVbucket(request, response);
} else if (status == ResponseStatus.UNKNOWN_COLLECTION) {
handleOutdatedCollection(request, RetryReason.KV_COLLECTION_OUTDATED);
} else if (errorUnknown && errorMapIndicatesRetry(errorCode)) {
RetryOrchestrator.maybeRetry(ioContext, request, RetryReason.KV_ERROR_MAP_INDICATED);
} else if (statusIndicatesInvalidChannel(status)) {
closeChannelWithReason(ioContext, ctx, ChannelClosedProactivelyEvent.Reason.KV_RESPONSE_CONTAINED_CLOSE_INDICATION);
} else {
RetryReason retryReason = statusCodeIndicatesRetry(status, request);
if (retryReason == null) {
if (!request.completed()) {
decodeAndComplete(request, response);
} else {
ioContext.environment().orphanReporter().report(request);
}
} else {
RetryOrchestrator.maybeRetry(ioContext, request, retryReason);
}
}
}
use of com.couchbase.client.core.retry.RetryReason in project couchbase-jvm-clients by couchbase.
the class BaseEndpoint method send.
@Override
public <R extends Request<? extends Response>> void send(final R request) {
if (request.timeoutElapsed()) {
request.cancel(CancellationReason.TIMEOUT);
}
if (request.completed()) {
return;
}
final EndpointContext ctx = endpointContext.get();
if (canWrite()) {
request.context().lastDispatchedFrom(ctx.localSocket().orElse(null)).lastDispatchedTo(ctx.remoteSocket()).lastChannelId(ctx.channelId().orElse(null));
if (!pipelined) {
outstandingRequests.incrementAndGet();
}
if (circuitBreakerEnabled) {
circuitBreaker.track();
request.response().whenComplete((response, throwable) -> {
if (circuitBreakerCallback.apply(response, throwable)) {
circuitBreaker.markSuccess();
} else {
circuitBreaker.markFailure();
}
});
}
channel.writeAndFlush(request).addListener(f -> {
if (!f.isSuccess()) {
EndpointContext context = endpointContext.get();
Event.Severity severity = disconnect.get() ? Event.Severity.DEBUG : Event.Severity.WARN;
context.environment().eventBus().publish(new EndpointWriteFailedEvent(severity, context, f.cause()));
RetryOrchestrator.maybeRetry(context, request, RetryReason.ENDPOINT_NOT_WRITABLE);
}
});
} else {
RetryReason retryReason = circuitBreaker.allowsRequest() ? RetryReason.ENDPOINT_NOT_WRITABLE : RetryReason.ENDPOINT_CIRCUIT_OPEN;
RetryOrchestrator.maybeRetry(endpointContext.get(), request, retryReason);
}
}
use of com.couchbase.client.core.retry.RetryReason in project couchbase-jvm-clients by couchbase.
the class KeyValueMessageHandlerTest method retriesCertainResponseStatusCodes.
/**
* Certain status codes are identified that should be passed to the retry orchestrator rathen than complete
* the response right away.
*/
@Test
void retriesCertainResponseStatusCodes() {
List<MemcacheProtocol.Status> retryOnThese = Arrays.asList(MemcacheProtocol.Status.LOCKED, MemcacheProtocol.Status.TEMPORARY_FAILURE, MemcacheProtocol.Status.SYNC_WRITE_IN_PROGRESS, MemcacheProtocol.Status.SYNC_WRITE_RE_COMMIT_IN_PROGRESS);
List<RetryReason> retryReasons = Arrays.asList(RetryReason.KV_LOCKED, RetryReason.KV_TEMPORARY_FAILURE, RetryReason.KV_SYNC_WRITE_IN_PROGRESS, RetryReason.KV_SYNC_WRITE_RE_COMMIT_IN_PROGRESS);
int i = 0;
for (MemcacheProtocol.Status status : retryOnThese) {
EmbeddedChannel channel = new EmbeddedChannel(new KeyValueMessageHandler(null, CTX, Optional.of(BUCKET)));
try {
GetRequest request = new GetRequest("key", Duration.ofSeconds(1), CTX, CID, FailFastRetryStrategy.INSTANCE, null);
channel.writeOutbound(request);
ByteBuf getResponse = MemcacheProtocol.response(channel.alloc(), MemcacheProtocol.Opcode.GET, (byte) 0, status.status(), request.opaque(), 0, Unpooled.EMPTY_BUFFER, Unpooled.EMPTY_BUFFER, Unpooled.EMPTY_BUFFER);
channel.writeInbound(getResponse);
assertEquals(CancellationReason.noMoreRetries(retryReasons.get(i)), request.cancellationReason());
assertEquals(0, getResponse.refCnt());
i++;
} finally {
channel.finishAndReleaseAll();
}
}
}
Aggregations