What library collects various small Future-based constructs?

Over time, I’ve written many small Future-related functions and classes. Most recently I’ve had to write a AsyncReadWriteLock (trying to acquire returns a Future[HeldLock], no thread affinity). A Google search found this implementation of a similar construct, but that’s not a ReadWrite lock, so I had to write my own.

Is there a library or project that collects small-ish, Future-related utility code? There’s a sort of barrier of convenience for publishing my own (testing cross-compiles, pushing releases to Maven, etc), so I’m not likely to do it for small miscellaneous code. I would be much more likely to contribute PRs to an existing project, and it would be more discoverable too.

ETA: some other constructs that often come up for me:

  • Run a => Future[Unit] in a loop, possibly with a delay (from the end of one invocation to the start of the next) based on an akka or netty Scheduler
  • Variations on Future object methods, e.g. one that folds a Seq[T] using a function T => Future[T] (not sure if this is easier with Scala 2.12 than in 2.11)
  • Convert synchronous exceptions to failed futures, so I don’t have to write both catch and recover every time I call a method returning a Future whose implementation I don’t trust

Maybe these would be useful additions Jon Pretty’s rapture library? I don’t see his typical user name in the list of usernames I can @ mention at this forum, but you can find him on twitter and ping him to see what he thinks.

I don’t use twitter. I pinged him on Gitter.

Maybe cats https://github.com/typelevel/cats?

@curoli cats has a more narrow purpose: functional programming constructs. It doesn’t have any Future-related code as far as I can tell, and its README suggests other libraries for more specific uses - but none of them relates to asynchronicity.

Cats actually provides instances for Future given you have an implicit ExecutionContext in scope, it’s just that Future doesn’t play very nicely with functional programming and has some performance problems out of the box (see Easy Performance Wins With Scalaz for more details).

You might find that Monix will help with the second half of your post - it provides lots of utilities like MVar, Callback, atomic types, CancelableFuture, AsyncSemaphore, AsyncQueue, schedulers, not to mention the Observable type. It uses its own Future-like construct that does not execute immediately (Task).

  • Run a => Future[Unit] in a loop, possibly with a delay (from the end of one invocation to the start of the next) based on an akka or netty Scheduler

Sounds like Task + whileM or untilM with an explicit sleep Task or a custom ReferenceScheduler perhaps?

  • Variations on Future object methods, e.g. one that folds a Seq[T] using a function T => Future[T] (not sure if this is easier with Scala 2.12 than in 2.11)

Depending upon what you mean by fold this might just be List(..).traverse or it could be something more like Observable.fromIterable(..).mapTask(..).foldLeftL(..) or List(..).foldM with Task maybe?

  • Convert synchronous exceptions to failed futures, so I don’t have to write both catch and recover every time I call a method returning a Future whose implementation I don’t trust

Sounds like Task.eval { /* code that throws exceptions */ } or Task.fromFuture(..) depending upon the input

If you can handle adding a dependency I can highly recommend it over my own experience of accumulating various snippets.

1 Like

There is no community standard for standard library Future, though I wish there was one. There are better choices if you have the flexibility to change all your existing code to Monix, Scalaz or Cats. Here is my collection of Future utilities: https://github.com/S-Mach/s_mach.concurrent

Feel free to use it or copy to your own.

  • Run a => Future[Unit] in a loop, possibly with a delay (from the end of one invocation to the start of the next) based on an akka or netty Scheduler

In my lib see Future.delayed. In Akka, you can use ActorSystem.scheduler

  • Variations on Future object methods, e.g. one that folds a Seq[T] using a function T => Future[T] (not sure if this is easier with Scala 2.12 than in 2.11)

In my lib see Collection.async.map/flatMap. Also akka-streams does this now with mapAsync

  • Convert synchronous exceptions to failed futures, so I don’t have to write both catch and recover every time I call a method returning a Future whose implementation I don’t trust

Unsure what you mean. Future.apply will catch synchronous exceptions and convert them to failed future.

Unfortunately I can’t change all my code to a different Future implementation, not only because of the codebase and interaction with other libraries, but because of the large team of people working on it.

A method returning a Future is sometimes implemented as having a short synchronously executed part before the (first) Future is scheduled, and that initial part can throw an exception instead of returning a failed Future. This is typical if the method doesn’t actually use Future.apply but instead calls some other method that itself returns a Future, and then maybe maps that. Here’s a naive example:

def foo(i: Int): Future[Int] = ???
def bar(i: Int): Future[Int] = foo(1/i)

If you call bar(0) it will throw instead of returning a failed Future.

A caller of the method needs to use both try/catch and the future’s recover to be sure all errors are handled, and then the catch and recover blocks’ contents are duplicated. I’ve had to debug a few issues caused by this.

In the end, even having a wrapper method it’s annoying to use, so I’ve been converting a lot of code to use the async/await macros, which do this automatically. Unfortunately, that creates even more overhead, since the macros allocate a state machine class instance…

A method returning a Future is sometimes implemented as having a short synchronously executed part before the (first) Future is scheduled, and that initial part can throw an exception instead of returning a failed Future. This is typical if the method doesn’t actually use Future.apply but instead calls some other method that itself returns a Future, and then maybe maps that.

I’ve found that just letting those kind of exceptions trickle up is the best strategy. Attempting to fix this by catching them upfront will be tedious and very error prone. In your example, I would simply accept that when I call bar, it might throw an exception instead of return a Future. I’ve found that almost all async libraries can throw an exception instead of returning a Future (including my own above). Depending on the framework I’m working in, I catch these kind of exceptions at the highest level possible (hopefully in one spot). If working with web services, I would log the exception and return a 500, but context and requirements will determine best way to handle the exception.

So I’m not recommending you use this, but if I had to write something to solve this:

implicit class FutureExt(val self: Future.type) extends AnyVal {
  def noThrow[A](f: => Future[A]) : Future[A] =
    try {
      f
    } catch {
      case ex:Throwable =>
        Future.failed(ex)
    }
}

...

Future.noThrow(bar(0))

Maybe Monix can give some ideas.
http://www.beyondthelines.net/programming/futures-vs-tasks/