Last active
August 27, 2022 16:18
-
-
Save sshark/308f67f4c9f2d7b734bfcf6e24dac55d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.teckhooi | |
import cats.effect.{ExitCode, IO, IOApp} | |
import cats.effect.IO.ioParallel // requires for UptimeService[IO] | |
import cats.{Id, Monad, Parallel, Show} | |
import cats.syntax.parallel._ | |
import cats.syntax.functor._ | |
import cats.syntax.traverse._ // requires for traverse | |
import cats.syntax.show._ | |
import cats.syntax.flatMap._ // requires for UptimeService[Id] | |
import scala.concurrent.duration.{Duration, SECONDS} | |
import scala.concurrent.{Await, Future} | |
object UptimeApp extends IOApp { | |
trait UptimeClient[F[_]] { | |
def getUptime(hostname: String): F[Int] | |
} | |
class UptimeService[F[_]: Monad: Parallel](implicit client: UptimeClient[F]) { | |
def getTotalUptime(hostnames: List[String]): F[Int] = | |
// hostnames.parTraverse(client.getUptime).map(_.sum) // takes 1s to complete | |
hostnames.traverse(client.getUptime).map(_.sum) // takes 2s to complete | |
} | |
val hosts: Map[String, Int] = Map("host1" -> 10, "host2" -> 8) | |
import concurrent.ExecutionContext.Implicits.global | |
implicit object FutureClient extends UptimeClient[Future] { | |
override def getUptime(hostname: String): Future[Int] = { | |
Thread.sleep(1000) | |
Future(hosts.getOrElse(hostname, 0)) | |
} | |
} | |
implicit object IOClient extends UptimeClient[IO] { | |
override def getUptime(hostname: String): IO[Int] = { | |
IO.sleep(Duration(1, SECONDS)) *> IO.pure(hosts.getOrElse(hostname, 0)) | |
} | |
} | |
implicit object IdClient extends UptimeClient[Id] { | |
override def getUptime(hostname: String): Int = hosts.getOrElse(hostname, 0) | |
} | |
implicit def showFuture[A: Show]: Show[Future[A]] = | |
(t: Future[A]) => Await.result(t, Duration(1, SECONDS)).show | |
override def run(args: List[String]): IO[ExitCode] = { | |
for { | |
startMillis <- IO(System.currentTimeMillis()) | |
service = new UptimeService[IO] | |
result <- service.getTotalUptime(List("host1", "host2")) | |
_ <- IO(println(s"Result: $result")) | |
_ <- IO(println(s"Time taken: ${System.currentTimeMillis() - startMillis}ms")) | |
} yield ExitCode.Success | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment