com.couchbase.client.scala.Collection.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-client_2.12 Show documentation
Show all versions of scala-client_2.12 Show documentation
The official Couchbase Scala SDK
/*
* Copyright (c) 2019 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.scala
import com.couchbase.client.core.annotation.SinceCouchbase
import com.couchbase.client.core.api.kv.CoreExpiry
import com.couchbase.client.core.io.CollectionIdentifier
import com.couchbase.client.scala.codec._
import com.couchbase.client.scala.datastructures._
import com.couchbase.client.scala.durability.Durability
import com.couchbase.client.scala.durability.Durability._
import com.couchbase.client.scala.kv._
import com.couchbase.client.scala.manager.query.CollectionQueryIndexManager
import com.couchbase.client.scala.util.CoreCommonConverters.{
convert,
convertExpiry,
encoder,
makeCommonOptions
}
import com.couchbase.client.scala.util.{ExpiryUtil, TimeoutUtil}
import scala.compat.java8.OptionConverters._
import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.jdk.CollectionConverters._
import scala.reflect.ClassTag
import scala.util.control.NonFatal
import scala.util.{Failure, Try}
object Collection {
private[scala] def block[T](in: Future[T]): Try[T] = {
try {
Try(Await.result(in, Duration.Inf))
} catch {
case NonFatal(err) => Failure(err)
}
}
}
/**
* Provides blocking, synchronous access to all collection APIs. This is the main entry-point for key-value (KV)
* operations.
*
* If asynchronous access is needed, we recommend looking at the [[AsyncCollection]] which is built around
* returning `Future`s, or the [[ReactiveCollection]] which provides a reactive programming API.
*
* This blocking API itself is just a small layer on top of the [[AsyncCollection]] which blocks the current thread
* until the request completes with a response.
*
* @author Graham Pople
* @since 1.0.0
* @define Id the unique identifier of the document
* @define CAS Couchbase documents all have a CAS (Compare-And-Set) field, a simple integer that allows
* optimistic concurrency - e.g. it can detect if another agent has modified a document
* in-between this agent getting and modifying the document. The default is 0, which disables
* CAS checking.
* @define WithExpiry Couchbase documents optionally can have an expiration field set, e.g. when they will
* automatically expire. For efficiency reasons, by default the value of this expiration
* field is not fetched upon getting a document. If expiry is being used, then set this
* field to true to ensure the expiration is fetched. This will not only make it available
* in the returned result, but also ensure that the expiry is available to use when mutating
* the document, to avoid accidentally resetting the expiry to the default of 0.
* @define Expiry Couchbase documents optionally can have an expiration field set, e.g. when they will
* automatically expire. On mutations if this is left at the default (0), then any expiry
* will be removed and the document will never expire. If the application wants to preserve
* expiration then they should use the `withExpiration` parameter on any gets, and provide
* the returned expiration parameter to any mutations.
* @define Timeout when the operation will timeout. This will default to `timeoutConfig().kvTimeout()` in the
* provided [[com.couchbase.client.scala.env.ClusterEnvironment]].
* @define RetryStrategy provides some control over how the SDK handles failures. Will default to `retryStrategy()`
* in the provided [[com.couchbase.client.scala.env.ClusterEnvironment]].
* @define ErrorHandling any `scala.util.control.NonFatal` error returned will derive ultimately from
* `com.couchbase.client.core.error.CouchbaseException`. See
* [[https://docs.couchbase.com/scala-sdk/current/howtos/error-handling.html the error handling docs]]
* for more detail.
* @define SupportedTypes this can be of any type for which an implicit
* `com.couchbase.client.scala.codec.Conversions.JsonSerializer` can be found: a list
* of types that are supported 'out of the box' is available at
* [[https://docs.couchbase.com/scala-sdk/current/howtos/json.html these JSON docs]]
* @define Durability writes in Couchbase are written to a single node, and from there the Couchbase Server will
* take care of sending that mutation to any configured replicas. This parameter provides
* some control over ensuring the success of the mutation's replication. See
* [[com.couchbase.client.scala.durability.Durability]]
* for a detailed discussion.
* @define ParentSpan an optional parent 'span' for the request, allowing tracing requests through the full
* distributed system
* @define Options configure options that affect this operation
**/
class Collection(
/** Provides access to an async version of this API. */
val async: AsyncCollection,
val bucketName: String
) {
private[scala] implicit val ec: ExecutionContext = async.ec
def name: String = async.name
def scopeName: String = async.scopeName
/** Provides access to a reactive-programming version of this API. */
val reactive = new ReactiveCollection(async)
/** Provides access to less-commonly used methods. */
val binary = new BinaryCollection(async.binary)
/** Manage query indexes for this collection */
lazy val queryIndexes = new CollectionQueryIndexManager(async.queryIndexes)
private[scala] val kvTimeout: Durability => Duration = TimeoutUtil.kvTimeout(async.environment)
private[scala] val kvReadTimeout: Duration = async.kvReadTimeout
private[scala] val kvOps = async.kvOps
private[scala] lazy val collectionIdentifier =
new CollectionIdentifier(bucketName, Some(scopeName).asJava, Some(name).asJava)
private def block[T](in: Future[T]) =
Collection.block(in)
/** Fetches a full document from this collection.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.GetOptions]] instead, which supports all available options.
*
* @param id $Id
* @param timeout $Timeout
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def get(
id: String,
timeout: Duration = kvReadTimeout
): Try[GetResult] =
Try(kvOps.getBlocking(makeCommonOptions(timeout), id, AsyncCollection.EmptyList, false))
.map(result => convert(result, async.environment, None))
/** Fetches a full document from this collection.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def get(
id: String,
options: GetOptions
): Try[GetResult] =
Try(kvOps.getBlocking(convert(options), id, options.project.asJava, options.withExpiry))
.map(result => convert(result, async.environment, options.transcoder))
/** Inserts a full document into this collection, if it does not exist already.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.InsertOptions]] instead, which supports all available options.
*
* @param id $Id
* @param content $SupportedTypes
* @param durability $Durability
* @param timeout $Timeout
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentAlreadyExistsException`, indicating the document already exists.
* $ErrorHandling
**/
def insert[T](
id: String,
content: T,
durability: Durability = Disabled,
timeout: Duration = Duration.MinusInf
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.insertBlocking(
makeCommonOptions(timeout),
id,
encoder(async.environment.transcoder, serializer, content),
convert(durability),
CoreExpiry.NONE
)
).map(result => convert(result))
}
/** Inserts a full document into this collection, if it does not exist already.
*
* @param id $Id
* @param content $SupportedTypes
* @param options $Options
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentAlreadyExistsException`, indicating the document already exists.
* $ErrorHandling
**/
def insert[T](
id: String,
content: T,
options: InsertOptions
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.insertBlocking(
convert(options),
id,
encoder(options.transcoder.getOrElse(async.environment.transcoder), serializer, content),
convert(options.durability),
ExpiryUtil.expiryActual(options.expiry, options.expiryTime)
)
).map(result => convert(result))
}
/** Replaces the contents of a full document in this collection, if it already exists.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.ReplaceOptions]] instead, which supports all available options.
*
* @param id $Id
* @param content $SupportedTypes
* @param cas $CAS
* @param durability $Durability
* @param timeout $Timeout
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def replace[T](
id: String,
content: T,
cas: Long = 0,
durability: Durability = Disabled,
timeout: Duration = Duration.MinusInf
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.replaceBlocking(
makeCommonOptions(timeout),
id,
encoder(async.environment.transcoder, serializer, content),
cas,
convert(durability),
CoreExpiry.NONE,
false
)
).map(result => convert(result))
}
/** Replaces the contents of a full document in this collection, if it already exists.
*
* @param id $Id
* @param content $SupportedTypes
* @param options $Options
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def replace[T](
id: String,
content: T,
options: ReplaceOptions
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.replaceBlocking(
convert(options),
id,
encoder(options.transcoder.getOrElse(async.environment.transcoder), serializer, content),
options.cas,
convert(options.durability),
ExpiryUtil.expiryActual(options.expiry, options.expiryTime),
options.preserveExpiry
)
).map(result => convert(result))
}
/** Upserts the contents of a full document in this collection.
*
* Upsert here means to insert the document if it does not exist, or replace the content if it does.
*
* This overloads provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.UpsertOptions]] instead, which supports all available options.
*
* @param id $Id
* @param content $SupportedTypes
* @param durability $Durability
* @param timeout $Timeout
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. $ErrorHandling
*/
def upsert[T](
id: String,
content: T,
durability: Durability = Disabled,
timeout: Duration = Duration.MinusInf
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.upsertBlocking(
makeCommonOptions(timeout),
id,
encoder(async.environment.transcoder, serializer, content),
convert(durability),
CoreExpiry.NONE,
false
)
).map(result => convert(result))
}
/** Upserts the contents of a full document in this collection.
*
* Upsert here means to insert the document if it does not exist, or replace the content if it does.
*
* @param id $Id
* @param content $SupportedTypes
* @param options $Options
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. $ErrorHandling
*/
def upsert[T](
id: String,
content: T,
options: UpsertOptions
)(implicit serializer: JsonSerializer[T]): Try[MutationResult] = {
Try(
kvOps.upsertBlocking(
convert(options),
id,
encoder(options.transcoder.getOrElse(async.environment.transcoder), serializer, content),
convert(options.durability),
ExpiryUtil.expiryActual(options.expiry, options.expiryTime),
options.preserveExpiry
)
).map(result => convert(result))
}
/** Removes a document from this collection, if it exists.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.RemoveOptions]] instead, which supports all available options.
*
* @param id $Id
* @param cas $CAS
* @param durability $Durability
* @param timeout $Timeout
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def remove(
id: String,
cas: Long = 0,
durability: Durability = Disabled,
timeout: Duration = Duration.MinusInf
): Try[MutationResult] = {
Try(kvOps.removeBlocking(makeCommonOptions(timeout), id, cas, convert(durability)))
.map(result => convert(result))
}
/** Removes a document from this collection, if it exists.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def remove(
id: String,
options: RemoveOptions
): Try[MutationResult] = {
Try(kvOps.removeBlocking(convert(options), id, options.cas, convert(options.durability)))
.map(result => convert(result))
}
/** Sub-Document mutations allow modifying parts of a JSON document directly, which can be more efficiently than
* fetching and modifying the full document.
*
* Mutations are all-or-nothing: if one fails, then no mutation will be performed.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.MutateInOptions]] instead, which supports all available options.
*
* @param id $Id
* @param spec a sequence of `MutateInSpec` specifying what mutations to apply to the document. See
* [[com.couchbase.client.scala.kv.MutateInSpec]] for more details.
* @param cas $CAS
* @param document controls whether the document should be inserted, upserted, or not touched. See
* [[com.couchbase.client.scala.kv.StoreSemantics]] for details.
* @param durability $Durability
* @param timeout $Timeout
*
* @return on success, a `Success(MutateInResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def mutateIn(
id: String,
spec: collection.Seq[MutateInSpec],
cas: Long = 0,
document: StoreSemantics = StoreSemantics.Replace,
durability: Durability = Disabled,
timeout: Duration = Duration.MinusInf
): Try[MutateInResult] = {
Try(
kvOps.subdocMutateBlocking(
makeCommonOptions(timeout),
id,
() => spec.map(v => v.convert).asJava,
convert(document),
cas,
convert(durability),
CoreExpiry.NONE,
false,
false,
false
)
).map(result => convert(result))
}
/** Sub-Document mutations allow modifying parts of a JSON document directly, which can be more efficiently than
* fetching and modifying the full document.
*
* Mutations are all-or-nothing: if one fails, then no mutation will be performed.
*
* @param id $Id
* @param spec a sequence of `MutateInSpec` specifying what mutations to apply to the document. See
* [[com.couchbase.client.scala.kv.MutateInSpec]] for more details.
* @param options $Options
*
* @return on success, a `Success(MutateInResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def mutateIn(
id: String,
spec: collection.Seq[MutateInSpec],
options: MutateInOptions
): Try[MutateInResult] = {
Try(
kvOps.subdocMutateBlocking(
convert(options),
id,
() => spec.map(v => v.convert).asJava,
convert(options.document),
options.cas,
convert(options.durability),
ExpiryUtil.expiryActual(options.expiry, options.expiryTime),
options.preserveExpiry,
options.accessDeleted,
options.createAsDeleted
)
).map(result => convert(result))
}
/** Fetches a full document from this collection, and simultaneously lock the document from writes.
*
* The CAS value returned in the [[kv.GetResult]] is the document's 'key': during the locked period, the document
* may only be modified by providing this CAS.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.GetAndLockOptions]] instead, which supports all available options.
*
* @param id $Id
* @param lockTime how long to lock the document for
* @param timeout $Timeout
*
* @return on success, a Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAndLock(
id: String,
lockTime: Duration,
timeout: Duration = kvReadTimeout
): Try[GetResult] =
Try(kvOps.getAndLockBlocking(makeCommonOptions(timeout), id, convert(lockTime)))
.map(result => convert(result, async.environment, None))
/** Fetches a full document from this collection, and simultaneously lock the document from writes.
*
* The CAS value returned in the [[kv.GetResult]] is the document's 'key': during the locked period, the document
* may only be modified by providing this CAS.
*
* @param id $Id
* @param lockTime how long to lock the document for
* @param options $Options
*
* @return on success, a Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAndLock(
id: String,
lockTime: Duration,
options: GetAndLockOptions
): Try[GetResult] =
Try(kvOps.getAndLockBlocking(convert(options), id, convert(lockTime)))
.map(result => convert(result, async.environment, options.transcoder))
/** Unlock a locked document.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.UnlockOptions]] instead, which supports all available options.
*
* @param id $Id
* @param cas must match the CAS value return from a previous `.getAndLock()` to successfully
* unlock the document
* @param timeout $Timeout
*
* @return on success, a `Success(Unit)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def unlock(
id: String,
cas: Long,
timeout: Duration = kvReadTimeout
): Try[Unit] =
Try(kvOps.unlockBlocking(makeCommonOptions(timeout), id, cas)).map(_ => ())
/** Unlock a locked document.
*
* @param id $Id
* @param cas must match the CAS value return from a previous `.getAndLock()` to successfully
* unlock the document
* @param options $Options
*
* @return on success, a `Success(Unit)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def unlock(
id: String,
cas: Long,
options: UnlockOptions
): Try[Unit] =
Try(kvOps.unlockBlocking(convert(options), id, cas)).map(_ => ())
/** Fetches a full document from this collection, and simultaneously update the expiry value of the document.
*
* @param id $Id
* @param expiry $Expiry
* @param options $Options
*
* @return on success, a Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAndTouch(
id: String,
expiry: Duration,
options: GetAndTouchOptions
): Try[GetResult] =
Try(kvOps.getAndTouchBlocking(convert(options), id, convertExpiry(expiry)))
.map(result => convert(result, async.environment, options.transcoder))
/** Fetches a full document from this collection, and simultaneously update the expiry value of the document.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.GetAndTouchOptions]] instead, which supports all available options.
*
* @param id $Id
* @param expiry $Expiry
* @param timeout $Timeout
*
* @return on success, a Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAndTouch(
id: String,
expiry: Duration,
timeout: Duration = kvReadTimeout
): Try[GetResult] =
Try(kvOps.getAndTouchBlocking(makeCommonOptions(timeout), id, convertExpiry(expiry)))
.map(result => convert(result, async.environment, None))
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInResult]] for details on
* how to process the results.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.LookupInOptions]] instead, which supports all available options.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param timeout $Timeout
*
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def lookupIn(
id: String,
spec: collection.Seq[LookupInSpec],
timeout: Duration = kvReadTimeout
): Try[LookupInResult] =
block(async.lookupIn(id, spec, timeout))
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInResult]] for details on
* how to process the results.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param options $Options
*
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def lookupIn(
id: String,
spec: collection.Seq[LookupInSpec],
options: LookupInOptions
): Try[LookupInResult] =
block(async.lookupIn(id, spec, options))
/** Retrieves any available version of the document.
*
* The application should default to using `.get()` instead. This method is intended for high-availability
* situations where, say, a `.get()` operation has failed, and the
* application wants to return any - even possibly stale - data as soon as possible.
*
* Under the hood this sends a request to all configured replicas for the document, including the active, and
* whichever returns first is returned.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.GetAnyReplicaOptions]] instead, which supports all available options.
*
* @param id $Id
* @param timeout $Timeout
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAnyReplica(
id: String,
timeout: Duration = kvReadTimeout
): Try[GetReplicaResult] =
Try(
reactive
.getAnyReplica(id, timeout)
.block(timeout)
)
/** Retrieves any available version of the document.
*
* The application should default to using `.get()` instead. This method is intended for high-availability
* situations where, say, a `.get()` operation has failed, and the
* application wants to return any - even possibly stale - data as soon as possible.
*
* Under the hood this sends a request to all configured replicas for the document, including the active, and
* whichever returns first is returned.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAnyReplica(
id: String,
options: GetAnyReplicaOptions
): Try[GetReplicaResult] = {
val timeout = if (options.timeout == Duration.MinusInf) kvReadTimeout else options.timeout
Try(
reactive
.getAnyReplica(id, options)
.block(timeout)
)
}
/** Retrieves all available versions of the document.
*
* The application should default to using `.get()` instead. This method is intended for advanced scenarios,
* including where a particular write has ambiguously failed (e.g. it may or may not have succeeded), and the
* application wants to attempt manual verification and resolution.
*
* The returned `Iterable` will block on each call to `next` until the next replica has responded.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.GetAllReplicasOptions]] instead, which supports all available options.
*
* @param id $Id
* @param timeout $Timeout
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAllReplicas(
id: String,
timeout: Duration = kvReadTimeout
): Iterable[GetReplicaResult] =
reactive.getAllReplicas(id, timeout).toIterable()
/** Retrieves all available versions of the document.
*
* The application should default to using `.get()` instead. This method is intended for advanced scenarios,
* including where a particular write has ambiguously failed (e.g. it may or may not have succeeded), and the
* application wants to attempt manual verification and resolution.
*
* The returned Iterable` will block on each call to `next` until the next replica has responded.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def getAllReplicas(
id: String,
options: GetAllReplicasOptions
): Iterable[GetReplicaResult] =
reactive.getAllReplicas(id, options).toIterable()
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInReplicaResult]] for details on
* how to process the results.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.LookupInAllReplicasOptions]] instead, which supports all available options.
*
* This variant will read and return all replicas of the document.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param timeout $Timeout
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`.
**/
@SinceCouchbase("7.6")
def lookupInAllReplicas(
id: String,
spec: collection.Seq[LookupInSpec],
timeout: Duration = kvReadTimeout
): Try[Iterable[LookupInReplicaResult]] =
Try(reactive.lookupInAllReplicas(id, spec, timeout).toIterable())
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInReplicaResult]] for details on
* how to process the results.
*
* This variant will read and return all replicas of the document.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param options $Options
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`.
**/
@SinceCouchbase("7.6")
def lookupInAllReplicas(
id: String,
spec: collection.Seq[LookupInSpec],
options: LookupInAllReplicasOptions
): Try[Iterable[LookupInReplicaResult]] =
Try(reactive.lookupInAllReplicas(id, spec, options).toIterable())
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInReplicaResult]] for details on
* how to process the results.
*
* This variant will read all replicas of the document, and return the first one found.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.LookupInAnyReplicaOptions]] instead, which supports all available options.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param timeout $Timeout
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`.
**/
@SinceCouchbase("7.6")
def lookupInAnyReplica(
id: String,
spec: collection.Seq[LookupInSpec],
timeout: Duration = kvReadTimeout
): Try[LookupInReplicaResult] = {
Try(
reactive.lookupInAnyReplica(id, spec, timeout).block()
)
}
/** SubDocument lookups allow retrieving parts of a JSON document directly, which may be more efficient than
* retrieving the entire document.
*
* Individual operations can succeed or fail without affecting the others. See [[kv.LookupInReplicaResult]] for details on
* how to process the results.
*
* This variant will read all replicas of the document, and return the first one found.
*
* @param id $Id
* @param spec a sequence of `LookupInSpec` specifying what fields to fetch. See
* [[kv.LookupInSpec]] for more details.
* @param options $Options
* @return on success, a `Success(LookupInResult)`, else a `Failure(CouchbaseException)`.
**/
@SinceCouchbase("7.6")
def lookupInAnyReplica(
id: String,
spec: collection.Seq[LookupInSpec],
options: LookupInAnyReplicaOptions
): Try[LookupInReplicaResult] =
Try(
reactive.lookupInAnyReplica(id, spec, options).block()
)
/** Checks if a document exists.
*
* This doesn't fetch the document so if the application simply needs to know if the document exists, this is the
* most efficient method.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.ExistsOptions]] instead, which supports all available options.
*
* @param id $Id
* @param timeout $Timeout
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def exists(
id: String,
timeout: Duration = kvReadTimeout
): Try[ExistsResult] =
Try(kvOps.existsBlocking(makeCommonOptions(timeout), id))
.map(result => convert(result))
/** Checks if a document exists.
*
* This doesn't fetch the document so if the application simply needs to know if the document exists, this is the
* most efficient method.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(GetResult)`, else a `Failure(CouchbaseException)`. This could be `com
* .couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
**/
def exists(
id: String,
options: ExistsOptions
): Try[ExistsResult] =
Try(kvOps.existsBlocking(convert(options), id))
.map(result => convert(result))
/** Updates the expiry of the document with the given id.
*
* This overload provides only the most commonly used options. If you need to configure something more
* esoteric, use the overload that takes an [[com.couchbase.client.scala.kv.TouchOptions]] instead, which supports all available options.
*
* @param id $Id
* @param timeout $Timeout
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
*/
def touch(
id: String,
expiry: Duration,
timeout: Duration = kvReadTimeout
): Try[MutationResult] = {
Try(kvOps.touchBlocking(makeCommonOptions(timeout), id, convertExpiry(expiry)))
.map(result => convert(result))
}
/** Updates the expiry of the document with the given id.
*
* @param id $Id
* @param options $Options
*
* @return on success, a `Success(MutationResult)`, else a `Failure(CouchbaseException)`. This could be
* `com.couchbase.client.core.error.DocumentDoesNotExistException`, indicating the document could not be
* found. $ErrorHandling
*/
def touch(
id: String,
expiry: Duration,
options: TouchOptions
): Try[MutationResult] = {
Try(kvOps.touchBlocking(convert(options), id, convertExpiry(expiry)))
.map(result => convert(result))
}
/** Returns a [[com.couchbase.client.scala.datastructures.CouchbaseBuffer]] backed by this collection.
*
* @param id id of the document underyling the datastructure
* @param options options for controlling the behaviour of the datastructure
*/
def buffer[T](id: String, options: Option[CouchbaseCollectionOptions] = None)(
implicit decode: JsonDeserializer[T],
encode: JsonSerializer[T],
tag: ClassTag[T]
): CouchbaseBuffer[T] = {
new CouchbaseBuffer[T](id, this)
}
/** Returns a [[com.couchbase.client.scala.datastructures.CouchbaseSet]] backed by this collection.
*
* @param id id of the document underyling the datastructure
* @param options options for controlling the behaviour of the datastructure
*/
def set[T](id: String, options: Option[CouchbaseCollectionOptions] = None)(
implicit decode: JsonDeserializer[T],
encode: JsonSerializer[T]
): CouchbaseSet[T] = {
new CouchbaseSet[T](id, this)
}
/** Returns a [[com.couchbase.client.scala.datastructures.CouchbaseMap]] backed by this collection.
*
* @param id id of the document underyling the datastructure
* @param options options for controlling the behaviour of the datastructure
*/
def map[T](id: String, options: Option[CouchbaseCollectionOptions] = None)(
implicit decode: JsonDeserializer[T],
encode: JsonSerializer[T],
tag: ClassTag[T]
): CouchbaseMap[T] = {
new CouchbaseMap[T](id, this)
}
/** Returns a [[com.couchbase.client.scala.datastructures.CouchbaseQueue]] backed by this collection.
*
* @param id id of the document underyling the datastructure
* @param options options for controlling the behaviour of the datastructure
*/
def queue[T](id: String, options: Option[CouchbaseCollectionOptions] = None)(
implicit decode: JsonDeserializer[T],
encode: JsonSerializer[T],
tag: ClassTag[T]
): CouchbaseQueue[T] = {
new CouchbaseQueue[T](id, this)
}
/** Initiates a KV range scan, which will return a non-blocking stream of KV documents.
*
* Uses default options.
*
* '''CAVEAT:'''This method is suitable for use cases that require relatively
* low concurrency and tolerate relatively high latency.
* If your application does many scans at once, or requires low latency results,
* we recommend using SQL++ (with a primary index on the collection) instead.
*/
@SinceCouchbase("7.6")
def scan(scanType: ScanType): Try[Iterator[ScanResult]] = {
scan(scanType, ScanOptions())
}
/** Initiates a KV range scan, which will return a non-blocking stream of KV documents.
*
* '''CAVEAT:'''This method is suitable for use cases that require relatively
* low concurrency and tolerate relatively high latency.
* If your application does many scans at once, or requires low latency results,
* we recommend using SQL++ (with a primary index on the collection) instead.
*/
@SinceCouchbase("7.6")
def scan(scanType: ScanType, opts: ScanOptions): Try[Iterator[ScanResult]] = {
block(async.scan(scanType, opts))
}
}