播放光滑的会话连接超时

时间:2014-03-24 23:51:38

标签: scala playframework play-slick slick-2.0

我遇到了Slick 2.0.1和play-slick 0.6.0.1中的会话和连接处理问题

错误是

[SQLException: Timed out waiting for a free available connection.]
[...]
Caused by: java.sql.SQLException: Timed out waiting for a free available connection.
    at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:88) ~[bonecp.jar:na]
[...]

我有一个播放基本控制器特性,用于在一个地方设置显式会话

trait BaseController extends Controller with Secured {
    import play.api.Play.current
    implicit def session: SessionDef = play.api.db.slick.DB.withSession {
        implicit session => {session}
    }
}

然后有/ list动作,使用显式会话简单调用UserService:

object List extends BaseController with Secured {
  def index = IsAuthenticated { username =>
    implicit request =>
    UserService.findByEmail(username).map { user =>
      Ok(views.html.List.index(user))
    }.getOrElse(Forbidden)
  }
}

我已删除所有异步操作,因此我认为此问题不会与类似问题重复:Play slick and Async - is it a race condition?Scala Play 2.2 Slick 1.0.1 - future { Try {...} } Timed out waiting for a free available connection

重新加载动作大约10次后会出现问题。

显然我在光滑的会话处理中做错了 - 在playframework中是否有任何关于光滑2会话处理的好例子?最好的做法是什么?

编辑:问题的一个可能来源可能是我用来保存TableQueries的对象

object Models {
    val users = TableQuery[Users]
    val mailinglists = TableQuery[Mailinglists]
    val mailinglistMemberships = TableQuery[MailinglistMemberships]
}

如果这可能是问题的根源,那么放置这些引用的好地方是什么?该对象的主要原因是在表定义的外键中引用这些实例(类似于http://slick.typesafe.com/doc/2.0.1/schemas.html#constraints

编辑:以下是findByEmail的代码 - 但我认为这并不重要。在所有查询中似乎都是相同的行为和问题。

def findByEmail(email: String)(implicit session: Session): Option[User]
  = Models.users.filter(_.email === email).firstOption

我会感谢任何正确方向的暗示。

2 个答案:

答案 0 :(得分:0)

我也遇到了同样的问题。看起来应用程序没有从连接池中获取连接。所以我使用了配置:

db.default.partitionCount=1  
db.default.maxConnectionsPerPartition=20 
db.default.minConnectionsPerPartition=10 
db.default.acquireIncrement=1    
db.default.acquireRetryAttempts=5 
db.default.acquireRetryDelay=5 seconds 
db.default.acquireRetryDelay=5 seconds
db.default.idleMaxAge=10 minute 
db.default.idleConnectionTestPeriod=5 minutes 
db.default.initSQL="SELECT 1" 
db.default.maxConnectionAge=1 hour

然后永远不会得到错误(等待免费可用连接超时)。(我的应用程序部署在带有postgres数据库的heroku上)

答案 1 :(得分:0)

问题出在BaseController特征的隐式会话定义中。似乎会话定义需要在Action级别而不是在控制器级别 - 不幸的是我无法解释原因(尚未)。

trait BaseController extends Controller with Secured {
    //REMOVED this code
    //import play.api.Play.current
    //implicit def session: SessionDef = play.api.db.slick.DB.withSession {
    //    implicit session => {session}
    //}
}

使用DbAction帮助更新了控制器操作 - 不会导致连接超时。

trait Application extends Controller {
  def index = DBAction { implicit request =>
    request.session.get("email") flatMap (email => UserService.findByEmail(email)) map { user =>
      Ok(views.html.index(user))
    } getOrElse {
      Ok(views.html.index(null))
    }
  }
}

object Application extends Controller with Application

所以仍然缺少的是将经过身份验证的操作与播放版本的DBAction混合。这里提出了同样的问题:compose slick dbaction with authenticated action

也许这个光滑/光滑的团队中的某个人可以介入并回答这些问题?