runtime start stop times for zio effects

runtime start stop times for zio effects

Sometimes you need to collect the start and stop times for an effect running. For example, if the effect represents a job, you may want to record the job start and stop times in a database for analysis.

zio has a .timed combinator that provides you a duration, but if you need to also add the start and stop time, .timed is not quiet right.

Fortunately, we can add a few zip’ish combinators and get what we need. I use scala.js js.Date in the code below but substitute in your own date function as appropriate:

  /** Capture run stats including start and stop datetime. Once you have used the
   * timing result via `flatMap{ case (start,stop,delta,exit) => ... }`, use
   * `ZIO.done(exit)` to push the exit value back into an effect if desired.
  def timeRun[R, E,A](effect: ZIO[R,E,A]):
      ZIO[R with zio.clock.Clock, Nothing, (js.Date, js.Date, zio.duration.Duration, Exit[E,A])] =
    (UIO.succeed(new js.Date()) &&& {
      case (duration, (start, exit)) =>
        val completed = new js.Date(start.getTime() + duration.toMillis)
        (start, completed, duration, exit)

The .run combinator gives you the exit value of the effect parameter so you can decide how to work with the result and date data. The &&& combinator zips the results of each effect together and .timed passes along the tuple (duration, effect result).

timeRun(effect){ case (start, stop, duration, exit) =>
  val recordRunEffect = exit match {
    case Exit.Success(v) => putStrLen(s"Success: start: $start, $stop, result: $v")
    case Exit.Failure(c) => putStrLen(s"Failure: ${duration}ms: ${c.prettyPrint}")
  // If desired, pass through the exit value as if this stage never happened!
  recordRunEffect *> ZIO.done(exit)

It’s not a perfect approach though in case your date function takes a long time to run relative to the effect, but its probably good enough for many scenarios.

That’s it!


Popular posts from this blog

zio layers and framework integration

typescript and react types

dotty+scala.js+async: interesting options