使用单独的ExecutionContext进行Slick

时间:2018-06-12 03:07:25

标签: scala playframework slick

我正在使用Play 2.5和Slick。关于此主题的docs只是声明一切都由Slick和Play的Slick模块管理。但是,此示例打印Dispatcher[akka.actor.default-dispatcher]

class MyDbioImpl @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext)
  with HasDatabaseConfigProvider[JdbcProfile] {
  import profile.api._
  def selectSomeStuff(): Future[MyResult] = db.run {
    println(ec)
    [...]
  }
}

由于执行上下文打印在db.run中,似乎我的所有数据库访问也将在默认执行上下文中执行。

我找到this answer一个较旧的问题,当时解决了这个问题。但是这个解决方案已被弃用,建议使用依赖注入来获取应用程序上下文。当我尝试这样做时,我得到一个错误,说play.akka.actor.slick-context不存在......

class MyDbioProvider @Inject()(actorSystem: ActorSystem,
                               protected val dbConfigProvider: DatabaseConfigProvider)
  extends Provider[MyDbioImpl] {
  override def get(): MyDbioImpl = {
    val ec = actorSystem.dispatchers.lookup("play.akka.actor.slick-context")
    new MyDbioImpl(dbConfigProvider)(ec)
  }
}

编辑: Slick的执行上下文是否是在某个配置文件中定义的“正常”执行上下文?上下文切换发生在哪里?我认为“数据库世界”的入口点是db.run

2 个答案:

答案 0 :(得分:2)

根据Slick

  

每个数据库都包含一个管理线程池的AsyncExecutor   用于异步执行数据库I / O操作。它的大小是   调整数据库最佳性能的主要参数   宾语。它应该设置为您将用于大小的值   传统的阻塞应用程序中的连接池(请参阅   关于HikariCP文档中的池大小调整以进一步了解   信息)。使用Database.forConfig时,线程池是   直接在外部配置文件中配置   连接参数。如果您使用任何其他工厂方法来获取   在数据库中,您可以使用默认配置或指定   自定义AsyncExecutor。

基本上它表示你不需要创建一个独立的ExecutionContext,因为Slick已经在内部隔离了一个线程池。您对Slick的任何调用都是非阻塞的,因此您应该使用默认的ExecutionContext。

答案 1 :(得分:0)

Slick的此实现可在BasicBackend.scala文件:runInContextSafe方法中看到。代码如下:

val promise = Promise[R]
val runnable = new Runnable {
   override def run() = {
      try {
         promise.completeWith(runInContextInline(a, ctx, streaming, topLevel, stackLevel = 1))
      } catch {
              case NonFatal(ex) => promise.failure(ex)
      }
   }
}
DBIO.sameThreadExecutionContext.execute(runnable)
promise.future

如上所示,此处使用Promise,然后使用其内部线程池快速执行其代码,并返回Promise的Future对象。因此,当执行Await.result / ready时,此处的Promise可能已经由Slick的内部线程执行,因此获取结果就足够了,并且可以在诸如Play的环境中执行Await.result / ready。不阻塞的。

有关详细信息,请参阅Scala关于“未来与承诺”的文档:https://docs.scala-lang.org/overviews/core/futures.html