-
Notifications
You must be signed in to change notification settings - Fork 16
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
Return unclosed InputStreams for binary and optional<binary> endpoints #570
Conversation
38fa7e4
to
4c98652
Compare
d96c0d6
to
55aaab6
Compare
Generate changelog in
|
99509e9
to
4f9431e
Compare
import java.util.Optional; | ||
import org.assertj.core.api.Assertions; | ||
|
||
/** A test-only inputstream which can only be closed once. */ |
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.
is this true? It looks like close can be called several times, which should work correctly based on the closeable 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 found this useful because while I was refactoring, I often ended up adding close calls to several different layers which quickly got confusing as it was never quite clear which bit was actually responsible for closing everything.
I agree that the contract of Closeable doesn't require us to do this whole exactly-once thing - I just found it helpful to try and condense the closing responsibility into one place and not duplicate it.
|
||
@Override | ||
public void close() throws IOException { | ||
closeCalled = Optional.of(new SafeRuntimeException("close was called here")); |
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.
should we record only the first close invocation? subsequent close calls will replace that value.
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.
Eh, not sure it's worth the faff tbh - people can unwind one at at time :)
dialogue-client-test-lib/src/main/java/com/palantir/dialogue/TestResponse.java
Show resolved
Hide resolved
dialogue-client-verifier/src/test/java/com/palantir/verification/BinaryReturnTypeTest.java
Outdated
Show resolved
Hide resolved
dialogue-client-verifier/src/test/java/com/palantir/verification/BinaryReturnTypeTest.java
Outdated
Show resolved
Hide resolved
|
||
ResponseClosingInputStream(InputStream inputStream, Closeable response) { | ||
this.inputStream = inputStream; | ||
this.response = response; |
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.
Not sure it's necessary to pass along the response object here -- all our implementations only require the body stream to be closed, and allow Response.close as a convenience to close the body.
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.
Yeah so this was something I wasn't quite sure about - given that people are free to implement their own Response
, it seemed like there's a possibility that closing the Response and closing the InputStream could release different resources somehow...
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.
Thoughts on updating the Response javadoc to note that at least one of response or response.body must be closed, but both aren't required? That way we force implementors to handle resource release -- all our current implementations only hold resources in the body, so I don't think there's risk, and it keeps the api a touch cleaner.
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.
Have added a bit of extra wording - does this capture your intentions?
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.
👍 yep, thanks.
dialogue-serde/src/main/java/com/palantir/conjure/java/dialogue/serde/ConjureBodySerDe.java
Outdated
Show resolved
Hide resolved
…lantir/dialogue into dfox/repro-gzip-binary-response
dialogue-serde/src/main/java/com/palantir/conjure/java/dialogue/serde/Encoding.java
Outdated
Show resolved
Hide resolved
private void setBinaryGzipResponse(String stringToCompress) { | ||
undertowHandler = exchange -> { | ||
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/octet-stream"); | ||
exchange.getResponseHeaders().put(Headers.CONTENT_ENCODING, "gzip"); |
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.
We might want to assert that there's a Accept-Encoding
request header that contains gzip
to prevent confusion in the future.
dialogue-serde/src/main/java/com/palantir/conjure/java/dialogue/serde/ConjureBodySerDe.java
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.
Thanks @iamdanfox!
.describedAs("Should receive exactly the number of bytes we sent!") | ||
.isEqualTo(limit); | ||
|
||
System.out.printf("%d MB took %d millis%n", megabytes, sw.elapsed(TimeUnit.MILLISECONDS)); |
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.
maybe it's just my mac, but this takes like 28 seconds for 3GB sometimes
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.
That’s odd considering we’re using plain text http, how long does the build system take?
9766414
to
399eef3
Compare
Released 1.2.2 |
Power merging because I have green CI but Circle is queuing me really hard: https://circleci.com/workflow-run/0a2af8e1-6e2a-49c9-9f48-6b930622bae5 |
Before this PR
Dialogue's binary handling is totally broken right now, which obviously blocks usage in internal replacement for atlas.
fixes #569
After this PR
==COMMIT_MSG==
Conjure endpoints returning
binary
oroptional<binary>
now correctly return unclosed InputStreams. Users must be careful to close these InputStreams, otherwise resources will be leaked.==COMMIT_MSG==
TODO:
Possible downsides?