[External] : Re: Future.resultNow / exceptionNow
Alex Otenko
oleksandr.otenko at gmail.com
Sun Nov 21 15:57:02 UTC 2021
On Sun, 21 Nov 2021, 14:56 Ron Pressler, <ron.pressler at oracle.com> wrote:
>
>
> > On 21 Nov 2021, at 14:00, Alex Otenko <oleksandr.otenko at gmail.com>
> wrote:
> >
> > No, you don't know what went wrong. You only know something did.
>
> The methods must only be called when the Future is in a certain state, and
> the exception tells you exactly what the actual, unexpected state is. You
> have all the information you could ever need to fix the bug. Suppose you
> call resultNow without having called join first. The error you’ll get will
> tell you exactly that this is the bug, and that adding join is necessary.
> And suppose you call resultNow after join but before handling exception,
> the error you’ll get will tell you exactly that that’s what missing.
>
No, because, to be precise, NPE un the task is the root cause. If not for
it, the task never throws, and in all the testing we never discovered the
missing exception handling in the code that calls resultNow.
Now in production NPE got triggered. We look through the logs, and see one
bug, but not the other. To fix it, you need one patch just to make the NPE
discoverable. So you will lose time to resolution.
> >
> > So, you see the code is broken. You get to deploy two patches: one to
> start using a different method to observe what has lead to the problem
> (likely a Runtime Exception or Error - say, NPE in the task), then the fix
> for the actual problem.
>
> The exception tells you *which* incorrect state has led to the problem
> (maybe the message should include precisely which State enum value is
> expected and which is found).
>
Not the full state, though, we learn just a single bit of information.
> >
> > As for maybeResultNow - I haven't warmed up to the idea that throwing by
> resultNow is saving me from a really bad problem.
>
> The problem that resultNow was created to solve is that in the common
> case, in which you already know the state of the future and have already
> handled exceptions, anything other than returning the result would be an
> unnecessary complication. Write down that code and see for yourself.
>
Sure. Here it is:
exe.join();
Throwable th = future.exceptionNow();
if (th != null) throw rewrap(th);
// here resultNow is guaranteed to be ok
// but exceptionNow will throw
> >
> > I am looking at the code that joined on executor, and don't see why it
> is more correct for (albeit indirect) state introspection to punish me with
> hidden throws.
>
> I don’t understand. The method for state introspection, Future.state,
> never fails. resultNow, which is *not* for state introspection, never
> punishes you. It just cannot continue when a bug in your program makes its
> precondition false, and it helps you by telling you what your bug is.
>
> > I am looking at another example that polls for result, and again don't
> see why throwing is better for something that is like a non-blocking get.
>
> The purpose of resultNow is not to be a non-blocking get (although you
> could write a non-blocking get with a combination of state and resultNow).
> The purpose of resultNow is to obtain the result in the common case, in
> which you already know that it’s there, and are *guaranteed* that the
> method will never fail.
>
People will use it as a get() that doesn't require try-catch.
> > Reminds me of NIO Selector API, where almost anything can result in a
> bunch of Runtime Exceptions.
>
> If we could panic, maybe we’d panic. The exception is not the point. It
> just indicates a bug in the program.
>
Well, and my contention is that you declare it a bug. What's the horrible
sin of the above check? A throwing exceptionNow doesn't really save me from
anything.
Alex
> I understand that you’d like a somewhat different feature, but please
> start with a motivation: take the current API and show what *problem you
> run into* that you’d like to solve.
>
> If your problem is unrelated to the JEP but is just about a non-blocking
> polling mechanism for Future, I’d still argue that having both state and
> resultNow is superior to a single maybeGetResult, because the former is
> more general: you can use it just as efficiently for polling or for
> obtaining the result in cases where the correct state is guaranteed.
>
> — Ron
More information about the loom-dev
mailing list