Quantcast
Channel: Akka Libraries - Discussion Forum for Akka technologies
Viewing all articles
Browse latest Browse all 1362

Unmarshaller.map() creates an unmarshaller that ignores the passed ExecutionContext

$
0
0

One would expect that this code:

unmarshaller.unmarshal(entity, materializer)

will perform the unmarshalling in the ExecutionContext of the specified materializer.

However, this is not the case!
If unmarshaller was created using Unmarshaller.map() function, then there is a case where unmarshalling is performed right in the caller thread — not using the provided ExecutionContext.

This is because of the usage of FastFuture inside Unmarshaller:

  def map[C](f: B => C): Unmarshaller[A, C] =
    transform(implicit ec => _ => _.fast map f)

FastFuture.map() calls out to transformWith():

  def transformWith[B](s: A => Future[B], f: Throwable => Future[B])(implicit executor: ExecutionContext): Future[B] = {
    def strictTransform[T](x: T, f: T => Future[B]) =
      try f(x)
      catch { case NonFatal(e) => ErrorFuture(e) }

    future match {
      case FulfilledFuture(a) => strictTransform(a, s)
      // ...

Here we go - on the last line strictTransform is used, instead of performing the computation in the specified ExecutionContext.

I think that this is very confusing and non-intuitive. Why is FastFuture used in Unmarshaller.map? Maybe Unmarshaller should offer two versions — one where a map is trivial and uses FastFuture, and another where it uses the regular Future for the case where map actually does the hard work — as is the case in our code:

Unmarshaller.forMediaType(MediaTypes.APPLICATION_JSON, Unmarshaller.entityToString())
      .thenApply { s -> fromJSON(mapper, s, expectedType) }

1 post - 1 participant

Read full topic


Viewing all articles
Browse latest Browse all 1362