Skip to content

Instantly share code, notes, and snippets.

View dkomanov's full-sized avatar

Dmitry Komanov dkomanov

View GitHub Profile
@dkomanov
dkomanov / ForComprehensions3.scala
Created May 22, 2020 22:16
[writing-async-app-in-scala-part-1] for-comprehensions 3
implicit class BooleanFutureExtensions(val future: Future[Boolean]) extends AnyVal {
def orFail(e: => Throwable): Future[Boolean] =
future.transform(t => if (t.isSuccess && !t.get) Failure(e) else t)
}
@dkomanov
dkomanov / ForComprehensions4.scala
Created May 22, 2020 22:17
[writing-async-app-in-scala-part-1] for-comprehensions 4
for {
_ <- hasPermissions orFail new PermissionDeniedException("...")
movie <- getMovie
if !movie.hidden
actors <- getActors(movie)
plot <- getPlot(movie)
} yield MovieDescription(movie, actors, plot)
@dkomanov
dkomanov / ForComprehensions5.scala
Created May 22, 2020 22:17
[writing-async-app-in-scala-part-1] for-comprehensions 5
movie <- getMovie.filter(!_.hidden).recoverWith {
case _: NoSuchElementException => Future.failed(new HiddenMovieException("..."))
}
@dkomanov
dkomanov / ForComprehensions6.scala
Created May 22, 2020 22:18
[writing-async-app-in-scala-part-1] for-comprehensions 6
implicit class FutureExtensions[T](val future: Future[T]) extends AnyVal {
def filterOrFail(f: T => Boolean, e: => Throwable): Future[T] =
future.flatMap(value => if (f(value)) Future.successful(value) else Future.failed(e))
}
@dkomanov
dkomanov / ForComprehensions7.scala
Created May 22, 2020 22:19
[writing-async-app-in-scala-part-1] for-comprehensions 7
for {
_ <- hasPermissions orFail new PermissionDeniedException("...")
movie <- getMovie.filterOrFail(!_.hidden, new HiddenMovieException("..."))
actors <- getActors(movie)
plot <- getPlot(movie)
} yield MovieDescription(movie, actors, plot)
@dkomanov
dkomanov / Option1.scala
Last active May 31, 2020 11:38
[writing-async-app-in-scala-part-1] option 1
implicit class FutureOfOptionExtensions[T](val v: Future[Option[T]]) extends AnyVal {
def orFail(e: => Throwable): Future[T] =
v.flatMap(_.fold[Future[T]](Future.failed(e), Future.successful)
}
@dkomanov
dkomanov / Option2.scala
Created May 22, 2020 22:25
[writing-async-app-in-scala-part-1] option 2
for {
movie <- findMovie("Dark Waters") orFail new MovieNotFoundException("...")
} yield movie
@dkomanov
dkomanov / RecoverFilter.scala
Created May 22, 2020 22:52
[writing-async-app-in-scala-part-1] recoverFilter
implicit class FutureExtensions[T](val future: Future[T]) extends AnyVal {
def recoverFilter(f: => T): Future[T] =
future.recover {
case _: NoSuchElementException | ControlException => f
}
def recoverFilterWith(f: => Future[T]): Future[T] =
future.recoverWith {
case _: NoSuchElementException | ControlException => f
}
@dkomanov
dkomanov / FutureException1.scala
Created May 23, 2020 22:28
[writing-async-app-in-scala-part-2] Safe Exception Propagation
Future(42)
.map[Int](_ => throw new IllegalArgumentException)
.flatMap[Int](_ => throw new IllegalStateException)
// Effectively: Future.failed(new IllegalArgumentException)
@dkomanov
dkomanov / FutureException2.scala
Created May 23, 2020 22:29
[writing-async-app-in-scala-part-2] Unsafe Exception Propagation
def innocentFunction(param: AnyRef): Future[Int] = {
require(param != null)
Future.successful(42)
}
innocentFunction(null)
.map(_ => throw new IllegalStateException)
// an IllegalArgumentException will be thrown before map call