-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment/jetty 12 chunk isError and warnings #9904
Conversation
@lorban I have removed the I have also started experimenting with transient failures (calling them warnings for now). I've updated AsyncSource and the ContentSourceInputStream. Both mostly trivial updates, but both definitely needed updates. So on that sample, every I've added you as an assignee rather than as a reviewer, so please feel free collaborate and experiment in this branch to see how you like it. I think there needs to be a lot more tests of mods to the basic |
…tty-12-chunk-isError
@sbordet this is ready for your review. @lorban and I tossed around the naming for a while. We ended up with:
We have updated a few things to handle "warnings":
Our feeling is that this change is good in that it removes the Currently nothing we have will inject a warning into any of our sources. Ultimately |
@sbordet here is the gist of this API modification, other changes are about adapting the implementation:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregw the only think I am worried is a spin loop in case of transient failed Chunks.
Do we have a test case for that?
And is the semantic that once the transient failed Chunk has been read, another read returns null (or something else)?
...tation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/ContentDocs.java
Outdated
Show resolved
Hide resolved
* @param chunk The chunk to test for an {@link Chunk#getError() error}. | ||
* @return True if the chunk is non-null and {@link Chunk#getError() chunk.getError()} returns non-null. | ||
*/ | ||
static boolean isError(Chunk chunk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to isFailure()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sbordet The names were discussed at length between @lorban and myself. We did try the renames that you suggest, but they don't really work.
Currently we have isError
and getError
, where an "error" can be a failure from fail(Throwable)
or a warning from warn(Throwable)
An alternative is to have isFailure
and getFailure
, where a "failure" can be a persistent from fail(Throwable)
or a either from fail(Throwable failure, boolean last)
. @lorban thoughts?
Eitherway, the language used is more than just these 2 methods and updates need to be coordinated through the javadoc and other methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sbordet note that @lorban and I did consider the fail(Throwable failure, boolean last)
approach, but there are big differences between the semantics of last being true/false.
With last==true, any queued chunks are failed and the source is drained and failed immediately. With last==false, the "warning" is handled in order with other chunks and no draining occurs.
I guess that can be OK behind the one method with careful javadoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote -0 on fail(Throwable failure, boolean last)
for the reasons @gregw explained: the last flag completely changes the semantic so I'd prefer to have two separate methods, but could live with a single well-documented one.
Error, failure and warning have very specific meanings in this context, so maybe they should be better documented but those three words were carefully chosen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also -0 on the single method. Having said that, I'm also only +0 on the warn(Throwable)
name.
It is interesting that to describe what a warning is, I tend to say it is a "transient failure" rather than a "transient error".
So I could definitely be +1 on isFailure(Chunk)
and getFailure()
if we could work out a good way of injecting a transient failure. That way we could talk about "failures" only and their attributes (last or not last), and not have to distinguish between "warning" and "error", as they would not apply.
Perhaps fail(Throwable)
and transientFail(Throwable)
?
Or maybe fail(Throwable failure, boolean last)
is not so bad if we javadoc it really well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lorban thoughts on naming? again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to stick to what we have: isError
, getError
and fail(Throwable)
. I just wouldn't add warn(Throwable)
on Content.Source
yet and only have it on AsyncContent
for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would stick with fail(Throwable), Throwable getFailure()
and isFailed(Chunk)
.
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/content/AsyncContent.java
Show resolved
Hide resolved
Note really. Since transient failures (aka warnings) are transient, then we'd only loop if something kept raising them over and over again. Currently we have no mechanism to introduce warnings (aka transient failures) other than in test harnesses.... but if we were, it would be as a result of an The related question, for when we want to actually use these transient failures is should However, we need to review all our callers of
It returns null. See |
# Conflicts: # jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
@lorban can I get a review on this modulo naming? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After pondering this change, I'm now wondering if isError()
shouldn't do return chunk != null && chunk.getError() != null && chunk.isLast()
.
All the existing code that used to do chunk instanceof Error
would then do the right thing both in case of a failure and a warning without any other change than isError(chunk)
: failures would mark the end of the source, and warnings would be considered like a normal content with a zero-byte buffer; this would all be safer by default.
...tation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/ContentDocs.java
Outdated
Show resolved
Hide resolved
...tation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/ContentDocs.java
Show resolved
Hide resolved
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-io/src/test/java/org/eclipse/jetty/io/ContentSourceTest.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-io/src/test/java/org/eclipse/jetty/io/AsyncContentTest.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAsyncContentTest.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAsyncContentTest.java
Outdated
Show resolved
Hide resolved
...ent-transports/src/test/java/org/eclipse/jetty/test/client/transport/ServerTimeoutsTest.java
Outdated
Show resolved
Hide resolved
That could be an All in all, I think all code needs to be revisited to make sure it can handle an non-last error/failure/warning, so I don't think this variation is necessary. |
@lorban The comment on the call last night regarding a Throwable that is an "error" but not a |
@lorban in preparing the rename I found lots of javadoc that linked through to |
renamed back to isFailure and getFailure
@lorban I have pushed the rename back to I think the distinction between "error", "failure" and "warning" would have been fine if all we were talking about was So I'm now a definitely +1 on the just call it "failure" camp. Hopefully I've done a reasonable job in the javadoc to explain transient vs persistent failures? I have also added a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few small things left.
Overall, I'm happy with this change and you're right about the purity of error vs failure vs warning that doesn't make sense in the overall picture. I'm still convinced isFailure(chunk, true)
is the right thing to do by default to check for errors, but we can re-review all that later and we don't generate transient failures for now so what we have now currently is safe. And I do agree that isFailure(chunk)
should not check the last flag. The contract totally LGTM.
jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Content.java
Outdated
Show resolved
Hide resolved
...10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/AsyncContentProducer.java
Outdated
Show resolved
Hide resolved
...-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java
Outdated
Show resolved
Hide resolved
...-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientTest.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last nit.
* @return True if the chunk is non-null and {@link Chunk#getFailure()} returns non-null | ||
* and {@link Chunk#isLast()} matches the passed status. | ||
*/ | ||
static boolean isFailure(Chunk chunk, boolean last) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is never called with last=false
?
Also, I don't think it is necessary, as if isFailed(Chunk)==true
then you can safely call chunk.isLast()
without NPE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used in lots of places, albeit mostly tests. No harm having it.
* @param chunk The chunk to test for an {@link Chunk#getError() error}. | ||
* @return True if the chunk is non-null and {@link Chunk#getError() chunk.getError()} returns non-null. | ||
*/ | ||
static boolean isError(Chunk chunk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would stick with fail(Throwable), Throwable getFailure()
and isFailed(Chunk)
.
# Conflicts: # jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/HttpInput.java
Experiment to see: