EzDevInfo.com

squeryl

A Scala DSL for talking with databases with minimum verbosity and maximum type safety Squeryl - A Scala ORM for SQL Databases squeryl is a strongly typed, declarative and sql like dsl for manipulating database objects from within the scala language

Which project is more mature, ScalaQuery or Squeryl? [closed]

For me both of them looks quite similar if it's going to features, but it's hard to say without using them (yet). So I have few questions:

1) Are they really feature comparable (more or less)?
2) Is there any example of enterprise or big open source system using any of them?
3) I have impression that Squeryl have better documentation, is lack of documentation in case of ScalaQuery real problem?
4) Which of them is growing faster and/or is faster on fixing the bugs?
5) Is any of them easier to use / more productive?


Source: (StackOverflow)

HowTo: Custom Field in Lift-Record-Squeryl

I'm trying to make a EnumListField in Lift/Record/Squeryl, similar to MappedEnumList in LiftMapper. The storage type should be Long/BIGINT. I understand that if I define:

def classOfPersistentField = classOf[Long]

Then Squeryl will know it should create a BIGINT column. And I know it will use setFromAny() to set the value, passing in the Long. The one piece I don't get is:

How will it read the field's value? If it uses valueBox, it will get a Seq[Enum#Value], and it won't know how to turn that into a Long. How do I tell Squeryl how to convert my Seq[Enum#Value] to a Long, or define a "getter" that returns a Long, and that doesn't conflict with the "normal" getter(s)?


Source: (StackOverflow)

Advertisements

Heroku memory leak with Play2 scala

Was doing some stretch (ab) test to my 1 heroku dyno and dev database with 20 connections limit.

During the calls (that access database with squeryl the heap allocation is increasing causing R14 (memory more than 512MB))

I cannot seem to reproduce the problem (at that levels at least locally).

Is there any way to get heroku heap dump and analyze it to get some clue?

Is there any known issues with play2, scala, squeryl and heroku memory leak?

Update

If i do System.gc at the end of the controller everything seems to be fine and slower ofc...I create a lot of object at that call but shouldn't heroku's JVM take care of gc? Also if i schedule gc call periodically don't free memory


Source: (StackOverflow)

Play migrations alternatives [closed]

I am about to start a new project that will use the Play! 2 framework for Scala, probably using Squeryl as ORM (but maybe Slick would be fine too, if it ready in time).

Now, Play! has a feature to upgrade your database using migrations. Unforunately, these migrations are written in SQL. This is not only an inconvenience (I would like to be able to write migrations in Scala) but has two problems

  • first, I need to write migrations on my own. I am used to South, that is able to infer schema migrations by looking at the current and previous definitions of my models;
  • second, it would be very cumbersome to handle data migrations. One may have the need to alter data programmatically, and this may not even be doable in plain SQL.

So, I am looking for an alternative. I was not able to find any migration tool for any Scala ORM that would generate schema migrations automatically, is there any?

The best tool I could find is Scala migrations. Is there a way to make Play! automatically use it in place of its own migration tool?


Source: (StackOverflow)

How to integrate the Scala Squeryl ORB with play 2.0 framework?

I am trying to use Squeryl ORB with play 2.0 framework, but when calling DB.getConnection() during initialization I get:

BadPath: path parameter: Invalid path ' - could not find datasource for defaultdb': Token not allowed in path expression: '-' (you can double-quote this token if you really want it here)

The database configuration looks like this (conf/application.conf):

db.default.url="jdbc:postgresql://localhost/mydb?user=postgres&password=postgres"
db.default.driver=org.postgresql.Driver
db.default.jndiName=defaultdb

And the initializing:

object Global extends GlobalSettings {
  override def onStart(app: Application) {

    SessionFactory.externalTransactionManagementAdapter = Some(() => 
        Some(new Session(
          DB.getConnection("defaultdb", true),
          new PostgreSqlAdapter)))
    ...

Is this the right way to do it? Is it correct to use the db.default.jndiName config value as parameter value to DB.getConnection()?

Or should it be done like this?:

  SessionFactory.concreteFactory = Some(() =>
    Session.create(
      java.sql.DriverManager.getConnection("jdbc:postgresql://..."),
      new PostgreSqlAdapter))

This works, but then I am not able to use the squeryl query objects in the template for iteration, which I hoped would be possible with externalTransactionManagementAdapter.

Update:

I corrected to the following: DB.getConnection("default", true) and removed the db.default.jndiName config. With this I am able to get and use a connection, but the second time getConnection() is called, it throws SQLException: Timed out waiting for a free available connection.

Update 2:

I haven't managed to use externalTransactionManagementAdapter, but concreteFactory works well - as described below.


Source: (StackOverflow)

Session must be bound error using Squeryl

Update: Okay, I fixed the problem I was having, but I'm still not quite sure what I was doing wrong. In any case, I wrote the following method in IRCDB:

def tryit[T](p: => T) = {
    Class.forName("org.h2.Driver") //what's the point in this...?

    SessionFactory.concreteFactory = Some(() =>
        Session.create(java.sql.DriverManager.getConnection("jdbc:h2:~/irc","ScalaIRC",""), new H2Adapter))

    transaction {
        p
    }
}

Then used it like so:

 val query = from(IRCDB.channels)(c => select(c))
 IRCDB.tryit {
     for (r <- query) println("chan: " + r.name)
 }

And it now works. From my understanding, I believed that once the session was created using the SessionFactory, I'd be able to use transaction { ... } anywhere that has the proper import. Apparently, my understanding is incorrect.

If anyone has anything to add please do.


So, I just started using Squeryl for a project I'm working on so this might just be an oversight on my part. So, first the code:

I have the following imports:

import org.squeryl.PrimitiveTypeMode._
import java.sql.Timestamp
import java.sql.DriverManager
import java.util.Date
import org.squeryl.adapters.H2Adapter
import org.squeryl.dsl.{OneToMany, ManyToOne, CompositeKey2}
import org.squeryl._

I have the following table defined:

class ChannelTable(val id: Long, val name : String,
               val p_mode : Boolean, val s_mode : Boolean,
               val i_mode : Boolean, val t_mode : Boolean,
               val n_mode : Boolean, val m_mode : Boolean,
               val key : Option[String]) extends KeyedEntity[Long] {
    def this() = this(0,"", false, false, false, false, false, false, Some(""))

    lazy val bans:OneToMany[ChannelBanTable] = IRCDB.channelToChanBans.left(this)
    lazy val users = IRCDB.channelUsers.left(this)
    lazy val invites = IRCDB.channelInvites.left(this)
}

And the following Schema defined:

object IRCDB extends Schema {
    val channels = table[ChannelTable]

    on(channels)(c => declare(
      c.p_mode defaultsTo(false),
      c.s_mode defaultsTo(false),
      c.i_mode defaultsTo(false),
      c.t_mode defaultsTo(false),
      c.n_mode defaultsTo(false),
      c.m_mode defaultsTo(false),
      c.name is(unique, indexed)
    ))

    def init {
        Class.forName("org.h2.Driver") //what's the point in this...?

        SessionFactory.concreteFactory = Some(() =>
          Session.create(DriverManager.getConnection("jdbc:h2:~/irc","ScalaIRC",""), new H2Adapter))
    }
    def getAllChannels = transaction { from(channels)(c => select(c))}
}

I have been able to insert into the table with the following at the Console:

scala> import db._;import org.squeryl.PrimitiveTypeMode._
import db._
import org.squeryl.PrimitiveTypeMode._
scala> IRCDB.init
scala> transaction { IRCDB.channels.insert(new ChannelTable(0,"#chan_name", false, false, false, false, false, false, None)) }
res3: db.ChannelTable = db.ChannelTable@4

I can confirm with the H2 Console that this does indeed occur. However, when I call IRCDB.getAllChannels (in both the Scala Console and in code) I get the following error:

java.lang.RuntimeException: no session is bound to current thread, a session must be created via Session.create 
and bound to the thread via 'work' or 'bindToCurrentThread'
    at scala.Predef$.error(Predef.scala:58)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:117)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:117)
    at scala.Option.getOrElse(Option.scala:59)
    at org.squeryl.Session$.currentSession(Session.scala:116)
    at org.squeryl.dsl.AbstractQuery.org$squeryl$dsl$AbstractQuery$$_dbAdapter(AbstractQuery.scala:136)
    at org.squeryl.dsl.AbstractQuery$$anon$1.<init>(AbstractQuery.scala:140)
    at org.squeryl.dsl.AbstractQuery.iterator(AbstractQuery.scala:138)
    at scala.collection.IterableLike$class.foreach(IterableLike.scala:79)
    at org.squeryl.dsl.AbstractQuery.foreach(AbstractQuery.scala:27)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:206)
    at org.squeryl.dsl.AbstractQuery.map(AbstractQuery.scala:27)
    at scala.runtime.ScalaRunTime$.inner$1(ScalaRunTime.scala:255)
    at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:258)
    at RequestResult$line7$object$.<init>(<console>:12)
    at RequestResult$line7$object$.<clinit>(<console>)
    at RequestResult$line7$object.scala_repl_result(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
    at scala.util.control.Exception$Catch.apply(Exception.scala:79)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1.apply(Interpreter.scala:980)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1.apply(Interpreter.scala:980)
    at scala.util.control.Exception$Catch.apply(Exception.scala:79)
    at scala.tools.nsc.Interpreter$Request.loadAndRun(Interpreter.scala:979)
    at scala.tools.nsc.Interpreter.loadAndRunReq$1(Interpreter.scala:578)
    at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:597)
    at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:575)
    at scala.tools.nsc.InterpreterLoop.reallyInterpret$1(InterpreterLoop.scala:471)
    at scala.tools.nsc.InterpreterLoop.interpretStartingWith(InterpreterLoop.scala:514)
    at scala.tools.nsc.InterpreterLoop.command(InterpreterLoop.scala:361)
    at scala.tools.nsc.InterpreterLoop.processLine$1(InterpreterLoop.scala:242)
    at scala.tools.nsc.InterpreterLoop.repl(InterpreterLoop.scala:248)
    at scala.tools.nsc.InterpreterLoop.main(InterpreterLoop.scala:558)
    at scala.tools.nsc.InterpreterLoop.main(InterpreterLoop.scala:609)
    at org.jetbrains.plugins.scala.compiler.rt.ConsoleRunner.main(ConsoleRunner.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)

I don't understand why I would be getting this error if I was able to insert rows into the table doing nearly the same way. If I try to execute transaction { from(IRCDB.channels)(c => select(c)) } at the Console I get the same error.


Edit: I've added the full stack trace. Also, I rewrote the getAllChannels function like this:

def getAllChannels = transaction { 
  val ret = from(channels)(c => select(c))
  println("sql: " + ret)
  ret
}

I still receive an error, but it does print the query out first -- I thought this may be useful:

sql: 'QueryExpressionNode[root:1a0d111]:rsm='ResultSetMapper:fdf48d()--
    'FieldSelectElement:ChannelTable1_name
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_i_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_s_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_key
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_n_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_m_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_id
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_t_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'FieldSelectElement:ChannelTable1_p_mode
        org.squeryl.dsl.ast.FieldSelectElement$$anon$3
    'ViewExpressionNode[sample:ChannelTable[16e3f87]]:rsm='ResultSetMapper:442b95($(1->ChannelTable.name:java.lang.String),$(2->ChannelTable.i_mode:java.lang.Boolean),$(3->ChannelTable.s_mode:java.lang.Boolean),$(4->ChannelTable.key:Option[java.lang.String]),$(5->ChannelTable.n_mode:java.lang.Boolean),$(6->ChannelTable.m_mode:java.lang.Boolean),$(7->ChannelTable.id:java.lang.Long),$(8->ChannelTable.t_mode:java.lang.Boolean),$(9->ChannelTable.p_mode:java.lang.Boolean))--*

Select
  ChannelTable1.name as ChannelTable1_name,
  ChannelTable1.i_mode as ChannelTable1_i_mode,
  ChannelTable1.s_mode as ChannelTable1_s_mode,
  ChannelTable1.key as ChannelTable1_key,
  ChannelTable1.n_mode as ChannelTable1_n_mode,
  ChannelTable1.m_mode as ChannelTable1_m_mode,
  ChannelTable1.id as ChannelTable1_id,
  ChannelTable1.t_mode as ChannelTable1_t_mode,
  ChannelTable1.p_mode as ChannelTable1_p_mode
From
  ChannelTable ChannelTable1
java.lang.RuntimeException: no session is bound to current thread, a session must be created via Session.create 
and bound to the thread via 'work' or 'bindToCurrentThread'
    at scala.Predef$.error(Predef.scala:58)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:117)
    at org.squeryl.Session$$anonfun$currentSession$1.apply(Session.scala:117)
    at scala.Option.getOrElse(Option.scala:59)
    at org.squeryl.Session$.currentSession(Session.scala:116)
    at org.squeryl.dsl.AbstractQuery.org$squeryl$dsl$AbstractQuery$$_dbAdapter(AbstractQuery.scala:136)
    at org.squeryl.dsl.AbstractQuery$$anon$1.<init>(AbstractQuery.scala:140)
    at org.squeryl.dsl.AbstractQuery.iterator(AbstractQuery.scala:138)
    at scala.collection.IterableLike$class.foreach(IterableLike.scala:79)
    at org.squeryl....

Source: (StackOverflow)

quote table names in squeryl

I have a table named group in a mysql db. When I map this table to squeryl I get SQL syntax errors since the table name group is not quoted (should be select * from `group`).

Is there any way I can tell squeryl to quote certain table names?


Source: (StackOverflow)

Schema definition in Squeryl using Scala Case Classes

While reading http://squeryl.org/schema-definition.html page of Squeryl project, I noticed case classes are rarely use in the schema definitions. I was wondering if using case classes to model schema definitions is not recommended ? I would use case classes for pattern matching ...


Source: (StackOverflow)

Persisting Collections with Squeryl

How can I persist a collections field (e.g. List[String] or Set[Int]) with Squeryl? What's the best way to encode it such that Squeryl won't create an association table?


Source: (StackOverflow)

How to make Squeryl work with the Play! Framework?

I'm trying to learn how to make a simple database app with Play and Squeryl. I've made the Tasks app from the Play tutorial, but I want to change the model / schema so that it uses Squeryl instead of Anorm. I've been looking at different tutorials, examples and answers, but I haven't really figured out how to do this.

So, given the source code from the Play Tutorial (ScalaTodoList); how do I proceed to make it work with Squeryl?

More specifically:

  • How do I implement the all(), create(), and delete() methods in my model? (I'd like to use auto-incrementing ID's for the Tasks)
  • Which database adapter to use is currently hard coded in Build.scala and Global.scala (see below). How can I make it such that it automatically uses H2 for dev/testing and Postgres on Heroku, like it does for Anorm in the Play tutorial?
  • How do I make sure that it automatically creates my tables?

This is what I've done thus far

I've completed the Play ScalaTodoList Tutorial.

In project/Build.scala, object ApplicationBuild, I've added the dependencies:

// From the "Squeryl Getting Started tutorial"
val posgresDriver = "postgresql" % "postgresql" % "8.4-702.jdbc4"
val h2 = "com.h2database" % "h2" % "1.2.127"

// From the "Squeryl Getting Started tutorial"
libraryDependencies ++= Seq(
  "org.squeryl" %% "squeryl" % "0.9.5",
  h2
)

// From the Play tutorial
val appDependencies = Seq(
  // Add your project dependencies here,
  "org.squeryl" %% "squeryl" % "0.9.5", // Copied from above so that it compiles (?)
  "postgresql" % "postgresql" % "8.4-702.jdbc4"
)

added app/Global.scala (taken from the SO answer mentioned above, just changed the adapter to H2):

import play.db.DB
import play.api.Application
import play.api.GlobalSettings
import org.squeryl._
import org.squeryl.adapters._

object Global extends GlobalSettings {

  override def onStart(app: Application): Unit =
  {
    SessionFactory.concreteFactory = Some(
      () => Session.create(DB.getDataSource().getConnection(),
        dbAdapter));
  }

  override def onStop(app: Application): Unit =
  {
  }

  val dbAdapter = new H2Adapter(); // Hard coded. Not good.

  }

in app/models/Task.scala I've added imports and removed the Anorm implemetations in all(), create(), and delete(). The controller from the Play tutorial expects the all() method to return List[Task].

import org.squeryl.PrimitiveTypeMode._
import org.squeryl.Schema
import org.squeryl.annotations.Column

case class Task(id: Long, label: String)

object Task extends Schema {
  val tasks = table[Task] // Inspired by Squeryl tutorial

  def all(): List[Task] = {
          List[Task]() // ??
  }

  def create(label: String) {
// ??
  }

  def delete(id: Long) {
// ??
  }
}

The rest of the files are left as they were at the end of the Play tutorial.


Source: (StackOverflow)

How to define a m:n relation with additional attributes in Squeryl?

Given a legacy database with a m:n relation and some additional attributes for the relation, how can this defined with squeryl. At the end the tables should look like this:


   +--------------+      +---------------+      +----------------+
   | TableA       |      | Rel_A_B       |      | TableB         |
   +--------------+ ____ +---------------+ ____ +----------------+
   | id: Int      |      | tableA: int   |      | compkey_1: int |
   | (more attrs) |      | tableB_1: int |      | compkey_2: int |
   +--------------+      | tableB_2: int |      | (more attrs)   |
                         | value: Varchar|      +----------------+
                         | date: Date    |
                         +---------------+

Theres no problem in defining the three tables manually with squeryl. However, as far as I understand the documentation at the moment (0.9.4) there is no possibility to define a many-to-many relationship with additional attributes for the relation.

That's why I defined three tables and two one-to-many relations:


// TableA
class TableA(val id: Int, ...) extends KeyedEntity[Int] {
    def this() = this(0, ...)
}

// TableB
class TableB(val compkey1: Int, val compkey2: Int, ...) 
        extends KeyedEntity[CompositeKey2[Int, Int]] {

    def id = CompositeKey2(compkey1, compkey2)
}

// Rel_A_B
class RelAB(val tabA: Int, val tabB1: Int, val tabB2: Int, val value: String, 
            val date: Date) extends KeyedEntity[CompositeKey3[Int, Int, Int]] {

    def id = CompositeKey3(tabA, tabB1, tabB2)
}

It's easy to define the relation between TableA and RelAB. I use an ordinary one-to-many relation:


val relA =
    oneToManyRelation(tableA, relAB).
    via((a, r) => a.id === r.tableA)

But I don't see a way to define the second relation. I already tried to define an additional composite value on the relation table (named compkeyB) containing just the columns from tableB and compare it to the composite key of tableB, but this doesn't work:


val relB =
    oneToManyRelation(tableB, relAB).
    via((b, r) => b.id === r.compkeyB)

It throws a "type mismatch" exception:

found   : org.squeryl.dsl.ast.LogicalBoolean
required: org.squeryl.dsl.ast.EqualityExpression

Any ideas how to solve this?


Source: (StackOverflow)

Squeryl session management with 'using'

I'm learning Squeryl and trying to understand the 'using' syntax but can't find documentation on it.

In the following example two databases are created, A contains the word Hello, and B contains Goodbye. The intention is to query the contents of A, then append the word World and write the result to B.

Expected console output is Inserted Message(2,HelloWorld)

object Test {
    def main(args: Array[String]) {
        Class.forName("org.h2.Driver");
        import Library._

        val sessionA = Session.create(DriverManager.getConnection(
                "jdbc:h2:file:data/dbA","sa","password"),new H2Adapter)
        val sessionB = Session.create(DriverManager.getConnection(
                "jdbc:h2:file:data/dbB","sa","password"),new H2Adapter)

        using(sessionA){
            drop; create
            myTable.insert(Message(0,"Hello"))
        }
        using(sessionB){
            drop; create
            myTable.insert(Message(0,"Goodbye"))
        }

        using(sessionA){
            val results = from(myTable)(s => select(s))//.toList

            using(sessionB){
                results.foreach(m => {
                    val newMsg = m.copy(msg = (m.msg+"World"))
                    myTable.insert(newMsg)
                    println("Inserted "+newMsg)
                })
            }
        }
    }

    case class Message(val id: Long, val msg: String) extends KeyedEntity[Long]
    object Library extends Schema { val myTable = table[Message] }
}

As it stands, the code prints Inserted Message(2,GoodbyeWorld), unless the toList is added on the end of the val results line.

Is there some way to bind the results query to use sessionA even when evaluated inside the using(sessionB)? This seems preferable to using toList to force the query to evaluate and store the contents in memory.

Update

Thanks to Dave Whittaker's answer, the following snippet fixes it without resorting to 'toList' and corrects my understanding of both 'using' and the running of queries.

val results = from(myTable)(s => select(s))

using(sessionA){            
    results.foreach(m => {
        val newMsg = m.copy(msg = (m.msg+"World"))
        using(sessionB){myTable.insert(newMsg)}
        println("Inserted "+newMsg)
    })
}

Source: (StackOverflow)

value === is not a member of type parameter TKey (using Squeryl)

I'm trying to write a simple BaseDao class using the excellent squeryl ORM framework.

However I've come across a problem when using generic typed keys. I get a compile error when I try and use the '===' operator in my generic BaseDao class. The compile error is: value === is not a member of type parameter TKey

My dao class with its troublesome method is defined as:

import org.squeryl.PrimitiveTypeMode._
import org.squeryl._

abstract class BaseDao[TKey, T <: BaseEntity[TKey]](val table: Table[T]) {

  def delete(entity: T) : Boolean = {
    table.deleteWhere(record => record.id === entity.id) //This is where I get the compile error
  }
}

BaseEntity is defined as:

abstract class BaseEntity[TKey] extends KeyedEntity[TKey]

I import PrimitiveTypeMode in my Dao class too... My first though was that TKey needed to be constrained to whatever the === operator was constrained to, but on looking at the source, there doesn't seem to be any explicit constraints around the operator, so I'm a bit lost.

The operator is defined in the source of squeryl here: https://github.com/max-l/Squeryl/blob/master/src/main/scala/org/squeryl/dsl/TypedExpression.scala


Source: (StackOverflow)

Memory leaks when recreating Squeryl in-memory database

I'm writing a simple Scala & Squeryl application. For test purposes, each time I run 'test' in sbt, an in-memory H2 db is created and populated with test data. After each run I can see that memory usage of java.exe (inside which sbt is running) in the Task Manager increases until after 4 or 5 runs it crashes with OutOfMemoryError. Am I missing something that explicitly releases memory used by H2 or Squeryl? By now, I use only Session.create and then Persistence.create. Here is an excerpt from my code:

object Persistence extends Schema {
  val documents = table[IncomeEntity]
  val positions = table[Position]
  val documentToPositions = oneToManyRelation(documents, positions).via(_.id === _.id_income)
}

class PersistenceTests extends FunSuite with BeforeAndAfterAll {

  override protected def beforeAll() {
    Class.forName("org.h2.Driver")
    SessionFactory.concreteFactory = Some(
      () => Session.create(DriverManager.getConnection("jdbc:h2:mem:test"), new H2Adapter)
    )
  }

  test("DDL") {
    transaction {
      Persistence.create
      assert(Persistence.documents.size == 0)
      assert(Persistence.positions.size == 0)
    }
  } 

  test("Insert") {
    transaction {
      Persistence.create
      (1 to 100) map { _ => IncomeMapper.save(new Income) }
      assert(Persistence.documents.size == 100)
    }
  }
}

The messages I get are simply the following:

[info] PersistenceTests:
sbt appears to be exiting abnormally.
  The log file for this session is at C:\Users\Oleg\AppData\Local\Temp\sbt7320472784033855835.log
java.lang.OutOfMemoryError: PermGen space
Error during sbt execution: java.lang.OutOfMemoryError: PermGen space

Source: (StackOverflow)

REST (Squeryl/Akka/Spray) - Very low throughput

I am currently building my first REST API, based around an RSS aggregator. I have it implemented using one of two traits, either a MemoryBasedDB or PostgresDB. On each access to the root url, it will make an asynchronous call out to the feed to grab the newest articles, and return that as an XML string for parsing. After parsing, it is persisted in the database as an Article object.

Functionally, it's fine either way for me. However, when load testing with weighttp or gatling it will fail under 1k requests/1k concurent users using Postgres with the following:

In weighttp:

error: read() failed: Connection reset by peer (104)

And in my server logs:

final [WARN] [09/21/2014 14:45:27.224] [on-spray-can-akka.actor.default-dispatcher-36] [akka://on-spray-can/user/IO-HTTP/listener-0/523] Configured registration timeout of 1 second expired, stopping

I believe it has something to do with the way my queries are laid out. They are blocking and as each actor has to wait for a response, the load behind them piles up higher and higher to the point of failure (timeout). However, in my research I have only been able to find this asynchronous driver for postgres which is currently incompatible with Squeryl (to my understanding).

How can I make DB access faster? Currently I am achieving ~10-15req/s using Postgres, and ~400req/s using in-memory persistence.

My model:

case class Article(id: Option[String], idint: Option[Int], title: String, author: String, published: String, updated: String, `abstract`: Option[String], content: Option[String], link: Option[String])

My queries:

trait PostgresDB extends Schema {

  val articles = table[Article]("articles")
  on(articles)(e => declare(e.idint is(unique)))

  def create(x: Article) = inTransaction {
      articles.insert(x)
  }

  def getAll: Set[Article] = inTransaction {
      from(articles)(article => select(article)).toSet
  }

  def getArticle(x: Int) = inTransaction {
      from(articles)(article => where(article.idint === Some(x)) select(article)).toList(0)
  }

  def printy = transaction {
      articles.schema.printDdl(println(_))
  }
}

So far I have tried:

  • Implementing C3P0 for connection pooling. No real change.
  • Adjusting postgresql.conf for performance. Small positive change.
  • Adjusting application.conf for spray/akka for performance. Small positive change.

Relevant info:

  • Kernel:
    • Linux 3.13.0-33-generic #58-Ubuntu SMP Tue Jul 29 16:45:05 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
  • Postgres 9.3
  • Scala 2.10.4
  • Spray 1.3.1
  • Akka 2.3.5

Source: (StackOverflow)