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

com.sandinh.couchbase.ScalaBucket.scala Maven / Gradle / Ivy

There is a newer version: 9.2.0
Show newest version
package com.sandinh.couchbase

import com.couchbase.client.java.bucket.AsyncBucketManager
import com.couchbase.client.java.document.Document
import com.couchbase.client.java.error.DocumentDoesNotExistException
import com.couchbase.client.java.query.{AsyncN1qlQueryResult, N1qlQuery, Statement}
import com.couchbase.client.java.view.{AsyncViewResult, ViewQuery}
import com.couchbase.client.java.{AsyncBucket, PersistTo, ReplicaMode, ReplicateTo}
import com.sandinh.couchbase.document.JsDocument
import com.sandinh.rx.Implicits._
import play.api.libs.json.Reads
import rx.{Observer, Observable}
import scala.concurrent.{Promise, Future}
import scala.reflect.ClassTag
import scala.concurrent.ExecutionContext.Implicits.global

object ScalaBucket {
  private[ScalaBucket] implicit class RichCbObs[T](val underlying: Observable[T]) extends AnyVal {
    /** couchbase-java-client return an empty Observable for get (or getXX) operators if document do not exist,
      * but return an `onError(DocumentDoesNotExistException)` Observable for unlock, replace, append, prepend operators.
      * When convert the getXX-return-Observable to Future (note that Future can not be empty),
      * for consistent, we also return a DocumentDoesNotExistException-failed Future.
      * @see com.sandinh.rx.Implicits.RichJObs#toFuture()
      */
    def toCbGetFuture: Future[T] = {
      val p = Promise[T]()
      underlying.single.subscribe(new Observer[T] {
        def onCompleted(): Unit = {}
        def onNext(t: T): Unit = p success t
        def onError(e: Throwable): Unit = e match {
          //NoSuchElementException is thrown in underlying.single
          case _: NoSuchElementException => p failure new DocumentDoesNotExistException
          case _                         => p failure e
        }
      })
      p.future
    }
  }
}

final class ScalaBucket(val asJava: AsyncBucket) /*extends AnyVal*/ {
  import ScalaBucket._

  @inline def name = asJava.name

  def getJsT[T: Reads](id: String): Future[T] = get[JsDocument](id).map(_.content.as[T])

  def get[D <: Document[_]](id: String)(implicit tag: ClassTag[D]): Future[D] =
    asJava.get(id, tag.runtimeClass.asInstanceOf[Class[D]]).toCbGetFuture

  /** usage: {{{
    * import com.sandinh.couchbase.Implicits._
    *
    * bucket.getT[String](id)
    * bucket.getT[JsValue](id)
    * }}}
    */
  def getT[T](id: String)(implicit c: Class[_ <: Document[T]]): Future[T] =
    asJava.get(id, c).toCbGetFuture.map(_.content)

  @deprecated("use com.sandinh.couchbase.Implicits.DocNotExistFuture", "7.1.0")
  def getOrElseT[T](id: String)(default: => T)(implicit c: Class[_ <: Document[T]]): Future[T] =
    getT[T](id).recover { case _: DocumentDoesNotExistException => default }

  def getFromReplica[D <: Document[_]](id: String, tpe: ReplicaMode)(implicit tag: ClassTag[D]): Future[D] =
    asJava.getFromReplica(id, tpe, tag.runtimeClass.asInstanceOf[Class[D]]).toCbGetFuture

  def getAndLock[D <: Document[_]](id: String, lockTime: Int)(implicit tag: ClassTag[D]): Future[D] =
    asJava.getAndLock(id, lockTime, tag.runtimeClass.asInstanceOf[Class[D]]).toCbGetFuture

  def getAndTouch[D <: Document[_]](id: String, expiry: Int)(implicit tag: ClassTag[D]): Future[D] =
    asJava.getAndTouch(id, expiry, tag.runtimeClass.asInstanceOf[Class[D]]).toCbGetFuture

  def insert[D <: Document[_]](document: D): Future[D] = asJava.insert(document).toFuture
  def insert[D <: Document[_]](document: D, persistTo: PersistTo): Future[D] = asJava.insert(document, persistTo).toFuture
  def insert[D <: Document[_]](document: D, replicateTo: ReplicateTo): Future[D] = asJava.insert(document, replicateTo).toFuture
  def insert[D <: Document[_]](document: D, persistTo: PersistTo, replicateTo: ReplicateTo): Future[D] =
    asJava.insert(document, persistTo, replicateTo).toFuture

  def upsert[D <: Document[_]](document: D): Future[D] = asJava.upsert(document).toFuture
  def upsert[D <: Document[_]](document: D, persistTo: PersistTo): Future[D] = asJava.upsert(document, persistTo).toFuture
  def upsert[D <: Document[_]](document: D, replicateTo: ReplicateTo): Future[D] = asJava.upsert(document, replicateTo).toFuture
  def upsert[D <: Document[_]](document: D, persistTo: PersistTo, replicateTo: ReplicateTo): Future[D] =
    asJava.upsert(document, persistTo, replicateTo).toFuture

  def replace[D <: Document[_]](document: D): Future[D] = asJava.replace(document).toFuture
  def replace[D <: Document[_]](document: D, persistTo: PersistTo): Future[D] = asJava.replace(document, persistTo).toFuture
  def replace[D <: Document[_]](document: D, replicateTo: ReplicateTo): Future[D] = asJava.replace(document, replicateTo).toFuture
  def replace[D <: Document[_]](document: D, persistTo: PersistTo, replicateTo: ReplicateTo): Future[D] =
    asJava.replace(document, persistTo, replicateTo).toFuture

  def remove[D <: Document[_]](document: D): Future[D] = asJava.remove(document).toFuture
  def remove[D <: Document[_]](document: D, persistTo: PersistTo): Future[D] = asJava.remove(document, persistTo).toFuture
  def remove[D <: Document[_]](document: D, replicateTo: ReplicateTo): Future[D] = asJava.remove(document, replicateTo).toFuture
  def remove[D <: Document[_]](document: D, persistTo: PersistTo, replicateTo: ReplicateTo): Future[D] =
    asJava.remove(document, persistTo, replicateTo).toFuture

  def remove[D <: Document[_]](id: String)(implicit tag: ClassTag[D]) = asJava.remove(id, tag.runtimeClass.asInstanceOf[Class[D]]).toFuture
  def remove[D <: Document[_]](id: String, persistTo: PersistTo)(implicit tag: ClassTag[D]): Future[D] =
    asJava.remove(id, persistTo, tag.runtimeClass.asInstanceOf[Class[D]]).toFuture
  def remove[D <: Document[_]](id: String, replicateTo: ReplicateTo)(implicit tag: ClassTag[D]): Future[D] =
    asJava.remove(id, replicateTo, tag.runtimeClass.asInstanceOf[Class[D]]).toFuture
  def remove[D <: Document[_]](id: String, persistTo: PersistTo, replicateTo: ReplicateTo)(implicit tag: ClassTag[D]): Future[D] =
    asJava.remove(id, persistTo, replicateTo, tag.runtimeClass.asInstanceOf[Class[D]]).toFuture

  def query(query: ViewQuery): Future[AsyncViewResult] = asJava.query(query).toFuture
  def query(query: N1qlQuery): Future[AsyncN1qlQueryResult] = asJava.query(query).toFuture
  def query(query: Statement): Future[AsyncN1qlQueryResult] = asJava.query(query).toFuture

  def unlock(id: String, cas: Long): Future[Boolean] = asJava.unlock(id, cas).toFuture.map(_.booleanValue)
  def unlock[D <: Document[_]](document: D): Future[Boolean] = asJava.unlock(document).toFuture.map(_.booleanValue)

  def touch(id: String, expiry: Int): Future[Boolean] = asJava.touch(id, expiry).toFuture.map(_.booleanValue)
  def touch[D <: Document[_]](document: D): Future[Boolean] = asJava.touch(document).toFuture.map(_.booleanValue)

  def counter(id: String, delta: Long): Future[Long] = asJava.counter(id, delta).toFuture.map(_.content.longValue)
  def counter(id: String, delta: Long, initial: Long, expiry: Int = 0): Future[Long] =
    asJava.counter(id, delta, initial, expiry).toFuture.map(_.content.longValue)

  /** @note the result document has expiry = 0 & content = null
    * @see https://github.com/couchbase/couchbase-java-client/commit/6f0c7cf2247a3ef99a71ef2edd67f1077e4646e0
    */
  def append[D <: Document[_]](document: D): Future[D] = asJava.append(document).toFuture
  /** @note the result document has expiry = 0 & content = null
    * @see https://github.com/couchbase/couchbase-java-client/commit/6f0c7cf2247a3ef99a71ef2edd67f1077e4646e0
    */
  def prepend[D <: Document[_]](document: D): Future[D] = asJava.prepend(document).toFuture

  def bucketManager: Future[AsyncBucketManager] = asJava.bucketManager().toFuture

  def close(): Future[Boolean] = asJava.close().toFuture.map(_.booleanValue)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy