code: @InterfaceStability.Experimental
      @InterfaceAudience.Public
      public static <D extends Document<?>> Single<D> getFirstPrimaryOrReplica(final String id,
          final Class<D> target, final Bucket bucket, final long primaryTimeout, final long replicaTimeout) {
          if (primaryTimeout <= 0) {
              throw new IllegalArgumentException("Primary timeout must be greater than 0ms");
          }
          if (replicaTimeout <= 0) {
              throw new IllegalArgumentException("Replica timeout must be greater than 0ms");
          }
  
          Observable<D> fallback = bucket
              .async()
              .getFromReplica(id, ReplicaMode.ALL, target)
              .timeout(replicaTimeout, TimeUnit.MILLISECONDS)
              .firstOrDefault(null)
              .filter(new Func1<D, Boolean>() {
                  @Override
                  public Boolean call(D d) {
                      return d != null;
                  }
              });
  
          return bucket
              .async()
              .get(id, target)
              .timeout(primaryTimeout, TimeUnit.MILLISECONDS)
              .onErrorResumeNext(fallback)
              .toSingle();
      }
docs: Asynchronously fetch the document from the primary and if that operations fails try
  all the replicas and return the first document that comes back from them.
  
  @param id the document ID to fetch.
  @param target the custom document type to use.
  @param bucket the bucket to use when fetching the doc.
  @param primaryTimeout the timeout to use in MS when fetching the primary.
  @param replicaTimeout the timeout to use in MS when subsequently fetching the replicas and primary.
  @return @return a {@link Single} with either 0 or 1 {@link Document}.