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

scalikejdbc.LoanPattern.scala Maven / Gradle / Ivy

The newest version!
package scalikejdbc

import org.slf4j.LoggerFactory

import scala.language.reflectiveCalls
import scala.concurrent.{ ExecutionContext, Future }
import scala.util.control.NonFatal

object LoanPattern extends LoanPattern

/**
 * Loan pattern implementation
 */
trait LoanPattern {

  private[scalikejdbc] val loanPatternLogger =
    LoggerFactory.getLogger(classOf[LoanPattern])

  type Closable = { def close(): Unit }

  def using[R <: Closable, A](resource: R)(f: R => A): A = {
    try {
      f(resource)
    } finally {
      try {
        resource.close()
      } catch {
        case NonFatal(e) =>
          val e2 = e match {
            case _: ReflectiveOperationException if e.getCause != null =>
              // Scala 3 use simple reflection instead of MethodHandle unlike Scala 2.x
              // We use `cause` for compatibility if `ReflectiveOperationException`
              // https://github.com/lampepfl/dotty/blob/fcd837addc5b466b055da069960e48c5d4d5c1dc/library/src/scala/reflect/Selectable.scala#L36-L40
              e.getCause
            case _ =>
              e
          }
          loanPatternLogger.warn(
            s"Failed to close a resource (resource: ${resource.getClass().getName()} error: ${e2.getMessage})"
          )
      }
    }
  }

  /**
   * Guarantees a Closeable resource will be closed after being passed to a block that takes
   * the resource as a parameter and returns a Future.
   */
  def futureUsing[R <: Closable, A](
    resource: R
  )(f: R => Future[A])(implicit ec: ExecutionContext): Future[A] = {
    f(resource) andThen { case _ => resource.close() } // close no matter what
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy