What can ZIO do for me? A Long Polling example with sttp.

Requirements: A basic understanding of ZIO and Cats.

This is my first blog on Medium, so have mercy;).
I am just a user / learner of ZIO.
If you are only interested in the ZIO-part you can jump to the chapter Long Polling with ZIO

Image for post
Image for post

Ok let us start. After checking out some Blogs (see https://github.com/pme123/zio-examples), I wanted to tackle a problem I had at work with ZIO.

Scenario

Image for post
Image for post

In our Play Application we use a Rest Service that provides Long Polling for fetching Tasks.

So our first solution was just to poll this Service:

Polling with Futures

Image for post
Image for post

Our client asks every second if there are some Tasks.

Annoying right?

https://gph.is/2ayuQLg

Here is the implementation:

Long Polling with Futures

As externalTaskApi.fetchAndLock(taskRequest) supports already Long Polling, we just needed to add an additional attribute to the taskRequest.

Image for post
Image for post

Our Client asks for Tasks and waits a defined time for them.

After receiving the response, the Client asks for the next Tasks right away.

This was my first solution:

You may spot the problem: Future[Future[_]]. If the App is restarted there could be two fetchAndProcessTasks() running now - Really Bad!

Adding a flag works (because it is a singleton) but it is considered bad Scala style:

Long Polling with a Typed Actor

So in the end we introduced a Typed Actor:

This is now safe but Wow so much code!

Long Polling with ZIO

Image for post
Image for post
https://zio.dev

Now let us try to do this with ZIO.

For the REST-call we use sttp.

First we have a simple GET request to the defined url. The result we log to the console (also an Effect).

This will call the service only once. So let’s do this forever:

All we need to add is, of course forever

What about some Resilience? For example with this code, whenever you restart the server, the client will die.

Image for post
Image for post

Again we can add this with one line. I choose 5 attempts; each of them waits twice the time as the one before. This can be done by just combining recurs and exponential Schedules.

tapError provides a nice way to log the failing attempts.

The Log shows nicely how each attempt needed twice the time as the one before. In the end you give up with the error message from the failing client.

Next the result type is Either[String, Either[DeserializationError[Error], List[Int]]] from sttp. I would like the result to be a List in any case, if there was an exception it should be printed to the console. A Failure would stop the program entirely, what we don’t want, for exampleZIO.fail(Error).

To be fair in all the examples before ZIO, we encapsulated the code that accessed the REST-Service and the one that handles the numbers. So in essence this would be the code left:

Is this everything? Right I forgot that handle the Tasks are asynchronous. Adding some debug to the console:

Shows that there is at most one number handled per second:

So how can we handle the numbers in parallel?

The answer is to add the three characters Par for parallel. The result looks better now:

Running the App

Running the Client is extending zio.App and implementing its run function:

We log the error and finish the program either successful (0) of failing (-1).

Or you integrate it in your code:

All the client code you find here: HttpClient.

The Server

The server part simulates the behaviour of providing Numbers at different times.

I tried some aspects of ZIO, like its module pattern. But this is maybe something for another Blog.

Conclusion

Image for post
Image for post

I still struggle with ZIO, for example providing the runtime/ environment or interacting with Cats Libraries still gives me some headache.

But this example shows how powerful ZIO is to write elegant and robust programs. So give it a try if you are not already a Fan! It is really cool stuff.

References

ZIO: https://zio.dev

sttp: https://github.com/softwaremill/sttp

Cats: https://typelevel.org/cats/

Thanks to the reviewer Peti Koch.

Let me know if you have questions or stuff that can be done better!

Written by

Working for finnova.com in the Banking business. Prefer to work with Scala / ScalaJS.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store