DbOperation.scala 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  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.Configuration
  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. configuration: Configuration) {
  14. private val maxDbOperations = configuration.underlying.getInt("max-db-ops")
  15. private val partitionCount = configuration.getInt("db.hello_world.partitionCount").getOrElse(2)
  16. private val maxConnections =
  17. partitionCount * configuration.getInt("db.hello_world.maxConnectionsPerPartition").getOrElse(5)
  18. private val minConnections =
  19. partitionCount * configuration.getInt("db.hello_world.minConnectionsPerPartition").getOrElse(5)
  20. private val tpe = new ThreadPoolExecutor(minConnections, maxConnections,
  21. 0L, TimeUnit.MILLISECONDS,
  22. new LinkedBlockingQueue[Runnable](), // TODO: Could use ArrayBlockingQueue?
  23. new NamedThreadFactory("dbEc"))
  24. private val dbEc = ExecutionContext.fromExecutorService(tpe)
  25. // Anorm code
  26. /**
  27. * Run a DB operation in the DB context. Automatically
  28. * provides a Session.
  29. */
  30. def asyncDbOp[T](op: Connection => T): Future[T] = {
  31. // If the thread-pool queue used by the database grows too large then our server
  32. // is probably struggling, and we should start dropping requests. If we don't
  33. // then we'll just slow everything down and it will fail anyway. Better to fail
  34. // quickly rather than slowly. Set the max size of our queue something above the
  35. // number of concurrent connections that we expect to be handling.
  36. if (tpe.getQueue.size > maxDbOperations) sys.error(s"Aborted DB operation because queue is > $maxDbOperations")
  37. Future {
  38. db.withConnection { connection => op(connection) }
  39. }(dbEc)
  40. }
  41. }