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

com.github.mauricio.async.db.pool.AsyncObjectPool.scala Maven / Gradle / Ivy

/*
 * Copyright 2013 Maurício Linhares
 *
 * Maurício Linhares licenses this file to you 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.github.mauricio.async.db.pool

import scala.concurrent.{ExecutionContext, Future, Promise}

/**
 *
 * Defines the common interface for async object pools. These are pools that do not block clients trying to acquire
 * a resource from it. Different than the usual synchronous pool, you **must** return objects back to it manually
 * since it's impossible for the pool to know when the object is ready to be given back.
 *
 * @tparam T
 */

trait AsyncObjectPool[T] {

  /**
   *
   * Returns an object from the pool to the callee with the returned future. If the pool can not create or enqueue
   * requests it will fill the returned [[scala.concurrent.Future]] with an
   * [[com.github.mauricio.async.db.pool.PoolExhaustedException]].
   *
   * @return future that will eventually return a usable pool object.
   */

  def take: Future[T]

  /**
   *
   * Returns an object taken from the pool back to it. This object will become available for another client to use.
   * If the object is invalid or can not be reused for some reason the [[scala.concurrent.Future]] returned will contain
   * the error that prevented this object of being added back to the pool. The object is then discarded from the pool.
   *
   * @param item
   * @return
   */

  def giveBack( item : T ) : Future[AsyncObjectPool[T]]

  /**
   *
   * Closes this pool and future calls to **take** will cause the [[scala.concurrent.Future]] to raise an
   * [[com.github.mauricio.async.db.pool.PoolAlreadyTerminatedException]].
   *
   * @return
   */

  def close : Future[AsyncObjectPool[T]]

  /**
   *
   * Retrieve and use an object from the pool for a single computation, returning it when the operation completes.
   *
   * @param f function that uses the object
   * @return f wrapped with take and giveBack
   */

  def use[A](f: (T) => Future[A])(implicit executionContext: ExecutionContext): Future[A] =
    take.flatMap { item =>
      val p = Promise[A]()
      try {
        f(item).onComplete { r =>
          giveBack(item).onComplete { _ =>
            p.complete(r)
          }
        }
      } catch {
        // calling f might throw exception.
        // in that case the item will be removed from the pool if identified as invalid by the factory.
        // the error returned to the user is the original error thrown by f.
        case error: Throwable =>
          giveBack(item).onComplete { _ =>
            p.failure(error)
          }
      }

      p.future
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy