The silence of failed futures

263 views
Skip to first unread message

Nils Kilden-Pedersen

unread,
Jan 9, 2014, 9:35:21 AM1/9/14
to scala-user
A failed Future is, by default, silently ignored unless a callback is provided to the `failed` method.

Is there a good strategy to change that default, without incurring too much boilerplate? Generally, I'd like to avoid having to explicitly call `failed` every single time, because I know I'll forget in some cases.

Longer term, is there any chance of Future having a non-silent default?

√iktor Ҡlang

unread,
Jan 9, 2014, 9:38:40 AM1/9/14
to Nils Kilden-Pedersen, scala-user
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

Cheers,


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Cheers,

Viktor Klang

Director of Engineering

Twitter: @viktorklang

Nils Kilden-Pedersen

unread,
Jan 9, 2014, 9:50:27 AM1/9/14
to √iktor Ҡlang, scala-user
On Thu, Jan 9, 2014 at 8:38 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

I'm not so much proposing anything as simply looking for the best way handle failures in the least painful way possible.

A lot of my usage involves `foreach` as a means to act on the result. The alternative is use `onComplete` instead, which is more boilerplatey. 

Maybe a method similar to `foreach` that would fail in some manner if the future had failed?

(BTW, I meant to refer to `onFailure`, not `failed` in the OP)

√iktor Ҡlang

unread,
Jan 9, 2014, 10:08:55 AM1/9/14
to Nils Kilden-Pedersen, scala-user
On Thu, Jan 9, 2014 at 3:50 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
On Thu, Jan 9, 2014 at 8:38 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

I'm not so much proposing anything as simply looking for the best way handle failures in the least painful way possible.

A lot of my usage involves `foreach` as a means to act on the result. The alternative is use `onComplete` instead, which is more boilerplatey. 

Maybe a method similar to `foreach` that would fail in some manner if the future had failed?

What manner do you have in mind?
"foreach" is executed on "another thread" when the Future completes, so there's nowhere to "fail to".

Interesting to hear more ideas on this,

Cheers,
 

(BTW, I meant to refer to `onFailure`, not `failed` in the OP) 
 

Cheers,


On Thu, Jan 9, 2014 at 3:35 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
A failed Future is, by default, silently ignored unless a callback is provided to the `failed` method.

Is there a good strategy to change that default, without incurring too much boilerplate? Generally, I'd like to avoid having to explicitly call `failed` every single time, because I know I'll forget in some cases.

Longer term, is there any chance of Future having a non-silent default?

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Cheers,

Viktor Klang

Director of Engineering

Twitter: @viktorklang

Juha Heljoranta

unread,
Jan 9, 2014, 10:10:56 AM1/9/14
to scala...@googlegroups.com, Nils Kilden-Pedersen
How about something like this:

def handle[A](f: Future[A]) = f.value match {
case Some(Success(a)) => ???
case Some(Failure(e)) => ???
case None => ???
}

Cheers,
Juha
> > * Viktor Klang*
> > *Director of Engineering*
> > Typesafe <http://www.typesafe.com/>
> >
> > Twitter: @viktorklang

√iktor Ҡlang

unread,
Jan 9, 2014, 10:13:39 AM1/9/14
to Juha Heljoranta, scala-user, Nils Kilden-Pedersen
On Thu, Jan 9, 2014 at 4:10 PM, Juha Heljoranta <juha.he...@iki.fi> wrote:
How about something like this:

def handle[A](f: Future[A]) = f.value match {
  case Some(Success(a)) => ???
  case Some(Failure(e)) => ???
  case None => ???
}

How does that improve over onComplete? (aside being a racy operation that won't work in practice)

Cheers,



--
Cheers,

Viktor Klang

Director of Engineering

Twitter: @viktorklang

Nils Kilden-Pedersen

unread,
Jan 9, 2014, 10:21:30 AM1/9/14
to √iktor Ҡlang, scala-user
On Thu, Jan 9, 2014 at 9:08 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:



On Thu, Jan 9, 2014 at 3:50 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
On Thu, Jan 9, 2014 at 8:38 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

I'm not so much proposing anything as simply looking for the best way handle failures in the least painful way possible.

A lot of my usage involves `foreach` as a means to act on the result. The alternative is use `onComplete` instead, which is more boilerplatey. 

Maybe a method similar to `foreach` that would fail in some manner if the future had failed?

What manner do you have in mind?
"foreach" is executed on "another thread" when the Future completes, so there's nowhere to "fail to".

Interesting to hear more ideas on this,

The default for a Thread is to simply print to System.err. This is a reasonable default.

Kevin Wright

unread,
Jan 9, 2014, 10:23:39 AM1/9/14
to √iktor Ҡlang, Nils Kilden-Pedersen, scala-user

I imagine Nils was after something like the dead letter approach that we use with actors.  But you'd have to set up your own handler given that we can't assume the presence of akka-logger.

I can imagine tracking whether or not a Future has failed without being mapped or passed to an onSuccess or onFailure handler, but there also looks to be a big difficulty in identifying *which* future was unhandled when logging or otherwise processing it.

Juha Heljoranta

unread,
Jan 9, 2014, 10:27:05 AM1/9/14
to scala...@googlegroups.com, √iktor Ҡlang, Nils Kilden-Pedersen
On Thursday, January 09, 2014 16:13:39 √iktor Ҡlang wrote:
> On Thu, Jan 9, 2014 at 4:10 PM, Juha Heljoranta
<juha.he...@iki.fi>wrote:
> > How about something like this:
> >
> > def handle[A](f: Future[A]) = f.value match {
> >
> > case Some(Success(a)) => ???
> > case Some(Failure(e)) => ???
> > case None => ???
> >
> > }
>
> How does that improve over onComplete? (aside being a racy operation that
> won't work in practice)

None, apparently :)
Somehow though it was about List[Future].foreach instead of Future.foreach...

Cheers,
Juha

√iktor Ҡlang

unread,
Jan 9, 2014, 10:28:22 AM1/9/14
to Nils Kilden-Pedersen, scala-user
On Thu, Jan 9, 2014 at 4:21 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
On Thu, Jan 9, 2014 at 9:08 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:



On Thu, Jan 9, 2014 at 3:50 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
On Thu, Jan 9, 2014 at 8:38 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

I'm not so much proposing anything as simply looking for the best way handle failures in the least painful way possible.

A lot of my usage involves `foreach` as a means to act on the result. The alternative is use `onComplete` instead, which is more boilerplatey. 

Maybe a method similar to `foreach` that would fail in some manner if the future had failed?

What manner do you have in mind?
"foreach" is executed on "another thread" when the Future completes, so there's nowhere to "fail to".

Interesting to hear more ideas on this,

The default for a Thread is to simply print to System.err. This is a reasonable default.

And when would it be printed to System.err?

Alec Zorab

unread,
Jan 9, 2014, 10:28:37 AM1/9/14
to Juha Heljoranta, scala-user, √iktor Ҡlang, Nils Kilden-Pedersen
Maybe a foreachlike method could take an implicit errorhandler which is invoked on failure?


Alec Zorab

unread,
Jan 9, 2014, 10:29:50 AM1/9/14
to √iktor Ҡlang, Nils Kilden-Pedersen, scala-user
(previous suggestion made on the basis that my issues with forgetting about errors occurring in futures tend to stem from either foreach or pipeTo)

√iktor Ҡlang

unread,
Jan 9, 2014, 10:34:59 AM1/9/14
to Alec Zorab, Nils Kilden-Pedersen, scala-user
A cheap solution would be to have Future.foreach pipe failures to the implicit ExecutionContext's reportFailure method.

Cheers,

Nils Kilden-Pedersen

unread,
Jan 9, 2014, 2:31:22 PM1/9/14
to √iktor Ҡlang, Alec Zorab, scala-user
Mmm, tasty.

√iktor Ҡlang

unread,
Jan 9, 2014, 2:40:12 PM1/9/14
to Nils Kilden-Pedersen, scala-user, Alec Zorab

Open a ticket please

Alexandru Nedelcu

unread,
Jan 9, 2014, 5:03:36 PM1/9/14
to √iktor Ҡlang, Alec Zorab, Nils Kilden-Pedersen, scala-user
On Thu, Jan 9, 2014 at 5:34 PM, √iktor Ҡlang <viktor...@gmail.com> wrote:
A cheap solution would be to have Future.foreach pipe failures to the implicit ExecutionContext's reportFailure method.

For some reason, on stumbling upon ExecutionContext.reportFailure, I somehow assumed that its purpose is for logging errors in Futures. If that's not its purpose, then what does reportFailure do anyway?

--
Alexandru Nedelcu
www.bionicspirit.com

PGP Public Key:
https://bionicspirit.com/key.aexpk

√iktor Ҡlang

unread,
Jan 9, 2014, 5:11:20 PM1/9/14
to Alexandru Nedelcu, scala-user, Nils Kilden-Pedersen, Alec Zorab

reportFailure is when there is no way to communicate back to the user that something went wrong, see its usage in the stdlib.

Cheers,
V

Philipp Haller

unread,
Jan 10, 2014, 7:48:24 AM1/10/14
to Nils Kilden-Pedersen, √iktor Ҡlang, scala-user
On Thu, Jan 9, 2014 at 3:50 PM, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
On Thu, Jan 9, 2014 at 8:38 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
Same goes for a failed Try.
However, failures are always propagated along both (`map` preserves the failure etc)

What do you propose would be done?

I'm not so much proposing anything as simply looking for the best way handle failures in the least painful way possible.

A lot of my usage involves `foreach` as a means to act on the result. The alternative is use `onComplete` instead, which is more boilerplatey. 

Maybe a method similar to `foreach` that would fail in some manner if the future had failed?

`transform` is such a method. You can use it to attach error reporting to any future:

scala> import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.{Future, ExecutionContext}

scala> import ExecutionContext.Implicits.global
import ExecutionContext.Implicits.global

scala> def logged[T](fut: Future[T]) =
     |   fut.transform(identity, { t: Throwable =>
     |     Console.err.println(s"failed with $t")
     |     t
     |   })
logged: [T](fut: scala.concurrent.Future[T])scala.concurrent.Future[T]

scala> logged(Future { if (true) throw new Exception("boom") else 42 })
failed with java.lang.Exception: boom
res0: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@3999b7a4


Basically, `transform` takes two functions. The first function transforms the result of the success case (if applicable). The second function transforms the result of the failure case (if applicable).

Cheers,
Philipp

Michał Rus

unread,
Jan 10, 2014, 7:54:11 AM1/10/14
to Philipp Haller, Nils Kilden-Pedersen, √iktor Ҡlang, scala-user
Philipp, whoa, thanks!

m.

vate...@gmail.com

unread,
Jan 15, 2014, 8:16:38 AM1/15/14
to scala...@googlegroups.com
Thanks Philipp, interesting idea!

In addition, instead of writing "logged" through all our code, it is
possible to replace Future implementation - by adding our own
scala.concurrent.impl.Future in the beginning of classpath or by using
AspectJ weaver in runtime. If we really want it :)

> `transform` is such a method. You can use it to attach error
> reporting to any future:
> scala> def logged[T](fut: Future[T]) =
> | fut.transform(identity, { t: Throwable =>
> | Console.err.println(s"failed with $t")
> | t
> | })
> logged: [T](fut: scala.concurrent.Future[T])scala.concurrent.Future[T]
>
> scala> logged(Future { if (true) throw new Exception("boom") else
> scala> 42 })
> failed with java.lang.Exception: boom

--
Vatel

Naftoli Gugenheim

unread,
Jan 22, 2014, 5:34:06 PM1/22/14
to Philipp Haller, scala-user, Viktor Klang, Nils Kilden-Pedersen

Isn't a method like that usually named `fold`?

√iktor Ҡlang

unread,
Jan 22, 2014, 5:42:29 PM1/22/14
to Naftoli Gugenheim, Philipp Haller, scala-user, Nils Kilden-Pedersen
On Wed, Jan 22, 2014 at 11:34 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:

Isn't a method like that usually named `fold`?

Option
  def fold[B](ifEmpty: => B)(f: A => B): B

List
  def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1

Future
  def transform[S](s: (T) ⇒ S, f: (Throwable) ⇒ Throwable)(implicit executor: ExecutionContext): Future[S]



--
Cheers,

———————
Viktor Klang
Chief Architect - Typesafe

Twitter: @viktorklang

Rex Kerr

unread,
Jan 22, 2014, 5:59:07 PM1/22/14
to √iktor Ҡlang, Naftoli Gugenheim, Philipp Haller, scala-user, Nils Kilden-Pedersen
On Wed, Jan 22, 2014 at 2:42 PM, √iktor Ҡlang <viktor...@gmail.com> wrote:



On Wed, Jan 22, 2014 at 11:34 PM, Naftoli Gugenheim <nafto...@gmail.com> wrote:

Isn't a method like that usually named `fold`?

Option
  def fold[B](ifEmpty: => B)(f: A => B): B

List
  def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1

Future
  def transform[S](s: (T) ⇒ S, f: (Throwable) ⇒ Throwable)(implicit executor: ExecutionContext): Future[S]

Well,

ArrayBuffer
  def transform(f: (A) ⇒ A): ArrayBuffer.this.type

So, uh, it's not a fold, but it's more fold-like than transform-like given library precedent.

(Not that it matters that much as long as it's not a name that everyone associates with a given meaning; fold and map and foreach should have expected signatures, but I'm not sure there is a strong expectation for "transform".)

  --Rex


√iktor Ҡlang

unread,
Jan 22, 2014, 6:05:26 PM1/22/14
to Rex Kerr, Naftoli Gugenheim, Philipp Haller, scala-user, Nils Kilden-Pedersen
Let's leave the shed unpainted, shall we? :-)
 

  --Rex


Reply all
Reply to author
Forward
0 new messages