DbOperation.scala 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. package utils
  2. import java.sql.Connection
  3. import java.util.concurrent._
  4. import javax.inject.{Singleton, Inject}
  5. import play.api.db.Database
  6. import play.api.Play.current
  7. import play.core.NamedThreadFactory
  8. import play.db.NamedDatabase
  9. import scala.concurrent._
  10. import scala.concurrent.Future
  11. @Singleton
  12. class DbOperation @Inject()(@NamedDatabase("hello_world") protected val db: Database) {
  13. private val maxDbOperations = current.configuration.underlying.getInt("max-db-ops")
  14. private val partitionCount = current.configuration.getInt("db.hello_world.partitionCount").getOrElse(2)
  15. private val maxConnections =
  16. partitionCount * current.configuration.getInt("db.hello_world.maxConnectionsPerPartition").getOrElse(5)
  17. private val minConnections =
  18. partitionCount * current.configuration.getInt("db.hello_world.minConnectionsPerPartition").getOrElse(5)
  19. private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
  20. 0L, TimeUnit.MILLISECONDS,
  21. new LinkedBlockingQueue[Runnable](), // TODO: Could use ArrayBlockingQueue?
  22. new NamedThreadFactory("dbEc"))
  23. private val dbEc = ExecutionContext.fromExecutorService(tpe)
  24. // Anorm code
  25. /**
  26. * Run a DB operation in the DB context. Automatically
  27. * provides a Session.
  28. */
  29. def asyncDbOp[T](op: Connection => T): Future[T] = {
  30. // If the thread-pool queue used by the database grows too large then our server
  31. // is probably struggling, and we should start dropping requests. If we don't
  32. // then we'll just slow everything down and it will fail anyway. Better to fail
  33. // quickly rather than slowly. Set the max size of our queue something above the
  34. // number of concurrent connections that we expect to be handling.
  35. if (tpe.getQueue.size > maxDbOperations) sys.error(s"Aborted DB operation because queue is > $maxDbOperations")
  36. Future {
  37. db.withConnection { connection => op(connection) }
  38. }(dbEc)
  39. }
  40. }