All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.couchbase.client.java.bucket.api.Get Maven / Gradle / Ivy

There is a newer version: 3.7.7
Show newest version
/*
 * Copyright (c) 2018 Couchbase, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.couchbase.client.java.bucket.api;

import com.couchbase.client.core.ClusterFacade;
import com.couchbase.client.core.CouchbaseException;
import com.couchbase.client.core.annotations.InterfaceAudience;
import com.couchbase.client.core.annotations.InterfaceStability;
import com.couchbase.client.core.message.kv.GetRequest;
import com.couchbase.client.core.message.kv.GetResponse;
import com.couchbase.client.core.tracing.ThresholdLogReporter;
import com.couchbase.client.core.tracing.ThresholdLogSpan;
import com.couchbase.client.deps.io.netty.buffer.ByteBuf;
import com.couchbase.client.java.document.Document;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.error.CouchbaseOutOfMemoryException;
import com.couchbase.client.java.error.TemporaryFailureException;
import com.couchbase.client.java.error.TemporaryLockFailureException;
import com.couchbase.client.java.transcoder.Transcoder;
import io.opentracing.Scope;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Func0;
import rx.functions.Func1;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.couchbase.client.java.bucket.api.Utils.addDetails;
import static com.couchbase.client.java.bucket.api.Utils.addRequestSpan;
import static com.couchbase.client.java.bucket.api.Utils.applyTimeout;
import static com.couchbase.client.java.util.OnSubscribeDeferAndWatch.deferAndWatch;

/**
 * Contains the logic to execute and handle get requests.
 *
 * @author Michael Nitschinger
 * @since 2.6.0
 */
@InterfaceAudience.Private
@InterfaceStability.Uncommitted
public class Get {

    public static > Observable get(final String id, final Class target,
        final CouchbaseEnvironment environment, final String bucket, final ClusterFacade core,
        final Map, Transcoder> transcoders,
        final long timeout, final TimeUnit timeUnit) {
        return Observable.defer(new Func0>() {
            @Override
            public Observable call() {
                final GetRequest request = new GetRequest(id, bucket);
                addRequestSpan(environment, request, "get");
                return applyTimeout(deferAndWatch(new Func1>() {
                        @Override
                        public Observable call(Subscriber s) {
                            request.subscriber(s);
                            return core.send(request);
                        }
                    }).filter(new GetFilter(environment))
                        .map(new GetMap(environment, transcoders, target, id)),
                request, environment, timeout, timeUnit);
            }
        });
    }

    public static > Observable getAndLock(final String id, final Class target,
        final CouchbaseEnvironment environment, final String bucket, final ClusterFacade core,
        final Map, Transcoder> transcoders, final int lockTime,
        final long timeout, final TimeUnit timeUnit) {
        return Observable.defer(new Func0>() {
            @Override
            public Observable call() {
                final GetRequest request = new GetRequest(id, bucket, true, false, lockTime);
                addRequestSpan(environment, request, "get_and_lock");
                return applyTimeout(deferAndWatch(new Func1>() {
                        @Override
                        public Observable call(Subscriber s) {
                            request.subscriber(s);
                            return core.send(request);
                        }
                    }).filter(new GetAndLockFilter(environment))
                        .map(new GetMap(environment, transcoders, target, id)),
                request, environment, timeout, timeUnit);
            }
        });
    }

    public static > Observable getAndTouch(final String id, final Class target,
        final CouchbaseEnvironment environment, final String bucket, final ClusterFacade core,
        final Map, Transcoder> transcoders, final int expiry,
        final long timeout, final TimeUnit timeUnit) {
        return Observable.defer(new Func0>() {
            @Override
            public Observable call() {
                final GetRequest request = new GetRequest(id, bucket, false, true, expiry);
                addRequestSpan(environment, request, "get_and_touch");
                return applyTimeout(deferAndWatch(new Func1>() {
                        @Override
                        public Observable call(Subscriber s) {
                            request.subscriber(s);
                            return core.send(request);
                        }
                    }).filter(new GetAndTouchFilter(environment))
                        .map(new GetMap(environment, transcoders, target, id)),
                    request, environment, timeout, timeUnit);
            }
        });
    }


    public static class GetFilter implements Func1 {

        private final CouchbaseEnvironment environment;

        public GetFilter(CouchbaseEnvironment environment) {
          this.environment = environment;
        }

        @Override
        public Boolean call(GetResponse response) {
            if (response.status().isSuccess()) {
                return true;
            }
            ByteBuf content = response.content();
            if (content != null && content.refCnt() > 0) {
                content.release();
            }

            if (environment.operationTracingEnabled()) {
                environment.tracer().scopeManager()
                    .activate(response.request().span(), true)
                    .close();
            }

            switch (response.status()) {
                case NOT_EXISTS:
                    return false;
                case TEMPORARY_FAILURE:
                case SERVER_BUSY:
                    throw addDetails(new TemporaryFailureException(), response);
                case OUT_OF_MEMORY:
                    throw addDetails(new CouchbaseOutOfMemoryException(), response);
                default:
                    throw addDetails(new CouchbaseException(response.status().toString()), response);
            }
        }
    }

    private static class GetAndLockFilter implements Func1 {

        private final CouchbaseEnvironment environment;

        GetAndLockFilter(CouchbaseEnvironment environment) {
            this.environment = environment;
        }

        @Override
        public Boolean call(GetResponse response) {
            if (response.status().isSuccess()) {
                return true;
            }
            ByteBuf content = response.content();
            if (content != null && content.refCnt() > 0) {
                content.release();
            }

            if (environment.operationTracingEnabled()) {
                environment.tracer().scopeManager()
                    .activate(response.request().span(), true)
                    .close();
            }

            switch (response.status()) {
                case NOT_EXISTS:
                    return false;
                case TEMPORARY_FAILURE:
                case LOCKED:
                    throw addDetails(new TemporaryLockFailureException(), response);
                case SERVER_BUSY:
                    throw addDetails(new TemporaryFailureException(), response);
                case OUT_OF_MEMORY:
                    throw addDetails(new CouchbaseOutOfMemoryException(), response);
                default:
                    throw addDetails(new CouchbaseException(response.status().toString()), response);
            }
        }
    }

    private static class GetAndTouchFilter implements Func1 {

        private final CouchbaseEnvironment environment;

        GetAndTouchFilter(CouchbaseEnvironment environment) {
            this.environment = environment;
        }

        @Override
        public Boolean call(GetResponse response) {
            if (response.status().isSuccess()) {
                return true;
            }
            ByteBuf content = response.content();
            if (content != null && content.refCnt() > 0) {
                content.release();
            }

            if (environment.operationTracingEnabled()) {
                environment.tracer().scopeManager()
                    .activate(response.request().span(), true)
                    .close();
            }

            switch (response.status()) {
                case NOT_EXISTS:
                    return false;
                case TEMPORARY_FAILURE:
                case SERVER_BUSY:
                case LOCKED:
                    throw addDetails(new TemporaryFailureException(), response);
                case OUT_OF_MEMORY:
                    throw addDetails(new CouchbaseOutOfMemoryException(), response);
                default:
                    throw addDetails(new CouchbaseException(response.status().toString()), response);
            }
        }
    }

  public static class GetMap implements Func1 {

        private final CouchbaseEnvironment environment;
        private final Map, Transcoder> transcoders;
        private final Class target;
        private final String id;

        public GetMap(CouchbaseEnvironment environment, Map,
          Transcoder> transcoders, Class target, String id) {
          this.environment = environment;
          this.transcoders = transcoders;
          this.target = target;
          this.id = id;
        }

        @Override
        @SuppressWarnings({"unchecked"})
        public D call(final GetResponse response) {
            Transcoder transcoder = (Transcoder) transcoders.get(target);

            Scope decodeScope = null;
            if (environment.operationTracingEnabled()) {
                decodeScope = environment.tracer()
                    .buildSpan("response_decoding")
                    .asChildOf(response.request().span())
                    .startActive(true);
            }

            D decoded = (D) transcoder.decode(id, response.content(), response.cas(), 0,
                response.flags(), response.status());

            if (environment.operationTracingEnabled() && decodeScope != null) {
                decodeScope.close();
                if (decodeScope.span() instanceof ThresholdLogSpan) {
                    decodeScope.span().setBaggageItem(ThresholdLogReporter.KEY_DECODE_MICROS,
                        Long.toString(((ThresholdLogSpan) decodeScope.span()).durationMicros())
                    );
                }
            }

            if (environment.operationTracingEnabled()) {
                environment.tracer().scopeManager()
                    .activate(response.request().span(), true)
                    .close();
            }

            return decoded;
        }

    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy