Skip to content

Instantly share code, notes, and snippets.

View dkomanov's full-sized avatar

Dmitry Komanov dkomanov

View GitHub Profile
@dkomanov
dkomanov / RpcCaching1.scala
Created May 23, 2020 22:31
[writing-async-app-in-scala-part-2] RPC with caching
case class HttpRequest(uri: String)
def handleFromMemcached(r: HttpRequest): Future[Option[Int]] = {
require(r.uri != "/memcached-boom", "Memcached Boom!")
Future.successful(if (r.uri == "/memcached") Some(42) else None)
}
def handleFromCdn(r: HttpRequest): Future[Option[Int]] = {
require(r.uri != "/cnd-boom", "CDN Boom!")
Future.successful(if (r.uri == "/cdn") Some(42) else None)
@dkomanov
dkomanov / RpcCaching2.scala
Created May 23, 2020 22:34
[writing-async-app-in-scala-part-2] RPC with caching 2
val handlers: List[HttpRequest => Future[Option[Int]]] = List(
handleFromMemcached,
handleFromCdn,
r => handleFromHadoop(r).map(Some.apply)
)
def handle(r: HttpRequest): Future[Int] = {
executeLazily(handlers.map(handler => () => handler(r)))
.map(_.getOrElse(throw new IllegalStateException("Hadoop should always return Some!")))
}
@dkomanov
dkomanov / executeLazily.scala
Created May 23, 2020 22:36
[writing-async-app-in-scala-part-2] executeLazily implementation
def executeLazily[Argument, Return](argument: Argument,
list: List[Argument => Future[Option[Return]]])
(implicit ec: ExecutionContext): Future[Option[Return]] = {
val promise = Promise[Option[Return]]()
val iterator = list.iterator
def completeWith(t: Try[Option[Return]]): Unit = t match {
case Success(value) =>
if (value.isDefined || !iterator.hasNext)
promise.success(value)
@dkomanov
dkomanov / safeFuture.scala
Created May 23, 2020 22:43
[writing-async-app-in-scala-part-2] safeFuture implementation
def safeFuture[T](f: => Future[T]): Future[T] = {
try {
f
} catch {
case NonFatal(e) => Future.failed(e)
}
}
def handleFromMemcached(r: HttpRequest): Future[Option[Int]] = safeFuture {
require(r.uri != "/memcached-boom", "Memcached Boom!")
@dkomanov
dkomanov / FutureException3.scala
Created May 24, 2020 16:19
[writing-async-app-in-scala-part-2] trivial example
def rpcCall: Future[Option[String]]
def reportException(e: Throwable): Unit
def getUrlSafe: Future[Option[String]] = {
rpcCall.recover {
case e: Throwable =>
reportException(e)
None
}
}
@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 = ?",
@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 / 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 / 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)