My experience with Structured Concurrency
David Alayachew
davidalayachew at gmail.com
Sat Aug 16 19:23:20 UTC 2025
Hey Alan,
> I assume you mean allUntil(Predicate)
Whoops, yes.
> With allUntil then it does mean that the
> predicate may not be pure function
Mine was. It was basically just a Joiner.allUntil(t -> t.state() == FAILED
&& t.exception() instanceof SomeException).
Side note -- excited to see what Pattern-matching will bring to the Subtask
type specifically. Deconstructing it is something I will be doing a lot of.
But yes, if you are referring to once the allUntil became insufficient for
my needs, then yeah. I didn't like the idea of implementing multiple levels
of joiners, all with their own state. I could certainly make it work, but
that was my point with saying "bad memories" -- I remember how much work it
was making it work with inheritance in the past for separate contexts. And
I don't want to relive those bad memories. In general, I try to avoid too
many levels of inheritance with state.
> One thing that would help is if your
> could enumerate a few of the Joiners
> that you implemented. I'm wondering
> if they are general purpose of very
> specific.
Sure. Let me highlight 5 of them. Let me know if you need more examples --
I have about 30+ custom implementations.
1. A stateful Joiner<T, Optional<R>> that folds each success into an add()
on a builder for <R>. When add() returns false (has sufficient input), the
joiner cancels the scope. It returns an Optional of the constructed data
model.
2. A stateful Joiner<T, Stream<Subtask<T>>> that cancels the scope once I
hit X number of tasks that throw SomeException. It returns the tasks that
succeeded, plus those X failures.
3. A stateful Joiner<T, Optional<R>> that takes each successful result,
performs an RPC call using that result, then cancels the scope if the rpc
call is successful. It returns an Optional of the first successful rpc call.
4. A stateful Joiner<List<T>, Optional<R>> that, upon each successful
List<T>, recursively creates new scopes inside of the onComplete, with the
exit condition being that a list is empty. It then performs a reduce on the
returned scopes, bubbling up the call stack until it returns an Optional<R>
5. A stateful Joiner<T, Optional<T>> that cancels the scope on the first
success, but uses a Predicate<T> to determine a success. It returns an
Optional of the result.
Let me know if there is anything further that I can provide.
On Sat, Aug 16, 2025 at 4:53 AM Alan Bateman <alan.bateman at oracle.com>
wrote:
> On 15/08/2025 19:44, David Alayachew wrote:
> > :
> >
> > So, when someone recently challenged me to use Joiners (rather than
> > the old STS preview versions I was used to), I started creating
> > Joiners to handle all sorts of failure and outcomes. At first, a lot
> > of them could be handled by the Joiner.awaitUntil(), where I would
> > just check and see if the task failed, then handle the error. But as I
> > got further and further along, I started needing to add state to my
> > Joiners in order to get the failure handling that I wanted. For
> > example, if a certain number of timeouts occur, cancel the scope.
> > Well, that necessitates an AtomicNumber.
> >
> I assume you mean allUntil(Predicate), which is intended to make it easy
> to create a Joiner that implements a cancellation policy. Joiners are
> inherently stateful as many will accumulate results or exceptions, or
> maybe just count failures. With allUntil then it does mean that the
> predicate may not be pure function, is that the reason for the
> hesitation? Beyond allUntil does mean implementing the Joiner interface.
> I think your mails are pondering whether there is something between
> allUntil and implementing Joiner yourself. I don't think we've had
> enough feedback to date to know if there is something needed there. One
> thing that would help is if your could enumerate a few of the Joiners
> that you implemented. I'm wondering if they are general purpose of very
> specific.
>
> -Alan
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250816/975f3faf/attachment-0001.htm>
More information about the loom-dev
mailing list