1

I've created an REST api in scala using AKKA-HTTP, spray-json and Slick. For Authorization of route, I've used oauth2.

DAO to retrieve Data(Using Plain SQL):

def getAllNotes: Future[Seq[UserEntity]] = {
    implicit val getUserResult = GetResult(r => UserEntity(r.<<, r.<<, r.<<, r.<<, r.<<, r.<<))
    query(s"select id, email, password,created_at, updated_at, deleted_at from users", getUserResult)
}

DAO to retrieve Data(Slick Table):

def getAll(): Future[Seq[A]] = {
    db.run(tableQ.result)
}

Here's the part of routing:

val route: Route = pathPrefix("auth") {
    get {
        path("tests") {
            complete(userDao.getAll.map(u => u.toList))
        } ~
        path("test") {
            complete(userDao.getAllNotes.map(u => u.toList))
        } ~
        path("testUsers") {
            baseApi(userDao.getAllNotes)
        } ~
        path("users") {
            baseApi(userDao.getAll())
        }
    }
}

implicit def baseApi(f: ToResponseMarshallable): Route = {
    authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator) { auth =>
        pathEndOrSingleSlash {
            complete(f)
        }
    }
}

Functionally, all routes are working as intended but the performance seems to be degrading when OAUTH2 and Slick Tables are used for getting data.

The respective results of above routes:

1. "users"     => 10 request per second: OAUTH2: YES, Slick Table: YES
2. "testUsers" => 17 request per second: OAUTH2: YES, Slick Table: NO
3. "tests"     => 500 request per second: OAUTH2: NO, Slick Table: YES
4. "test"      => 5593 request per second: OAUTH2: NO, Slick Table: NO

My Problem

How can I optimize the REST request using OAUTH2 and Slick Table?

Would it be good practice if I used PLAIN SQL instead of Slick tables and Joins in all cases?

Sujit Baniya
  • 895
  • 9
  • 27

2 Answers2

0

It seems that enabling Oauth2 has the biggest impact, however the overhead added by akka http is negligible compared to the network/service call done on oauth2Authenticator. Even if it is done in async manner you still need to configure correctly the execution context (good read Explaining AKKA Thread Pool Execturor Config parameters).

In regards to the Slick part it seems that you declare the implicit row mapper on each request (can be a class val property). Take a look at the Compiled Queries and make sure that you allocate enough jdbc connections in your db connection pool configuration.

In any case the whole concept of this test does not seem very useful, one should have the minimal requirements(ex: min 100 requests/second) and then start building on top of that.

Ion Cojocaru
  • 2,583
  • 15
  • 16
  • By implicit row mapper on each request, do you mean `userDao.getAll.map(u => u.toList)`. Any example or code snippet would be good enough to analyze. :) – Sujit Baniya Feb 01 '17 at 04:39
  • I was refering to the `implicit val getUserResult` in `getAllNotes` method, that can be declared at the class level instead. – Ion Cojocaru Feb 01 '17 at 10:01
  • I replaced the implicit and the achievement I received is `5926 rps`. And How could I use Compiled in `getNotes()`? I tried db.run(Compiled(tableQ)) but that generated errors – Sujit Baniya Feb 01 '17 at 11:42
  • in the `getAllNotes` you use a `query` function that takes a string and a row mapper, I assume that in it you use something like `db.run(sql(plainQuery))`, since you query is without parameters you can also declare it at the class level as val notesQuery=Compile(sql"select .. from users")) and then in `getAllNotes` use `db.run(notesQuery)`... – Ion Cojocaru Feb 02 '17 at 09:22
  • do you have any other implementation idea for OAuth2 in Scala – Sujit Baniya Feb 13 '17 at 07:26
0

Part regarding Slick has been answered multiple times. Most recent answer is here: Cache Slick DBIO Actions

This should dramatically improve response times for plain Slick version.

I can't help you with OAUTH2 though :/

Community
  • 1
  • 1
Paul Dolega
  • 2,446
  • 14
  • 23