Future’s don’t really have a notion of “wait until the very end of this chain to clean up”, meaning that the function you propose is probably the best you can get away with.
I’ll give you two options:
Use ‘Emm’ or ‘Eff’ and compose Future[ManagedReource[A]]. Syntactically it adds boilerplate to everything you do, but it SHOULD allow you to fully abstract resource management from async execution. (I had planned to add this to scala-arm before life got in the way).
Use something like reactive streams (instead of futures) as these encode the notion of “done with stream” and allow you to clean up resources appropriately. I believe this is a big reason why scalaz.Task still eeks out in favor over typelevel/effects.
Yes, Futures as such certainly won’t compose like this. However, I had the naive hope that it might be possible to create a monadic API that allows nesting and chaining ManagedAsync instances, just like ManagedResource in scala-arm, memoizing creation blocks and mapper functions internally, and then finally invoke a builder/exec method that builds a Future from the whole nested/chained ManagedAsync assembly from inside out. I’ve tinkered a bit with this idea, but couldn’t come up with a good design so far. Whether this is just because of me or because there is none, I don’t know.
Thanks, I will take a look at those. Still looks like a mouthful, but at least a bit less scary than the ThoughtWorks lib I’d found.
I had thought about that, as we’re using rx.scala already. However, so far I haven’t found a nice “pattern language” for expressing the “RAII” open/close symmetry at this level, in particular with nested resources. Actually it felt like even nested invocations of my pathetic #managedAsync() method were easier to follow. Perhaps I just did it wrong, though.