install sbt:
- wrapper script: https://github.com/paulp/sbt-extras/blob/master/sbt
- or https://www.scala-sbt.org/download.html
build:
- ./build.sh
run:
./target/pack/bin/test
src and config:
src/main/scala/test.scala
*.sc | |
target | |
.bloop |
version=2.7.3 | |
project.git = true | |
maxColumn = 120 | |
docstrings = JavaDoc | |
align.tokens = ["%", "%%", {code = "=>", owner = "Case"}] | |
align.openParenCallSite = false | |
align.openParenDefnSite = false | |
align.arrowEnumeratorGenerator = true | |
align = most | |
continuationIndent.callSite = 2 | |
continuationIndent.defnSite = 2 | |
danglingParentheses = true | |
rewrite.rules = [SortModifiers] |
install sbt:
build:
run:
./target/pack/bin/test
src and config:
src/main/scala/test.scala
sbt.version=1.3.13 |
organization := "com.pasotan" | |
scalaVersion := "2.13.2" | |
scalacOptions += "-Ymacro-annotations" | |
fork in run := true | |
addCompilerPlugin("org.typelevel" % "kind-projector" % "0.11.0" cross CrossVersion.full) | |
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1" cross CrossVersion.binary) | |
addCompilerPlugin("com.github.cb372" % "scala-typed-holes" % "0.1.5" cross CrossVersion.full) | |
testFrameworks += new TestFramework("munit.Framework") | |
scalafmtOnCompile := true | |
cancelable in Global := true | |
javaOptions ++= Seq("-XX:+UseG1GC", "-Xmx600m", "-Xms600m", "-XX:SurvivorRatio=8", "-Duser.timezone=UTC") | |
enablePlugins(PackPlugin) | |
libraryDependencies ++= Seq( | |
"org.tpolecat" %% "doobie-core" % "0.9.2", | |
"org.tpolecat" %% "doobie-postgres" % "0.9.2", | |
"org.tpolecat" %% "doobie-hikari" % "0.9.2", | |
"ch.qos.logback" % "logback-classic" % "1.2.3" | |
) |
#!/bin/sh | |
mkdir -p src/main/resources src/main/scala project/ | |
mv build.properties plugins.sbt project/ | |
mv test.scala src/main/scala/ | |
mv logback.xml src/main/resources/ | |
sbt pack |
<configuration> | |
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | |
<encoder> | |
<pattern>%-5p [%d{ISO8601,UTC+0}] %c: %m%n%rEx</pattern> | |
</encoder> | |
</appender> | |
<root level="INFO"> | |
<appender-ref ref="STDOUT" /> | |
<!--<appender-ref ref="FILE"/>--> | |
</root> | |
</configuration> |
addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1") | |
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.1") | |
addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.13") | |
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1") | |
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") | |
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.13") |
import java.util.concurrent.{ThreadLocalRandom, TimeUnit, Executors} | |
import cats.implicits._ | |
import cats.effect._ | |
import doobie._ | |
import doobie.hikari._ | |
import doobie.implicits._ | |
import scala.concurrent.duration._ | |
object Test extends IOApp { | |
val PoolSize = 80 | |
val MaxLifeTime = 60L | |
val DBHost = "pg-staging" | |
val DBPort = 5555 | |
val DBName = "test" | |
val DBUser = "www" | |
val DBPasswd = "www" | |
val Driver = "org.postgresql.Driver" | |
val ConnectUrl = s"jdbc:postgresql://${DBHost}:${DBPort}/${DBName}" | |
def newPool(): Resource[IO, Transactor[IO]] = for { | |
ce <- ExecutionContexts.cachedThreadPool[IO] | |
te <- ExecutionContexts.cachedThreadPool[IO] | |
xa <- HikariTransactor.newHikariTransactor[IO]( | |
driverClassName = Driver, | |
url = ConnectUrl, | |
user = DBUser, | |
pass = DBPasswd, | |
connectEC = ce, // await connection here | |
blocker = Blocker.liftExecutionContext(te) // execute JDBC operations here | |
) | |
_ <- Resource.liftF { | |
xa.configure { ds => | |
IO { | |
ds.setMaximumPoolSize(PoolSize) | |
ds.setMaxLifetime(TimeUnit.SECONDS.toMillis(MaxLifeTime)) | |
ds.setConnectionTimeout(1000) | |
ds.setInitializationFailTimeout(10) | |
} | |
} | |
} | |
} yield xa | |
def rand(): Double = { | |
val a = ThreadLocalRandom.current().nextInt(100, 1500) | |
a.toDouble / 1000 | |
} | |
def test(xa: Transactor[IO]): IO[Unit] = { | |
val sleep = rand() | |
sql"select pg_sleep(${sleep})" | |
.query[Unit] | |
.option | |
.transact(xa) | |
.timeout(5.seconds) | |
.attempt | |
.map { | |
case Left(ex) => ex.printStackTrace() | |
case Right(_) => () | |
} >> | |
Timer[IO].sleep(10.millis) | |
} | |
override def run(args: List[String]): IO[ExitCode] = { | |
val _run = for { | |
xa <- fs2.Stream.resource(newPool()) | |
_ <- fs2.Stream | |
.constant(1) | |
.covary[IO] | |
.parEvalMapUnordered(PoolSize) { _ => | |
test(xa) | |
} | |
} yield () | |
_run.compile.drain.as(ExitCode.Success) | |
} | |
} |