Future.sequence
seems to work fine for me
(Scastie - An interactive playground for Scala.).
It works fine for me as well but it seemed to prevent the Futures in the
list executing asynchronously, although I was probably wrong as that
doesn’t seem to be the case in your example above (thanks for that).
However, are the futures using the ActorSystem
’s
ExecutionContext
? In that case it might be a race condition, since
AFAIK a shutdown ActorSystem
wouldn’t be able to dispatch the
remaining Future
s. From Akka’s documentation on
ActorSystem.terminate
:
Yes, that was the problem I was trying to fix by using the Futures - by
having each Actor complete a Future when it is finished and having the
main method wait for them all to complete before shutting everything down.
Be careful to not schedule any operations on the dispatcher of this
actor system as it will have been shut down before this future
completes.
To work around that, either use another ExecutionContext
, or make
sure that your terminate
handler depends on the “display results”
Future
s, rather than the “fetch results” Future
s.
I’ve got this working as I want but I think your last paragraph nails
the problem I was having - initially I was waiting on the fetch and not
the display result.
The application is taking a CSV file of flight data and using an Akka
stream to parse it and then collate by airport. The collation is done by
an actor that creates a sub-actor per airport which collects each
airport’s data and performs calculations on it:
val airports = actorSystem.actorOf(AirportRouter.props)
csv.runWith(Sink.actorRefWithAck(airports, StartOfData, Acknowledge,
EndOfData))
// Collect and display the per-airport statistics.
(airports ?
GetStats).mapTo[Future[Seq[Future[AirportStats]]]].map(.map(stats =>
Future.sequence(stats.map(.map(displayStats()))).onComplete( =>
actorSystem.terminate())
))
The outer future in Future[Seq[Future[AirportStats]]]] is completed when
the router actor has processed all the records in the Akka stream - by
that point all the per-airport collation actors will have been created,
even if they are still processing the data. The inner list of futures is
per-airport and they are completed as each airport’s statistics
calculations are complete. What I needed to do was to map those inner
futures to a future that is completed when the airport’s data has been
displayed, as you suggested.
Thanks for the help,