As a little ZIO 2 example with Scala 3, here’s some code that starts to show how to use ZIO.timeout along with ZIO.attempt while accessing an internet URL with Scala’s Source.fromURL.
Basically all I’m doing is:
- I attempt to access a URL using Scala’s
Source.fromURL, - and then I add a timeout to that, specifically a
ZIO##timeout
Here’s the code:
//> using scala "3"
//> using lib "dev.zio::zio::2.1.0"
package zio_http_timeout
import zio.*
import zio.Console.*
import scala.io.Source
object ZioHttpTimeout extends ZIOAppDefault:
val blueprint: ZIO[Any, Throwable, Option[String]] =
ZIO.attempt {
Source.fromURL("http://httpbin.org/get")
.mkString
}.timeout(5.milliseconds)
/**
* NOTE: `timeout` doesn’t make this an error, it’s still
* a `success` here, but it’s value is `None`.
*/
val run = blueprint.foldZIO(
failure => printLineError(s"FAILURE = $failure"),
success => printLine( s"SUCCESS = $success")
)
As shown in the comments, the way this works is:
- If the URL is properly accessed and downloaded within the timeout setting, the
successvalue is printed. This will be the text you download from the URL. Note that it is wrapped inside aSome. - If the
ZIO.timeoutis triggered, thesuccessvalue is still returned, and the result of it is aNone. - If something is wrong with your URL, you’ll get different types of exceptions inside the
failurevalue, includingjava.net.UnknownHostException,java.net.URISyntaxException, and possibly more.
More on ZIO.timeout
So a key here is starting to know how to work with the return value from ZIO.timeout. Here’s what the ZIO Scaladoc says about its timeout method:
Returns an effect that will timeout this effect, returning
Noneif the timeout elapses before the effect has produced a value; and returningSomeof the produced value otherwise.If the timeout elapses without producing a value, the running effect will be safely interrupted.
WARNING: The effect returned by this method will not itself return until the underlying effect is actually interrupted. This leads to more predictable resource utilization. If early return is desired, then instead of using
effect.timeout(d), useeffect.disconnect.timeout(d), which first disconnects the effect's interruption signal before performing the timeout, resulting in earliest possible return, before an underlying effect has been successfully interrupted.
That’s helpful, because it explains the Some and None usage, and also talks about how to interrupt/disconnect the underlying effect.
| this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |