Ver Fonte

Scala with Akka HTTP with Circe and Slick and Postgres (#4395)

* initial commit

* fix .sbtopts

* experiment with Dockerfile alpine JDK 11 etc.

* since alpine with JDK 11 is not yet available use hseeberger's image

* first impl

* change main class

* found the postgres ;)

* working version

* fix README.md

* rename project internally to match official name

* make configuration of individual route dispatchers flexible and for starters use one for all as he routes are probably not called all at once

* move akka-http-slick-postgres directory under frameworks/Scala/akka-http

* move akka-http sources under frameworks/Scala/akka-http/akka-http

* move the akka-http dockerfiles to frameworks/Scala/akka-http

* adjust paths

* create overall benchmark_config.json for akka-http

* fix some definitions

* try to improve Docker image caching so that when not changing build.sbt or anything relevant under project won't discard some things

* further improvements

* small fix

* some dependency version updates in akka-http default test
Sven Ludwig há 6 anos atrás
pai
commit
eb8043f8f7
68 ficheiros alterados com 1363 adições e 14 exclusões
  1. 24 0
      frameworks/Scala/akka-http/akka-http-slick-postgres.dockerfile
  2. 36 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/.dockerignore
  3. 34 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/.gitignore
  4. 5 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/.sbtopts
  5. 12 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/.scalafmt.conf
  6. 52 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/README.md
  7. 147 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/build.sbt
  8. 1 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/project/build.properties
  9. 7 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/project/plugins.sbt
  10. 84 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/application.conf
  11. 38 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/logback.xml
  12. 0 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/templates/fortunes.mustache
  13. 41 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/ApiRoutes.scala
  14. 101 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/ApiSupervisor.scala
  15. 30 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/AppConfig.scala
  16. 40 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/Main.scala
  17. 22 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/CustomPostgresProfile.scala
  18. 24 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseConfiguration.scala
  19. 6 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseRepository.scala
  20. 26 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseRepositoryLoader.scala
  21. 15 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/Fortune.scala
  22. 8 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRepository.scala
  23. 21 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRepositoryModule.scala
  24. 53 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRoute.scala
  25. 19 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneTable.scala
  26. 96 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/util/Deciders.scala
  27. 15 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/util/SameThreadDirectExecutor.scala
  28. 21 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/DbRoute.scala
  29. 15 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/Hello.scala
  30. 16 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/JsonRoute.scala
  31. 17 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/PlainTextRoute.scala
  32. 45 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/QueriesRoute.scala
  33. 49 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/UpdateRoute.scala
  34. 15 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/World.scala
  35. 18 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRepository.scala
  36. 27 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRepositoryModule.scala
  37. 22 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRoutes.scala
  38. 18 0
      frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldTable.scala
  39. 21 4
      frameworks/Scala/akka-http/akka-http.dockerfile
  40. 36 0
      frameworks/Scala/akka-http/akka-http/.dockerignore
  41. 34 0
      frameworks/Scala/akka-http/akka-http/.gitignore
  42. 5 0
      frameworks/Scala/akka-http/akka-http/.sbtopts
  43. 6 6
      frameworks/Scala/akka-http/akka-http/build.sbt
  44. 0 0
      frameworks/Scala/akka-http/akka-http/project/Formatting.scala
  45. 1 0
      frameworks/Scala/akka-http/akka-http/project/build.properties
  46. 1 1
      frameworks/Scala/akka-http/akka-http/project/plugins.sbt
  47. 0 0
      frameworks/Scala/akka-http/akka-http/project/project/plugins.sbt
  48. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/resources/application.conf
  49. 12 0
      frameworks/Scala/akka-http/akka-http/src/main/resources/templates/fortunes.mustache
  50. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/App.scala
  51. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Bootstrap.scala
  52. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Infrastructure.scala
  53. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Main.scala
  54. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/RequestMapping.scala
  55. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Templating.scala
  56. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/DataStore.scala
  57. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/MySqlDataStore.scala
  58. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/Fortune.scala
  59. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/World.scala
  60. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/DbHandler.scala
  61. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/FortunesHandler.scala
  62. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/JsonHandler.scala
  63. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/PlaintextHandler.scala
  64. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/QueriesHandler.scala
  65. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/UpdatesHandler.scala
  66. 0 0
      frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/util/RandomGenerator.scala
  67. 27 2
      frameworks/Scala/akka-http/benchmark_config.json
  68. 0 1
      frameworks/Scala/akka-http/project/build.properties

+ 24 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres.dockerfile

@@ -0,0 +1,24 @@
+FROM hseeberger/scala-sbt:8u151-2.12.4-1.1.1
+
+WORKDIR /akka-http-slick-postgres
+
+RUN mkdir project
+COPY akka-http-slick-postgres/project/build.properties project/
+COPY akka-http-slick-postgres/project/plugins.sbt project/
+
+RUN \
+  which sbt && \
+  pwd && \
+  ls -la . && \
+  ls -la project && \
+  sbt sbtVersion
+
+COPY akka-http-slick-postgres/build.sbt akka-http-slick-postgres/.sbtopts akka-http-slick-postgres/.scalafmt.conf ./
+
+RUN sbt update
+
+COPY akka-http-slick-postgres/src src
+
+RUN sbt clean compile stage
+
+CMD ["target/universal/stage/bin/akka-http-slick-postgres", "-Dakka.http.benchmark.postgres.dbhost=tfb-database", "-J-d64", "-J-server", "-J-Xms1g", "-J-Xmx1g", "-J-XX:UseG1GC", "-J-XX:ParallelGCThreads=3", "-J-XX:MetaspaceSize=192M", "-J-XX:MaxMetaspaceSize=192M", "-J-XX:+UseStringDeduplication"]

+ 36 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/.dockerignore

@@ -0,0 +1,36 @@
+.idea/
+*/*.iml
+
+# Created by .ignore support plugin (hsz.mobi)
+### SBT template
+# Simple Build Tool
+# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
+
+target/
+lib_managed/
+src_managed/
+project/boot/
+.history
+.cache
+### Scala template
+**/*.class
+**/*.log
+
+# sbt specific
+.lib/
+dist/*
+**/target*
+project/target
+project/project/target
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+# ENSIME specific
+.ensime_cache/
+.ensime
+
+# our own buffer file
+compare.txt

+ 34 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/.gitignore

@@ -0,0 +1,34 @@
+.idea/
+*/*.iml
+
+# Created by .ignore support plugin (hsz.mobi)
+### SBT template
+# Simple Build Tool
+# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
+
+target/
+lib_managed/
+src_managed/
+project/boot/
+.history
+.cache
+### Scala template
+*.class
+*.log
+
+# sbt specific
+.lib/
+dist/*
+project/project/
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+# ENSIME specific
+.ensime_cache/
+.ensime
+
+# our own buffer file
+compare.txt

+ 5 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/.sbtopts

@@ -0,0 +1,5 @@
+-J-Xms256M
+-J-Xmx768M
+-J-XX:MaxMetaspaceSize=256M
+-Djava.awt.headless=true
+-Djava.net.preferIPv4Stack=true

+ 12 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/.scalafmt.conf

@@ -0,0 +1,12 @@
+# Global default style for scalafmt.
+style = default
+# Other options in addition to the default style.
+align.openParenCallSite    = true
+danglingParentheses        = false
+indentOperator             = spray
+maxColumn                  = 120
+project.excludeFilters     = [".*\\.sbt"]
+project.git                = true
+#rewrite.rules              = [RedundantBraces, RedundantParens, SortImports]
+#spaces.inImportCurlyBraces = true
+#unindentTopLevelOperators  = true

+ 52 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/README.md

@@ -0,0 +1,52 @@
+# akka-http-slick-postgres Benchmarking Test
+
+### Test Type Implementation Source Code
+
+* [JSON](src/main/scala/net/benchmark/akka/http/world/JsonRoute.scala)
+* [PLAINTEXT](src/main/scala/net/benchmark/akka/http/world/PlainTextRoute.scala)
+* [DB](src/main/scala/net/benchmark/akka/http/world/DbRoute.scala)
+* [QUERY](src/main/scala/net/benchmark/akka/http/world/QueriesRoute.scala)
+* [UPDATE](src/main/scala/net/benchmark/akka/http/world/UpdateRoute.scala)
+* [FORTUNES](src/main/scala/net/benchmark/akka/http/fortune/FortuneRoutes.scala)
+
+## Important Libraries
+
+The tests were run with:
+
+* [Akka HTTP](https://doc.akka.io/docs/akka-http/current/)
+* [Akka Streams](https://doc.akka.io/docs/akka/current/stream/)
+* [Slick](http://slick.lightbend.com/)
+* [HikariCP](https://brettwooldridge.github.io/HikariCP/)
+* [Circe](https://circe.github.io/circe/)
+* [Cats](https://github.com/typelevel/cats/)
+* [Scalate](https://scalate.github.io/scalate/)
+
+## Test URLs
+
+### JSON
+
+http://localhost:9339/json
+
+### PLAINTEXT
+
+http://localhost:9339/plaintext
+
+### DB
+
+http://localhost:9339/db
+
+### QUERY
+
+http://localhost:9339/query?queries=
+
+### CACHED QUERY
+
+http://localhost:9339/cached_query?queries=
+
+### UPDATE
+
+http://localhost:9339/update?queries=
+
+### FORTUNES
+
+http://localhost:9339/fortunes

+ 147 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/build.sbt

@@ -0,0 +1,147 @@
+lazy val akkaHttpSlickPostgres =
+  project
+    .in(file("."))
+    .enablePlugins(
+      GitBranchPrompt,
+      GitVersioning,
+      JavaAppPackaging,
+      DockerPlugin,
+      AshScriptPlugin
+    )
+    .settings(settings)
+    .settings(
+      name := "akka-http-slick-postgres",
+      mainClass in Compile := Some("net.benchmark.akka.http.Main"),
+      libraryDependencies ++= Seq(
+        library.akkaSlf4j,
+        library.akkaStream,
+        library.akkaHttp,
+        library.akkaHttpCirce,
+        library.akkaTestkit        % Test,
+        library.akkaHttpTestkit    % Test,
+        library.akkaStreamTestkit  % Test,
+        library.logbackClassic,
+        library.postgresql,
+        library.scalaCheck         % Test,
+        library.scalaTest          % Test,
+        library.scalateCore,
+        library.slick,
+        library.slickPgCore,
+        library.slickHikariCP,
+      ),
+      parallelExecution in Test := true
+    )
+
+lazy val library =
+  new {
+    object Version {
+      val akka              = "2.5.20"
+      val akkaHttp          = "10.1.7"
+      val akkaHttpCirce     = "1.23.0"
+      val logback           = "1.2.3"
+      val postgresql        = "42.2.5"
+      val scalaCheck        = "1.14.0"
+      val scalaTest         = "3.0.5"
+      val scalate           = "1.8.0"
+      val slick             = "3.2.3"
+      val slickPg           = "0.17.0"
+    }
+
+    val akkaSlf4j           = "com.typesafe.akka"            %% "akka-slf4j"                  % Version.akka
+    val akkaHttp            = "com.typesafe.akka"            %% "akka-http"                   % Version.akkaHttp
+    val akkaHttpTestkit     = "com.typesafe.akka"            %% "akka-http-testkit"           % Version.akkaHttp
+    val akkaHttpCirce       = "de.heikoseeberger"            %% "akka-http-circe"             % Version.akkaHttpCirce
+    val akkaStream          = "com.typesafe.akka"            %% "akka-stream"                 % Version.akka
+    val akkaStreamTestkit   = "com.typesafe.akka"            %% "akka-stream-testkit"         % Version.akka
+    val akkaTestkit         = "com.typesafe.akka"            %% "akka-testkit"                % Version.akka
+    val logbackClassic      = "ch.qos.logback"               %  "logback-classic"             % Version.logback
+    val postgresql          = "org.postgresql"               %  "postgresql"                  % Version.postgresql
+    val scalaCheck          = "org.scalacheck"               %% "scalacheck"                  % Version.scalaCheck
+    val scalaTest           = "org.scalatest"                %% "scalatest"                   % Version.scalaTest
+    val scalateCore         = "org.scalatra.scalate"         %% "scalate-core"                % Version.scalate
+    val slick               = "com.typesafe.slick"           %% "slick"                       % Version.slick
+    val slickHikariCP       = "com.typesafe.slick"           %% "slick-hikaricp"              % Version.slick
+    val slickPgCore         = "com.github.tminglei"          %% "slick-pg"                    % Version.slickPg
+  }
+
+lazy val settings =
+  commonSettings ++
+    gitSettings ++
+    packagingSettings ++
+    scalafmtSettings
+
+lazy val commonSettings =
+  Seq(
+    organization := "net.benchmark.akka.http",
+    organizationName := "Akka",
+    scalaVersion := "2.12.4",
+    scalacOptions ++= Seq(
+      "-deprecation",
+      "-encoding",
+      "UTF-8",
+      "-explaintypes",
+      "-feature",
+      "-target:jvm-1.8",
+      "-unchecked",
+      "-Xfatal-warnings",
+      "-Xfuture",
+      "-Xlint",
+      "-Ydelambdafy:method",
+      "-Yno-adapted-args",
+      "-Ypartial-unification",
+      "-Ywarn-numeric-widen",
+      "-Ywarn-unused-import",
+      "-Ywarn-value-discard"
+    ),
+    scalacOptions in (Compile, console) --= Seq("-Xfatal-warnings"), // Relax settings for console
+    scalacOptions in (Test, console) --= Seq("-Xfatal-warnings"), // Relax settings for console
+    javacOptions ++= Seq(
+      "-encoding",
+      "UTF-8",
+      "-source",
+      "1.8",
+      "-target",
+      "1.8"
+    ),
+    javaOptions ++= Seq(
+      "-jvm-debug 5555"
+    ),
+    transitiveClassifiers := Seq("sources"),
+    publishArtifact in (Compile, packageDoc) := false,
+    unmanagedSourceDirectories.in(Compile) := Seq(scalaSource.in(Compile).value),
+    unmanagedSourceDirectories.in(Test) := Seq(scalaSource.in(Test).value),
+    wartremoverWarnings in (Compile, compile) ++= Warts.unsafe
+  )
+
+lazy val gitSettings =
+  Seq(
+    git.useGitDescribe := true
+  )
+
+lazy val packagingSettings =
+  Seq(
+    mappings in Universal += {
+      // we are using the reference.conf as default application.conf
+      // the user can override settings here
+      val conf = (resourceDirectory in Compile).value / "reference.conf"
+      conf -> "conf/application.conf"
+    },
+    scriptClasspath := Seq("../conf/") ++ scriptClasspath.value,
+    daemonUser.in(Docker) := "root",
+    maintainer.in(Docker) := "sourcekick",
+    version.in(Docker) := version.value,
+    dockerBaseImage := "openjdk:jre-alpine",
+    dockerExposedPorts := Seq(8080),
+    dockerExposedVolumes in Docker := Seq("/config"),
+    mappings in Universal += {
+      var appjar = (packageBin in Test).value
+      appjar -> s"lib/${appjar.getName}"
+    }
+  )
+
+lazy val scalafmtSettings =
+  Seq(
+    scalafmtOnCompile := true,
+    scalafmtOnCompile.in(Sbt) := false,
+    scalafmtVersion := "1.5.1"
+  )

+ 1 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/project/build.properties

@@ -0,0 +1 @@
+sbt.version = 1.1.1

+ 7 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/project/plugins.sbt

@@ -0,0 +1,7 @@
+addSbtPlugin("com.typesafe.sbt"   % "sbt-git"             % "1.0.0")
+addSbtPlugin("com.typesafe.sbt"   % "sbt-native-packager" % "1.3.16")
+addSbtPlugin("com.lucidchart"     % "sbt-scalafmt"        % "1.15")
+addSbtPlugin("org.wartremover"    % "sbt-wartremover"     % "2.4.0")
+addSbtPlugin("io.get-coursier"    % "sbt-coursier"        % "1.0.3")
+
+libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25" // Needed by sbt-git

+ 84 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/application.conf

@@ -0,0 +1,84 @@
+akka {
+  loggers                          = [akka.event.slf4j.Slf4jLogger]
+  logging-filter                   = "akka.event.slf4j.Slf4jLoggingFilter"
+  loglevel                         = error
+  log-dead-letters                 = 5
+  log-dead-letters-during-shutdown = on
+  logger-startup-timeout           = 30s
+  daemonic = off
+  jvm-exit-on-fatal-error = on
+  jvm-shutdown-hooks = on
+
+  actor {
+    provider = "local"
+    serialize-messages = off
+    serialize-creators = off
+    allow-java-serialization = off
+
+    default-dispatcher {
+      type = "Dispatcher"
+      executor = "fork-join-executor"
+      fork-join-executor {
+        parallelism-min = 3
+        parallelism-factor = 1.4
+        parallelism-max = 20
+        task-peeking-mode = "FIFO"
+      }
+    }
+
+    debug {
+      lifecycle = off
+      receive   = off
+      unhandled = on
+    }
+  }
+}
+
+akka-http-slick-postgres {
+  # Settings for the REST api server.
+  api {
+    # Listening address
+    address = 0.0.0.0
+    # Listening port
+    port = 9339
+    # The dispatcher that will be used for the routing operations.
+    # See the official documentation at http://doc.akka.io/docs/akka/current/scala/dispatchers.html for details.
+  }
+
+  queries {
+    route-dispatcher-config-path = "akka-http-slick-postgres.custom-routes-dispatcher"
+  }
+
+  updates {
+    route-dispatcher-config-path = "akka-http-slick-postgres.custom-routes-dispatcher"
+  }
+
+  db {
+    route-dispatcher-config-path = "akka-http-slick-postgres.custom-routes-dispatcher"
+  }
+
+  fortunes {
+    route-dispatcher-config-path = "akka-http-slick-postgres.custom-routes-dispatcher"
+  }
+
+  custom-routes-dispatcher {
+    type = "Dispatcher"
+    executor = "fork-join-executor"
+    fork-join-executor {
+      parallelism-min = 3
+      parallelism-factor = 1.4
+      parallelism-max = 20
+      task-peeking-mode = "FIFO"
+    }
+  }
+
+  database {
+    profile = "net.benchmark.akka.http.db.CustomPostgresProfile$"
+    db {
+      url = "jdbc:postgresql://tfb-database:5432/hello_world?user=benchmarkdbuser&password=benchmarkdbpass"
+    }
+    numThreads = 10
+    queueSize = 20000
+    maxConnections = 10
+  }
+}

+ 38 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/logback.xml

@@ -0,0 +1,38 @@
+<configuration>
+  <appender name="STDOUT_AKKA" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
+      <!--pattern>%date{ISO8601} [%X{sourceThread}] %-5level %logger{36} %X{akkaTimestamp} %X{akkaSource} %X{sourceActorSystem} - %msg%n</pattern-->
+    </encoder>
+  </appender>
+
+  <appender name="ASYNC_AKKA" class="ch.qos.logback.classic.AsyncAppender">
+    <appender-ref ref="STDOUT_AKKA" />
+  </appender>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} %-5level %logger{36} - %msg%n</pattern>
+      <!--pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern-->
+    </encoder>
+  </appender>
+
+  <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
+    <appender-ref ref="STDOUT" />
+  </appender>
+
+  <logger name="akka" level="WARN" additivity="false">
+    <appender-ref ref="ASYNC_AKKA"/>
+  </logger>
+
+  <logger name="com.zaxxer.hikari" level="ERROR"/>
+
+  <logger name="slick" level="ERROR"/>
+
+  <logger name="net.benchmark" level="INFO"/>
+
+  <root level="ERROR">
+    <appender-ref ref="ASYNC"/>
+  </root>
+
+</configuration>

+ 0 - 0
frameworks/Scala/akka-http/src/main/resources/templates/fortunes.mustache → frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/resources/templates/fortunes.mustache


+ 41 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/ApiRoutes.scala

@@ -0,0 +1,41 @@
+package net.benchmark.akka.http
+
+import akka.actor.ActorSystem
+import akka.http.scaladsl.model.StatusCodes
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route}
+import net.benchmark.akka.http.db.DatabaseRepositoryLoader
+import net.benchmark.akka.http.fortune.FortuneRoute
+import net.benchmark.akka.http.world.WorldRoutes
+import org.slf4j.{Logger, LoggerFactory}
+
+import scala.concurrent.ExecutionContextExecutor
+
+object ApiRoutes {
+
+  private val log: Logger = LoggerFactory.getLogger(getClass)
+
+  def routes(dbLoader: DatabaseRepositoryLoader,
+             sd: ExecutionContextExecutor,
+             qd: ExecutionContextExecutor,
+             ud: ExecutionContextExecutor,
+             dd: ExecutionContextExecutor,
+             fd: ExecutionContextExecutor)(implicit system: ActorSystem): Route =
+    handleRejections(RejectionHandler.default) {
+      val eh: ExceptionHandler = ExceptionHandler {
+        case ex @ (_: Exception) =>
+          log.error("Error occured.", ex)
+          complete(StatusCodes.InternalServerError)
+      }
+
+      val worldRoutes = new WorldRoutes(dbLoader.loadWorldRepository(), sd, qd, ud, dd)
+      val fortuneRoutes = new FortuneRoute(dbLoader.loadFortuneRepository(), sd, fd)
+
+      handleExceptions(eh) {
+        get {
+          worldRoutes.routes() ~
+          fortuneRoutes.route()
+        }
+      }
+    }
+}

+ 101 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/ApiSupervisor.scala

@@ -0,0 +1,101 @@
+package net.benchmark.akka.http
+
+import akka.actor._
+import akka.http.scaladsl.Http
+import akka.pattern.pipe
+import akka.stream.ActorMaterializer
+import com.typesafe.config.Config
+import net.benchmark.akka.http.ApiSupervisor.ApiMessages
+import net.benchmark.akka.http.db.DatabaseRepositoryLoader
+import net.benchmark.akka.http.util.SameThreadDirectExecutor
+
+import scala.util.Failure
+
+class ApiSupervisor(dbLoader: DatabaseRepositoryLoader, materializer: ActorMaterializer)
+    extends Actor
+    with ActorLogging {
+
+  private val config: Config = context.system.settings.config
+  private val port: Int = config.getInt("akka-http-slick-postgres.api.port")
+  private val address: String = config.getString("akka-http-slick-postgres.api.address")
+
+  implicit val mat: ActorMaterializer = materializer
+  implicit val system: ActorSystem = context.system
+
+  private val sd = SameThreadDirectExecutor.executionContext()
+  private val qd = context.system.dispatchers.lookup(AppConfig.Queries.routeDispatcherConfigPath)
+  private val ud = context.system.dispatchers.lookup(AppConfig.Updates.routeDispatcherConfigPath)
+  private val dd = context.system.dispatchers.lookup(AppConfig.Db.routeDispatcherConfigPath)
+  private val fd = context.system.dispatchers.lookup(AppConfig.Fortunes.routeDispatcherConfigPath)
+
+  @SuppressWarnings(Array("org.wartremover.warts.Any"))
+  override def receive: Receive = {
+    case ApiMessages.Shutdown =>
+      log.info("Received Shutdown command from {}.", sender().path)
+      val _ = context.system.terminate()
+      context.stop(self)
+
+    case ApiMessages.StartApi =>
+      log.info("Received StartApi command from {}.", sender().path)
+
+      import context.dispatcher
+
+      val _ = Http(system).bindAndHandle(ApiRoutes.routes(dbLoader, sd, qd, ud, dd, fd), address, port).pipeTo(self)
+
+      context.become(running(sender()))
+
+    case Terminated(ref) =>
+      log.debug("Received Terminated message from {}.", ref.path)
+  }
+
+  @SuppressWarnings(Array("org.wartremover.warts.Any"))
+  def running(supervisor: ActorRef): Receive = {
+    case Http.ServerBinding(socketAddress) =>
+      log.info("Listening on {}.", socketAddress)
+      supervisor ! ApiMessages.ApiStarted
+
+    case Failure(cause) =>
+      log.error(cause, "Can't bind to {}:{}!", address, port)
+      context.stop(self)
+
+    case ApiMessages.Shutdown =>
+      log.info("Received Shutdown message")
+      context.stop(self)
+  }
+
+}
+
+object ApiSupervisor {
+
+  final val Name: String = "ApiSupervisorActor"
+
+  def props(dbLoader: DatabaseRepositoryLoader, materializer: ActorMaterializer): Props =
+    Props(new ApiSupervisor(dbLoader, materializer))
+
+  /**
+    * A sealed trait for the messages of the actor.
+    */
+  sealed trait ApiMessages
+
+  /**
+    * A companion object for the trait to keep the namespace clean.
+    */
+  object ApiMessages {
+
+    /**
+      * Indicates that the API has been started successfully.
+      */
+    case object ApiStarted extends ApiMessages
+
+    /**
+      * Tell the actor to start the Api.
+      */
+    case object StartApi extends ApiMessages
+
+    /**
+      * Tell the actor to shutdown the actor system.
+      */
+    case object Shutdown extends ApiMessages
+
+  }
+}

+ 30 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/AppConfig.scala

@@ -0,0 +1,30 @@
+package net.benchmark.akka.http
+
+import com.typesafe.config.{Config, ConfigFactory}
+
+object AppConfig {
+
+  val config: Config = ConfigFactory.load()
+
+  object Queries {
+    val routeDispatcherConfigPath: String =
+      config.getString("akka-http-slick-postgres.queries.route-dispatcher-config-path")
+
+  }
+
+  object Updates {
+    val routeDispatcherConfigPath: String =
+      config.getString("akka-http-slick-postgres.updates.route-dispatcher-config-path")
+
+  }
+
+  object Db {
+    val routeDispatcherConfigPath: String = config.getString("akka-http-slick-postgres.db.route-dispatcher-config-path")
+  }
+
+  object Fortunes {
+    val routeDispatcherConfigPath: String =
+      config.getString("akka-http-slick-postgres.fortunes.route-dispatcher-config-path")
+  }
+
+}

+ 40 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/Main.scala

@@ -0,0 +1,40 @@
+package net.benchmark.akka.http
+import akka.actor.{ActorRef, ActorSystem, Terminated}
+import akka.stream.ActorMaterializer
+import com.typesafe.config.Config
+import net.benchmark.akka.http.ApiSupervisor.ApiMessages
+import net.benchmark.akka.http.db.{
+  CustomPostgresProfile,
+  DatabaseConfiguration,
+  DatabaseRepositoryLoader,
+  DatabaseRepositoryLoaderModule
+}
+import net.benchmark.akka.http.util.SameThreadDirectExecutor
+import org.slf4j.{Logger, LoggerFactory}
+import slick.basic.DatabaseConfig
+
+import scala.concurrent.Future
+
+object Main {
+
+  private final val log: Logger = LoggerFactory.getLogger(this.getClass)
+
+  def main(args: Array[String]): Unit = {
+    implicit val system: ActorSystem = ActorSystem("AkkaSlickBenchmarkApp")
+    implicit val mat: ActorMaterializer = ActorMaterializer()
+
+    val config: Config = system.settings.config
+
+    val dbConfig: DatabaseConfig[CustomPostgresProfile] = DatabaseConfiguration.getDefaultDatabaseConfiguration(config)
+    val dbLoader: DatabaseRepositoryLoader = new DatabaseRepositoryLoaderModule(dbConfig)
+
+    val api: ActorRef = system.actorOf(ApiSupervisor.props(dbLoader, mat))
+
+    api ! ApiMessages.StartApi
+
+    val finish: Future[Terminated] = system.whenTerminated
+    finish.onComplete(_ => log.info("akka-http-slick-postgres app terminated!"))(
+      SameThreadDirectExecutor.executionContext())
+  }
+
+}

+ 22 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/CustomPostgresProfile.scala

@@ -0,0 +1,22 @@
+package net.benchmark.akka.http.db
+
+import com.github.tminglei.slickpg._
+import slick.basic.Capability
+import slick.jdbc.JdbcCapabilities
+
+trait CustomPostgresProfile extends ExPostgresProfile with PgArraySupport with PgDateSupport with PgDate2Support {
+
+  // Add back `capabilities.insertOrUpdate` to enable native `upsert` support; for postgres 9.5+
+  override protected def computeCapabilities: Set[Capability] =
+    super.computeCapabilities + JdbcCapabilities.insertOrUpdate
+
+  // IMPORTANT: Do not add a type annotation here or you'll trigger an error. See https://github.com/tminglei/slick-pg/issues/303#issuecomment-252403085
+  override val api = MyAPI
+
+  object MyAPI extends API with ArrayImplicits with SimpleDateTimeImplicits with DateTimeImplicits
+}
+
+/**
+  * The actual postgresql profile useable by the application.
+  */
+object CustomPostgresProfile extends CustomPostgresProfile

+ 24 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseConfiguration.scala

@@ -0,0 +1,24 @@
+package net.benchmark.akka.http.db
+
+import com.typesafe.config.Config
+import slick.basic.DatabaseConfig
+
+object DatabaseConfiguration {
+
+  /**
+    * Return a slick database configuration which is defined in the given config
+    * at the provided path.
+    *
+    * @param path   A path in the configuration at which the database is defined.
+    * @param config A configuration.
+    * @return A slick database configuration.
+    */
+  def getDatabaseConfiguration(path: String)(config: Config): DatabaseConfig[CustomPostgresProfile] = {
+    DatabaseConfig.forConfig[CustomPostgresProfile](path, config)
+  }
+
+  // Load the database configuration from the default path.
+  val getDefaultDatabaseConfiguration: Config => DatabaseConfig[CustomPostgresProfile] = getDatabaseConfiguration(
+    "akka-http-slick-postgres.database")
+
+}

+ 6 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseRepository.scala

@@ -0,0 +1,6 @@
+package net.benchmark.akka.http.db
+
+/**
+  * A base trait for database repositories. Every repository must extend this trait.
+  */
+trait DatabaseRepository extends Product with Serializable

+ 26 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/db/DatabaseRepositoryLoader.scala

@@ -0,0 +1,26 @@
+package net.benchmark.akka.http.db
+
+import net.benchmark.akka.http.fortune.{FortuneRepository, FortuneRepositoryModule}
+import net.benchmark.akka.http.world.{WorldRepository, WorldRepositoryModule}
+import slick.basic.DatabaseConfig
+
+trait DatabaseRepositoryLoader {
+
+  def close(): Unit
+
+  def loadWorldRepository(): WorldRepository
+
+  def loadFortuneRepository(): FortuneRepository
+
+}
+
+final class DatabaseRepositoryLoaderModule(dbConfig: DatabaseConfig[CustomPostgresProfile])
+    extends DatabaseRepositoryLoader {
+
+  override def close(): Unit = dbConfig.db.close()
+
+  override def loadWorldRepository(): WorldRepository = new WorldRepositoryModule(dbConfig)
+
+  override def loadFortuneRepository(): FortuneRepository = new FortuneRepositoryModule(dbConfig)
+
+}

+ 15 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/Fortune.scala

@@ -0,0 +1,15 @@
+package net.benchmark.akka.http.fortune
+import io.circe.{Decoder, Encoder}
+
+object Fortune {
+
+  implicit val decodeFortune: Decoder[Fortune] =
+    Decoder.forProduct2("id", "message")(Fortune.apply)
+
+  implicit val encodeFortune: Encoder[Fortune] =
+    Encoder.forProduct2("id", "message")(v => (v.id, v.message))
+
+  def tupled = (this.apply _).tupled
+}
+
+case class Fortune(id: Int, message: String)

+ 8 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRepository.scala

@@ -0,0 +1,8 @@
+package net.benchmark.akka.http.fortune
+import slick.basic.DatabasePublisher
+
+trait FortuneRepository {
+
+  def all(): DatabasePublisher[Fortune]
+
+}

+ 21 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRepositoryModule.scala

@@ -0,0 +1,21 @@
+package net.benchmark.akka.http.fortune
+
+import net.benchmark.akka.http.db.CustomPostgresProfile
+import net.benchmark.akka.http.db.CustomPostgresProfile.api._
+import slick.basic.{DatabaseConfig, DatabasePublisher}
+import slick.jdbc.{ResultSetConcurrency, ResultSetType}
+
+class FortuneRepositoryModule(val dbConfig: DatabaseConfig[CustomPostgresProfile]) extends FortuneRepository {
+
+  private val db = dbConfig.db
+
+  private val fortunes = FortuneTable.fortuneTableQuery
+
+  override def all(): DatabasePublisher[Fortune] = {
+    db.stream(
+      fortunes.result.withStatementParameters(rsType = ResultSetType.ForwardOnly,
+                                              rsConcurrency = ResultSetConcurrency.ReadOnly,
+                                              fetchSize = 100))
+  }
+
+}

+ 53 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneRoute.scala

@@ -0,0 +1,53 @@
+package net.benchmark.akka.http.fortune
+
+import akka.NotUsed
+import akka.actor.ActorSystem
+import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
+import akka.http.scaladsl.model.HttpCharsets.`UTF-8`
+import akka.http.scaladsl.model.HttpEntity
+import akka.http.scaladsl.model.MediaTypes.`text/html`
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.Route
+import akka.stream.ActorMaterializer
+import akka.stream.scaladsl.{Sink, Source}
+import net.benchmark.akka.http.util.Deciders
+import org.fusesource.scalate.TemplateEngine
+import slick.basic.DatabasePublisher
+
+import scala.concurrent.{ExecutionContextExecutor, Future}
+
+class FortuneRoute(fr: FortuneRepository, sd: ExecutionContextExecutor, fd: ExecutionContextExecutor)(
+    implicit val system: ActorSystem) {
+
+  private val te = new TemplateEngine()
+  private val fmat: ActorMaterializer = ActorMaterializer(Deciders.resumingMat("fmat"))
+
+  private implicit lazy val fm: ToEntityMarshaller[Seq[Fortune]] = {
+    val fortunesTemplate = te.load("/templates/fortunes.mustache")
+    Marshaller.opaque { fortunes =>
+      HttpEntity(
+        contentType = `text/html`.withCharset(`UTF-8`),
+        string = te.layout("", fortunesTemplate, Map("fortunes" -> fortunes))
+      )
+    }
+  }
+
+  private def source(p: DatabasePublisher[Fortune]): Source[Fortune, NotUsed] = {
+    Source
+      .fromPublisher(p)
+      .prepend(Source.single(Fortune(0, "Additional fortune added at request time.")))
+  }
+
+  @SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
+  def route(): Route = {
+    path("fortunes") {
+      withExecutionContext(fd) {
+        complete(
+          source(fr.all())
+            .runWith(Sink.seq[Fortune])(fmat)
+            .flatMap(s => Future.successful(s.sortBy(_.message)))(sd))
+      }
+    }
+  }
+
+}

+ 19 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/fortune/FortuneTable.scala

@@ -0,0 +1,19 @@
+package net.benchmark.akka.http.fortune
+
+import net.benchmark.akka.http.db.CustomPostgresProfile.api._
+
+object FortuneTable {
+
+  val fortuneTableQuery: TableQuery[FortuneTable] = TableQuery[FortuneTable]
+
+}
+
+class FortuneTable(tag: Tag) extends Table[Fortune](tag, "Fortune") {
+
+  def id = column[Int]("id", O.PrimaryKey)
+
+  def message = column[String]("message")
+
+  def * = (id, message) <> (Fortune.tupled, Fortune.unapply)
+
+}

+ 96 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/util/Deciders.scala

@@ -0,0 +1,96 @@
+package net.benchmark.akka.http.util
+import akka.actor.ActorSystem
+import akka.event.Logging
+import akka.stream.{ActorAttributes, ActorMaterializerSettings, Attributes, Supervision}
+import org.slf4j.{Logger, LoggerFactory}
+
+object Deciders {
+
+  def stoppingMat(name: String)(implicit system: ActorSystem): ActorMaterializerSettings = {
+    ActorMaterializerSettings(system)
+      .withSupervisionStrategy(Deciders.StoppingDecider.stoppingDecider(s"materializer_$name"))
+  }
+
+  def stopping(name: String): Attributes = {
+    ActorAttributes.supervisionStrategy(Deciders.StoppingDecider.stoppingDecider(s"stage_$name"))
+  }
+
+  def restartingMat(name: String)(implicit system: ActorSystem): ActorMaterializerSettings = {
+    ActorMaterializerSettings(system)
+      .withSupervisionStrategy(Deciders.RestartingDecider.restartingDecider(s"materializer_$name"))
+  }
+
+  def restarting(name: String): Attributes = {
+    ActorAttributes.supervisionStrategy(Deciders.RestartingDecider.restartingDecider(s"stage_$name"))
+  }
+
+  def resumingMat(name: String)(implicit system: ActorSystem): ActorMaterializerSettings = {
+    ActorMaterializerSettings(system)
+      .withSupervisionStrategy(Deciders.ResumingDecider.resumingDecider(s"materializer_$name"))
+  }
+
+  def resuming(name: String): Attributes = {
+    ActorAttributes.supervisionStrategy(Deciders.ResumingDecider.resumingDecider(s"stage_$name"))
+  }
+
+  val logLevels: Attributes = Attributes.logLevels(
+    onElement = Logging.DebugLevel,
+    onFinish = Logging.InfoLevel,
+    onFailure = Logging.WarningLevel
+  )
+
+  private object StoppingDecider {
+
+    private val log: Logger =
+      LoggerFactory.getLogger(StoppingDecider.getClass.getName)
+
+    def stoppingDecider(name: String): Function[Throwable, Supervision.Directive] = {
+      val loggingStoppingDecider: Supervision.Decider = {
+        case t: Throwable =>
+          log.error(name + " - Throwable during streaming. Stopping.", t)
+          Supervision.Stop
+        case _ =>
+          log.error(name + " - Unexpected case!! Stopping.")
+          Supervision.Stop
+      }
+      loggingStoppingDecider
+    }
+  }
+
+  private object RestartingDecider {
+
+    private val log: Logger =
+      LoggerFactory.getLogger(RestartingDecider.getClass.getName)
+
+    def restartingDecider(name: String): Function[Throwable, Supervision.Directive] = {
+      val loggingRestartingDecider: Supervision.Decider = {
+        case t: Throwable =>
+          log.error(name + " - Throwable during streaming. Restarting.", t)
+          Supervision.Restart
+        case _ =>
+          log.error(name + " - Unexpected case!! Stopping.")
+          Supervision.Stop
+      }
+      loggingRestartingDecider
+    }
+  }
+
+  private object ResumingDecider {
+
+    private val log: Logger =
+      LoggerFactory.getLogger(ResumingDecider.getClass.getName)
+
+    def resumingDecider(name: String): Function[Throwable, Supervision.Directive] = {
+      val loggingResumingDecider: Supervision.Decider = {
+        case t: Throwable =>
+          log.error(name + " - Throwable during streaming. Resuming.", t)
+          Supervision.Resume
+        case _ =>
+          log.error(name + " - Unexpected case!! Stopping.")
+          Supervision.Stop
+      }
+      loggingResumingDecider
+    }
+  }
+
+}

+ 15 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/util/SameThreadDirectExecutor.scala

@@ -0,0 +1,15 @@
+package net.benchmark.akka.http.util
+
+import java.util.concurrent.Executor
+
+import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
+
+object SameThreadDirectExecutor extends Executor {
+
+  def executionContext(): ExecutionContextExecutor = {
+    ExecutionContext.fromExecutor(this)
+  }
+
+  override def execute(command: Runnable): Unit = command.run()
+
+}

+ 21 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/DbRoute.scala

@@ -0,0 +1,21 @@
+package net.benchmark.akka.http.world
+import akka.http.scaladsl.server.Directives.{complete, path, withExecutionContext}
+import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
+
+import scala.concurrent.ExecutionContextExecutor
+
+class DbRoute(wr: WorldRepository, dd: ExecutionContextExecutor) {
+
+  private def rand(): Int = {
+    java.util.concurrent.ThreadLocalRandom.current().nextInt(10000) + 1
+  }
+
+  def route() = {
+    path("db") {
+      withExecutionContext(dd) {
+        complete(wr.require(rand()))
+      }
+    }
+  }
+
+}

+ 15 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/Hello.scala

@@ -0,0 +1,15 @@
+package net.benchmark.akka.http.world
+
+import io.circe.{Decoder, Encoder}
+
+object Hello {
+
+  implicit val decodeWorld: Decoder[Hello] =
+    Decoder.forProduct1("message")(Hello.apply)
+
+  implicit val encodeWorld: Encoder[Hello] =
+    Encoder.forProduct1("message")(v => v.message)
+
+}
+
+case class Hello(message: String)

+ 16 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/JsonRoute.scala

@@ -0,0 +1,16 @@
+package net.benchmark.akka.http.world
+import akka.http.scaladsl.server.Directives.{complete, path}
+import akka.http.scaladsl.server.Route
+import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
+
+object JsonRoute {
+
+  private val msg = "Hello, World!"
+
+  def route: Route = {
+    path("json") {
+      complete(Hello(msg))
+    }
+  }
+
+}

+ 17 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/PlainTextRoute.scala

@@ -0,0 +1,17 @@
+package net.benchmark.akka.http.world
+import akka.http.scaladsl.model.HttpCharsets.`UTF-8`
+import akka.http.scaladsl.model.{HttpEntity, HttpResponse, MediaType}
+import akka.http.scaladsl.server.Directives.{complete, path}
+import akka.http.scaladsl.server.Route
+
+object PlainTextRoute {
+
+  private val pt = HttpResponse(
+    entity = HttpEntity(MediaType.customWithFixedCharset("text", "plain", `UTF-8`), "Hello, World!"))
+
+  def route: Route =
+    path("plaintext") {
+      complete(pt)
+    }
+
+}

+ 45 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/QueriesRoute.scala

@@ -0,0 +1,45 @@
+package net.benchmark.akka.http.world
+import akka.NotUsed
+import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.Route
+import akka.stream.scaladsl.Source
+import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
+
+import scala.concurrent.ExecutionContextExecutor
+import scala.util.Try
+
+class QueriesRoute(wr: WorldRepository, qd: ExecutionContextExecutor) {
+
+  implicit private val jss: JsonEntityStreamingSupport =
+    EntityStreamingSupport.json().withParallelMarshalling(5, unordered = true)
+
+  private def rand(i: Int): Int = {
+    val _ = i
+    java.util.concurrent.ThreadLocalRandom.current().nextInt(10000) + 1
+  }
+
+  private def parse(pn: Option[String]): Int = {
+    pn.fold(Try(1))(s => Try(s.toInt)).getOrElse(1).min(500).max(1)
+  }
+
+  private def source(n: Int): Source[World, NotUsed] = {
+    Source(1 to n)
+      .map(rand)
+      .mapAsync(n)(i => wr.require(i))
+  }
+
+  @SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
+  def route(): Route = {
+    path("queries") {
+      withExecutionContext(qd) {
+        parameter('queries.?) { pn: Option[String] =>
+          complete {
+            source(parse(pn))
+          }
+        }
+      }
+    }
+  }
+
+}

+ 49 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/UpdateRoute.scala

@@ -0,0 +1,49 @@
+package net.benchmark.akka.http.world
+import akka.NotUsed
+import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
+import akka.http.scaladsl.server.Directives._
+import akka.stream.scaladsl.Source
+import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
+
+import scala.concurrent.ExecutionContextExecutor
+import scala.util.Try
+
+class UpdateRoute(wr: WorldRepository, ud: ExecutionContextExecutor, sd: ExecutionContextExecutor) {
+
+  implicit private val jss: JsonEntityStreamingSupport =
+    EntityStreamingSupport.json().withParallelMarshalling(5, unordered = true)
+
+  private def rand(i: Int): Int = {
+    val _ = i
+    java.util.concurrent.ThreadLocalRandom.current().nextInt(10000) + 1
+  }
+
+  private def rand(): Int = {
+    java.util.concurrent.ThreadLocalRandom.current().nextInt(10000) + 1
+  }
+
+  private def parse(pn: Option[String]): Int = {
+    pn.fold(Try(1))(s => Try(s.toInt)).getOrElse(1).min(500).max(1)
+  }
+
+  private def source(n: Int): Source[World, NotUsed] = {
+    Source(1 to n)
+      .map(rand)
+      .mapAsync(n)(wr.require)
+      .mapAsync(n) { w =>
+        val wn = w.copy(randomNumber = rand())
+        wr.update(wn).map(_ => wn)(sd)
+      }
+  }
+
+  def route() = {
+    path("updates") {
+      withExecutionContext(ud) {
+        parameter('queries.?) { pn =>
+          complete(source(parse(pn)))
+        }
+      }
+    }
+  }
+
+}

+ 15 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/World.scala

@@ -0,0 +1,15 @@
+package net.benchmark.akka.http.world
+import io.circe.{Decoder, Encoder}
+
+object World {
+
+  implicit val decodeWorld: Decoder[World] =
+    Decoder.forProduct2("id", "randomNumber")(World.apply)
+
+  implicit val encodeWorld: Encoder[World] =
+    Encoder.forProduct2("id", "randomNumber")(v => (v.id, v.randomNumber))
+
+  def tupled = (this.apply _).tupled
+}
+
+case class World(id: Int, randomNumber: Int)

+ 18 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRepository.scala

@@ -0,0 +1,18 @@
+package net.benchmark.akka.http.world
+
+import scala.concurrent.Future
+
+trait WorldRepository {
+
+  def find(id: Int): Future[Option[World]]
+
+  def require(id: Int): Future[World]
+
+  /**
+    *  Update.
+    * @param world The new data.
+    * @return How many worlds have been updated, usually 1.
+    */
+  def update(world: World): Future[Int]
+
+}

+ 27 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRepositoryModule.scala

@@ -0,0 +1,27 @@
+package net.benchmark.akka.http.world
+
+import net.benchmark.akka.http.db.CustomPostgresProfile
+import net.benchmark.akka.http.db.CustomPostgresProfile.api._
+import slick.basic.DatabaseConfig
+
+import scala.concurrent.Future
+
+class WorldRepositoryModule(val dbConfig: DatabaseConfig[CustomPostgresProfile]) extends WorldRepository {
+
+  private val db = dbConfig.db
+
+  private val worlds = WorldTable.worldTableQuery
+
+  override def find(id: Int): Future[Option[World]] = {
+    db.run(worlds.filter(_.id === id).result.headOption)
+  }
+
+  override def require(id: Int): Future[World] = {
+    db.run(worlds.filter(_.id === id).result.head)
+  }
+
+  override def update(world: World): Future[Int] = {
+    db.run(worlds.filter(_.id === world.id).map(_.randomNumber).update(world.randomNumber))
+  }
+
+}

+ 22 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldRoutes.scala

@@ -0,0 +1,22 @@
+package net.benchmark.akka.http.world
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.Route
+
+import scala.concurrent.ExecutionContextExecutor
+
+class WorldRoutes(wr: WorldRepository,
+                  sd: ExecutionContextExecutor,
+                  qd: ExecutionContextExecutor,
+                  ud: ExecutionContextExecutor,
+                  dd: ExecutionContextExecutor) {
+
+  private val qr = new QueriesRoute(wr, qd).route()
+  private val ur = new UpdateRoute(wr, ud, sd).route()
+  private val dr = new DbRoute(wr, dd).route()
+
+  @SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
+  def routes(): Route = {
+    qr ~ ur ~ dr ~ JsonRoute.route ~ PlainTextRoute.route
+  }
+
+}

+ 18 - 0
frameworks/Scala/akka-http/akka-http-slick-postgres/src/main/scala/net/benchmark/akka/http/world/WorldTable.scala

@@ -0,0 +1,18 @@
+package net.benchmark.akka.http.world
+
+import net.benchmark.akka.http.db.CustomPostgresProfile.api._
+
+object WorldTable {
+
+  val worldTableQuery: TableQuery[WorldTable] = TableQuery[WorldTable]
+
+}
+
+class WorldTable(tag: Tag) extends Table[World](tag, "World") {
+
+  def id = column[Int]("id", O.PrimaryKey)
+
+  def randomNumber = column[Int]("randomnumber")
+
+  def * = (id, randomNumber) <> (World.tupled, World.unapply)
+}

+ 21 - 4
frameworks/Scala/akka-http/akka-http.dockerfile

@@ -1,7 +1,24 @@
 FROM hseeberger/scala-sbt:8u151-2.12.5-1.1.2
 FROM hseeberger/scala-sbt:8u151-2.12.5-1.1.2
+
 WORKDIR /akka-http
 WORKDIR /akka-http
-COPY project project
-COPY src src
-COPY build.sbt build.sbt
-RUN sbt -batch clean compile stage
+
+RUN mkdir project
+COPY akka-http/project/build.properties project/
+COPY akka-http/project/plugins.sbt project/
+
+RUN \
+  which sbt && \
+  pwd && \
+  ls -la . && \
+  ls -la project && \
+  sbt sbtVersion
+
+COPY akka-http/build.sbt akka-http/.sbtopts ./
+
+RUN sbt update
+
+COPY akka-http/src src
+
+RUN sbt clean compile stage
+
 CMD ["target/universal/stage/bin/akka-http-benchmark", "-Dakka.http.benchmark.mysql.dbhost=tfb-database", "-J-server", "-J-Xms2g", "-J-Xmx2g", "-J-XX:NewSize=1g", "-J-XX:MaxNewSize=1g", "-J-XX:InitialCodeCacheSize=256m", "-J-XX:ReservedCodeCacheSize=256m", "-J-XX:+UseParallelGC", "-J-XX:-UseBiasedLocking", "-J-XX:+AlwaysPreTouch"]
 CMD ["target/universal/stage/bin/akka-http-benchmark", "-Dakka.http.benchmark.mysql.dbhost=tfb-database", "-J-server", "-J-Xms2g", "-J-Xmx2g", "-J-XX:NewSize=1g", "-J-XX:MaxNewSize=1g", "-J-XX:InitialCodeCacheSize=256m", "-J-XX:ReservedCodeCacheSize=256m", "-J-XX:+UseParallelGC", "-J-XX:-UseBiasedLocking", "-J-XX:+AlwaysPreTouch"]

+ 36 - 0
frameworks/Scala/akka-http/akka-http/.dockerignore

@@ -0,0 +1,36 @@
+.idea/
+*/*.iml
+
+# Created by .ignore support plugin (hsz.mobi)
+### SBT template
+# Simple Build Tool
+# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
+
+target/
+lib_managed/
+src_managed/
+project/boot/
+.history
+.cache
+### Scala template
+**/*.class
+**/*.log
+
+# sbt specific
+.lib/
+dist/*
+**/target*
+project/target
+project/project/target
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+# ENSIME specific
+.ensime_cache/
+.ensime
+
+# our own buffer file
+compare.txt

+ 34 - 0
frameworks/Scala/akka-http/akka-http/.gitignore

@@ -0,0 +1,34 @@
+.idea/
+*/*.iml
+
+# Created by .ignore support plugin (hsz.mobi)
+### SBT template
+# Simple Build Tool
+# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
+
+target/
+lib_managed/
+src_managed/
+project/boot/
+.history
+.cache
+### Scala template
+*.class
+*.log
+
+# sbt specific
+.lib/
+dist/*
+project/project/
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+# ENSIME specific
+.ensime_cache/
+.ensime
+
+# our own buffer file
+compare.txt

+ 5 - 0
frameworks/Scala/akka-http/akka-http/.sbtopts

@@ -0,0 +1,5 @@
+-J-Xms256M
+-J-Xmx768M
+-J-XX:MaxMetaspaceSize=256M
+-Djava.awt.headless=true
+-Djava.net.preferIPv4Stack=true

+ 6 - 6
frameworks/Scala/akka-http/build.sbt → frameworks/Scala/akka-http/akka-http/build.sbt

@@ -4,20 +4,20 @@ organization := "com.typesafe.akka"
 
 
 name := "akka-http-benchmark"
 name := "akka-http-benchmark"
 
 
-version := "0.0.1-SNAPSHOT"
+version := "0.1.0-SNAPSHOT"
 
 
 scalaVersion := "2.12.6"
 scalaVersion := "2.12.6"
 
 
 resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"
 resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"
 
 
 libraryDependencies ++= Seq(
 libraryDependencies ++= Seq(
-  "com.typesafe.akka" %% "akka-http" % "10.1.3",
-  "com.typesafe.akka" %% "akka-stream" % "2.5.14",
-  "de.heikoseeberger" %% "akka-http-jsoniter-scala" % "1.21.0",
+  "com.typesafe.akka" %% "akka-http" % "10.1.7",
+  "com.typesafe.akka" %% "akka-stream" % "2.5.20",
+  "de.heikoseeberger" %% "akka-http-jsoniter-scala" % "1.23.0",
   "mysql" % "mysql-connector-java" % "5.1.47",
   "mysql" % "mysql-connector-java" % "5.1.47",
-  "com.zaxxer" % "HikariCP" % "2.7.9",
+  "com.zaxxer" % "HikariCP" % "3.3.0",
   "org.scalatra.scalate" %% "scalate-core" % "1.8.0",
   "org.scalatra.scalate" %% "scalate-core" % "1.8.0",
-  "org.scalatest" %% "scalatest" % "3.0.4" % "test"
+  "org.scalatest" %% "scalatest" % "3.0.5" % "test"
 )
 )
 
 
 mainClass in Compile := Some("com.typesafe.akka.http.benchmark.Main")
 mainClass in Compile := Some("com.typesafe.akka.http.benchmark.Main")

+ 0 - 0
frameworks/Scala/akka-http/project/Formatting.scala → frameworks/Scala/akka-http/akka-http/project/Formatting.scala


+ 1 - 0
frameworks/Scala/akka-http/akka-http/project/build.properties

@@ -0,0 +1 @@
+sbt.version=1.1.2

+ 1 - 1
frameworks/Scala/akka-http/project/plugins.sbt → frameworks/Scala/akka-http/akka-http/project/plugins.sbt

@@ -3,5 +3,5 @@
 classpathTypes += "maven-plugin"
 classpathTypes += "maven-plugin"
 
 
 addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
 addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
-addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.2")
+addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.16")
 addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.3")
 addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.3")

+ 0 - 0
frameworks/Scala/akka-http/project/project/plugins.sbt → frameworks/Scala/akka-http/akka-http/project/project/plugins.sbt


+ 0 - 0
frameworks/Scala/akka-http/src/main/resources/application.conf → frameworks/Scala/akka-http/akka-http/src/main/resources/application.conf


+ 12 - 0
frameworks/Scala/akka-http/akka-http/src/main/resources/templates/fortunes.mustache

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+    <head><title>Fortunes</title></head>
+    <body>
+        <table>
+            <tr><th>id</th><th>message</th></tr>
+                {{#fortunes}}
+            <tr><td>{{id}}</td><td>{{message}}</td></tr>
+                {{/fortunes}}
+        </table>
+    </body>
+</html>

+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/App.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/App.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Bootstrap.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Bootstrap.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Infrastructure.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Infrastructure.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Main.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Main.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/RequestMapping.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/RequestMapping.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Templating.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Templating.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/DataStore.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/DataStore.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/MySqlDataStore.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/datastore/MySqlDataStore.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/Fortune.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/Fortune.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/World.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/entity/World.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/DbHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/DbHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/FortunesHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/FortunesHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/JsonHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/JsonHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/PlaintextHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/PlaintextHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/QueriesHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/QueriesHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/UpdatesHandler.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/UpdatesHandler.scala


+ 0 - 0
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/util/RandomGenerator.scala → frameworks/Scala/akka-http/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/util/RandomGenerator.scala


+ 27 - 2
frameworks/Scala/akka-http/benchmark_config.json

@@ -1,6 +1,7 @@
 {
 {
   "framework": "akka-http",
   "framework": "akka-http",
-  "tests": [{
+  "tests": [
+    {
       "default": {
       "default": {
         "json_url": "/json",
         "json_url": "/json",
         "plaintext_url": "/plaintext",
         "plaintext_url": "/plaintext",
@@ -21,6 +22,30 @@
         "database_os": "Linux",
         "database_os": "Linux",
         "display_name": "akka-http",
         "display_name": "akka-http",
         "notes": ""
         "notes": ""
+      },
+      "slick-postgres": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "fortune_url": "/fortunes",
+        "update_url": "/updates?queries=",
+        "port": 9339,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "Postgres",
+        "framework": "akka-http",
+        "language": "Scala",
+        "flavor": "None",
+        "orm": "Full",
+        "platform": "Akka",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "akka-http-slick-postgres",
+        "notes": "Applied libraries are Akka HTTP, Akka Streams, Circe, Cats, Slick, Scalate.",
+        "versus": "akka-http"
+      }
     }
     }
-  }]
+  ]
 }
 }

+ 0 - 1
frameworks/Scala/akka-http/project/build.properties

@@ -1 +0,0 @@
-sbt.version=1.1.6