use of com.couchbase.client.core.cnc.RequestSpan in project couchbase-jvm-clients by couchbase.
the class Observe method viaMutationToken.
private static Flux<ObserveItem> viaMutationToken(final int bucketReplicas, final ObserveContext ctx, final RequestSpan parent) {
if (!ctx.mutationToken().isPresent()) {
throw new IllegalStateException("MutationToken is not present, this is a bug!");
}
Duration timeout = ctx.timeout();
RetryStrategy retryStrategy = ctx.retryStrategy();
MutationToken mutationToken = ctx.mutationToken().get();
String id = ctx.key();
List<ObserveViaSeqnoRequest> requests = new ArrayList<>();
if (ctx.persistTo() != ObservePersistTo.NONE) {
final RequestSpan span = ctx.environment().requestTracer().requestSpan(TracingIdentifiers.SPAN_REQUEST_KV_OBSERVE, parent);
requests.add(new ObserveViaSeqnoRequest(timeout, ctx, ctx.collectionIdentifier(), retryStrategy, 0, true, mutationToken.partitionUUID(), id, span));
}
if (ctx.persistTo().touchesReplica() || ctx.replicateTo().touchesReplica()) {
for (short i = 1; i <= bucketReplicas; i++) {
final RequestSpan span = ctx.environment().requestTracer().requestSpan(TracingIdentifiers.SPAN_REQUEST_KV_OBSERVE, parent);
requests.add(new ObserveViaSeqnoRequest(timeout, ctx, ctx.collectionIdentifier(), retryStrategy, i, false, mutationToken.partitionUUID(), id, span));
}
}
return Flux.fromIterable(requests).flatMap(request -> {
ctx.core().send(request);
return Reactor.wrap(request, request.response(), true).onErrorResume(t -> Mono.empty()).doFinally(signalType -> request.context().logicallyComplete());
}).map(response -> ObserveItem.fromMutationToken(mutationToken, response));
}
use of com.couchbase.client.core.cnc.RequestSpan in project couchbase-jvm-clients by couchbase.
the class Observe method poll.
public static Mono<Void> poll(final ObserveContext ctx) {
if (ctx.persistTo() == ObservePersistTo.NONE && ctx.replicateTo() == ObserveReplicateTo.NONE) {
return Mono.empty();
}
if (!ctx.environment().ioConfig().mutationTokensEnabled() || !ctx.mutationToken().isPresent()) {
return Mono.error(new FeatureNotAvailableException("To use PersistTo and/or ReplicateTo, mutation tokens must " + "be enabled on the IO configuration"));
}
final RequestSpan parentSpan = ctx.environment().requestTracer().requestSpan("observe", ctx.parentSpan());
Flux<ObserveItem> observed = Flux.defer(() -> {
BucketConfig config = ctx.core().clusterConfig().bucketConfig(ctx.collectionIdentifier().bucket());
return Flux.just(validateReplicas(config, ctx.persistTo(), ctx.replicateTo()));
}).flatMap(replicas -> viaMutationToken(replicas, ctx, parentSpan));
return maybeRetry(observed, ctx).timeout(ctx.timeout(), ctx.environment().scheduler()).doFinally(t -> parentSpan.end());
}
use of com.couchbase.client.core.cnc.RequestSpan in project couchbase-jvm-clients by couchbase.
the class QueryRequest method toPrepareRequest.
/**
* Returns a new request that creates a prepared statement using this request as a template.
*/
@Stability.Internal
public QueryRequest toPrepareRequest(boolean autoExecute, RequestTracer requestTracer) {
String newStatement = "PREPARE " + statement();
byte[] newQuery = transformQuery(query -> {
query.put("statement", newStatement);
if (autoExecute) {
query.put("auto_execute", true);
} else {
// Keep only the fields required for preparation.
// Discard things like arguments, scan vectors, etc.
query.retain("statement", "timeout", "client_context_id", "query_context");
}
});
RequestSpan newSpan = requestTracer.requestSpan("prepare", requestSpan());
boolean newIdempotent = !autoExecute || idempotent();
return copy(newStatement, newQuery, newIdempotent, newSpan);
}
use of com.couchbase.client.core.cnc.RequestSpan in project couchbase-jvm-clients by couchbase.
the class KeyValueMessageHandler method write.
@Override
@SuppressWarnings({ "unchecked" })
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) {
if (msg instanceof KeyValueRequest) {
KeyValueRequest<Response> request = (KeyValueRequest<Response>) msg;
int opaque = request.opaque();
writtenRequests.put(opaque, request);
try {
ctx.write(request.encode(ctx.alloc(), opaque, channelContext), promise);
writtenRequestDispatchTimings.put(opaque, (Long) System.nanoTime());
if (request.requestSpan() != null) {
RequestTracer tracer = endpointContext.environment().requestTracer();
RequestSpan dispatchSpan = tracer.requestSpan(TracingIdentifiers.SPAN_DISPATCH, request.requestSpan());
if (!isInternalTracer) {
setCommonDispatchSpanAttributes(dispatchSpan, ctx.channel().attr(ChannelAttributes.CHANNEL_ID_KEY).get(), ioContext.localHostname(), ioContext.localPort(), endpoint.remoteHostname(), endpoint.remotePort(), null);
setNumericOperationId(dispatchSpan, request.opaque());
setCommonKVSpanAttributes(dispatchSpan, request);
}
writtenRequestDispatchSpans.put(opaque, dispatchSpan);
}
} catch (Throwable err) {
writtenRequests.remove(opaque);
if (err instanceof CollectionNotFoundException) {
if (channelContext.collectionsEnabled()) {
ConfigurationProvider cp = ioContext.core().configurationProvider();
if (cp.collectionRefreshInProgress(request.collectionIdentifier())) {
RetryOrchestrator.maybeRetry(ioContext, request, RetryReason.COLLECTION_MAP_REFRESH_IN_PROGRESS);
} else if (cp.config().bucketConfig(request.bucket()) instanceof MemcachedBucketConfig) {
request.fail(FeatureNotAvailableException.collectionsForMemcached());
} else {
handleOutdatedCollection(request, RetryReason.COLLECTION_NOT_FOUND);
}
return;
}
}
request.fail(err);
}
} else {
eventBus.publish(new InvalidRequestDetectedEvent(ioContext, ServiceType.KV, msg));
ctx.channel().close().addListener(f -> eventBus.publish(new ChannelClosedProactivelyEvent(ioContext, ChannelClosedProactivelyEvent.Reason.INVALID_REQUEST_DETECTED)));
}
}
use of com.couchbase.client.core.cnc.RequestSpan 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);
}
}
}
Aggregations