Skip to content

Instantly share code, notes, and snippets.

View dkomanov's full-sized avatar

Dmitry Komanov dkomanov

View GitHub Profile
@dkomanov
dkomanov / DirectStackTraceDemo.scala
Created May 25, 2020 16:46
[writing-async-app-in-scala-part-3] demo for stack trace
def stackTrace(implicit ec: ExecutionContext): Any = {
Await.result(
Future.successful(1)
.map(v => v + 1)
.flatMap(v => Future.successful(v))
.map { v =>
new IllegalStateException().printStackTrace()
v
},
10.seconds
@dkomanov
dkomanov / RpcClient.scala
Created May 25, 2020 16:44
[writing-async-app-in-scala-part-3] rpc client with 2 ExecutionContexts
class RpcClient(ownEc: ExecutionContext, appEc: ExecutionContext) {
def call: Future[String] =
Future("a")(ownEc)
.map(identity)(appEc) // here we move back to an application execution context
}
@dkomanov
dkomanov / DirectExecutorContextUsage.scala
Created May 25, 2020 16:41
[writing-async-app-in-scala-part-3] direct executor context usage
def rpcCall: Future[String]
def daoCall(id: String): Future[Int]
def extractId(idStr: String): Future[String]
def convertDbValue(value: Int): Future[Int]
import directExecutionContext
for {
idStr <- rpcCall
id <- extractId(idStr) // executed in RPC execution context
@dkomanov
dkomanov / MapDescribed.scala
Created May 25, 2020 16:39
[writing-async-app-in-scala-part-3] map described
def map[U](f: T => U)
(implicit ec: ExecutionContext): Future[U] = {
val promise = Promise()
if (isCompleted) // in real code this is an atomic operation + pattern matching
// even if it's completed, callback is submitted to ExecutionContext
ec.execute(() => {
f(result)
})
else
registerCallback(f)(ec)
@dkomanov
dkomanov / SmartMap.scala
Created May 25, 2020 16:37
[writing-async-app-in-scala-part-3] smartMap extension
def smartMap[U](f: T => U)(implicit ec: ExecutionContext): Future[U] =
if (future.isCompleted) {
if (future.value.get.isSuccess)
wrap(f(future.value.get.get))
else
future.asInstanceOf[Future[U]]
} else {
future.map(f)(ec)
}
@dkomanov
dkomanov / Benchmark.scala
Created May 25, 2020 16:34
[writing-async-app-in-scala-part-3] benchmark
var future = Future.successful(0)
for (_ <- 1 to 100) {
future = future.map(v => v + 1)
}
require(Await.result(future, 10.seconds) == 100)
@dkomanov
dkomanov / Transformations.scala
Created May 25, 2020 16:32
[writing-async-app-in-scala-part-3] multiple transformations
def rpcCall: Future[String] = ???
rpcCall
.map(_.split('_'))
.filter(_.length < 4)
.map {
case Array(single) => single
case Array(first, second@_) => first
case Array(first@_, second, third@_) => third
case _ => ""
@dkomanov
dkomanov / BlockingDao2.scala
Last active May 25, 2020 16:30
[writing-async-app-in-scala-part-3] blocking dao 2
class RobustDao(jdbcTemplate: JdbcTemplate,
blockingEc: ExecutionContext,
applicationEc: ExecutionContext) {
def get(id: String): Future[Option[RichDomainObject]] = {
Future(getBlocking(id))(blockingEc)
.map(blob => blob.map(parseJson))(applicationEc)
}
private def getBlocking(id: String): Option[String] =
jdbcTemplate.queryForObject(
@dkomanov
dkomanov / ExecutionContext.scala
Created May 25, 2020 16:29
[writing-async-app-in-scala-part-3] execution context
trait ExecutionContext {
def execute(runnable: Runnable): Unit
def reportFailure(cause: Throwable): Unit
}
@dkomanov
dkomanov / BlockingDao1.scala
Created May 25, 2020 16:19
[writing-async-app-in-scala-part-3] blocking dao 1
implicit val blockingExecutionContext =
ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(50))
class MyDao(jdbcTemplate: JdbcTemplate)(implicit ec: ExecutionContext) {
def get(id: String): Future[Option[RichDomainObject]] =
Future(getBlocking(id))
private def getBlocking(id: String): Option[RichDomainObject] =
jdbcTemplate.queryForObject(
"SELECT blob FROM table WHERE id = ?",