Practical fiber safety (and how Concurrent implies Parallel)

A short post, for a change.

cats-effect has start. And start has a problem that is outlined right in its docs (link):

* {{{
*   def par2[A, B](ioa: IO[A], iob: IO[B]): IO[(A, B)] =
*     for {
*       fa <- ioa.start
*       fb <- iob.start
*        a <- fa.join
*        b <- fb.join
*     } yield (a, b)
* }}}
*
* Note in such a case usage of `parMapN` (via `cats.Parallel`) is
* still recommended because of behavior on error and cancellation —
* consider in the example above what would happen if the first task
* finishes in error. In that case the second task doesn't get canceled,
* which creates a potential memory leak.

That doesn’t quite feel right. Especially in presense of cancelable flatMaps, it’s possible that we end up with a more ugly situation

Read More

Traverse your HLists for fun and profit

Surprisingly not mentioned often, there’s Typelevel kittens, a library for typeclass derivation for Cats, which also has few extra things. In particular, there’s an ability to sequence and traverse an HList. It doesn’t get enough exposure though, so let’s explore few illustrative ways this can be used.

WARNING: This post will contain a lot of code. Crazy shapeless aux type-level computation kind of code.

Read More

Scala exercises: cats-effect

There’s a lot of info on cats-effect these days, but a lot of it is about concrete use-cases. Yet there’s not much for those who know the basics but don’t feel confident enough with the library to build full-fledged applications. I’ve seen a couple of questions, however, which can be well generalized and are more complex and interesting than examples provided in documentation. So, I decided to turn them into exercises.

If you know how to do FP in Scala, and a bit about cats and cats-effect, the initial solution shouldn’t take more than an hour for you to arrive at. If you struggle to find a solution, there will be a couple of hints. And for those who want to dive deeper, there are bonus assignments which require additional generalization and/or refactoring.

Currently, there are just two. I plan to slowly build up the list as I solve more interesting problems, mine or others’.

Read More

Things to store in a Ref

Cats-effect 1.0.0-RC2 is out, and among various improvements, it brought to us some goodies in cats.effect.concurrent, exported from fs2 and Monix with a number of changes:

  • Ref - pure mutable reference
  • Deferred - a purely functional alternative to Promise
  • Semaphore - an access control tool
  • MVar - a mutable location that can be empty, useful as synchronization and communication channel

This post will focus on Ref and to show what interesting techniques it enables.

Read More

Better logging with Monix 3, part 1: MDC

Problem:

I want to figure out which log entries belong to which request.

Also, being a lazy person, I want to get away with as little work as possible. In particular that means:

  • I don’t want to pass extra function parameters / implicits (solutions like Logger.takingImplicit of scala-logging won’t cut)
  • I don’t want to pollute my domain signatures with something like ReaderT[Task, RequestId, A] instead of plain Tasks.
  • I don’t want to manually insert request ID to every call to log function. I want to set it once and be done with it.

Java SLF4J API already support all this functionality in form of MDC. However, the existing implementations use a ThreadLocal variable, which doesn’t work if you’re not creating a separate thread per each request - which I do not.

Solution:

Read More