-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Issue/544 reactive streams support #963
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
Issue/544 reactive streams support #963
Conversation
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(QueueBackedSubscriber.class); | ||
|
||
private final BlockingQueue<ByteBuffer> queue; |
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.
Blocking, really?
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.
The alternative is queuing up elements in the subscriber, but the risk with that is overflowing the queue (dropping elements is even worse) when the consumer is much slower than the producer. Also, note this implementation is only used when the provider doesn't support reactive streams.
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.
Also, note this implementation is only used when the provider doesn't support reactive streams.
I'd rather throw an UnsupportedOperationException
then. :)
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.
Mmm, I'm looking at the implementation of FeedableBodyGenerator
and realise I probably don't need blocking. Forgive me :-)
Hi Mirko, I think your |
// don't overflow the passed buffer | ||
if(buffer.remaining() <= lastElement.remaining()) { | ||
int bufferSize = buffer.remaining(); | ||
buffer.put(lastElement.array(), lastElement.position(), bufferSize); |
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.
What if the buffer doesn't have an array?
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.
Oh, is that possible? Any idea how I should handle that? (should I create the array myself, or fail?)
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.
Oh, is that possible?
Of course: DirectBuffers, composites, etc. That's what hasArray()
is for.
See
FeedableBodyGenerator
, you can put a ByteBuffer into another.
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.
@dotta the netty in action cover this:).composites could have array if it have only one element and the element have array or it was empty.
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.
@hepin1989 Don't confuse Netty's ByteBuf
and Java's ByteBuffer
:)
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.
@slandelle haha,sorry,I don't see the whole context:).
Hi @slandelle, thanks a lot for the feedback!
Do you mean the implementation of |
Yeah, they serve the same purpose, so I guess existing code could be reuse/extended/wrapped. |
executor.execute(new Runnable() { | ||
@Override | ||
public void run() { | ||
subscription.request(1); |
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.
@jroper I'm not so convinced about requesting only one element at a time. Any thought?
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.
Considering this is a fallback implementation, I think it's fine. Another option, seeing as the provider is going to end up buffering infinitely anyway, is you can invoke subscription.request(Long.MAX_VALUE)
in onSubscribe
, this is allowed according to reactive streams spec 3.17.
@slandelle I think you should be more pleased now (I for sure am :-)). |
@@ -0,0 +1,11 @@ | |||
package org.asynchttpclient.request.body.generator; | |||
|
|||
public interface IFeedableBodyGenerator { |
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.
For consistency, I'd rather remove the I
prefix and prefix the default implementation with Simple
(or better if you can think of something).
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.
👍
@@ -0,0 +1,68 @@ | |||
/* | |||
* Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved. |
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.
Please change copyright to "the AsyncHttpClient Project".
a7b7b08
to
f91bac1
Compare
@slandelle I believe I've addressed all comments. The only pending one is #963 (comment), which you are discussing with @jroper. Let me know if you have other comments, or if I should rebase and squash commits. |
@slandelle I'm happy to squash commits and rebase if you give me your bless :-) In the meanwhile, I'll update Play master to take advantage of the changes in this PR. Whohoo! |
@dotta Sorry, had some unexpected things to deal with first... Yes, could you please squash and rebase? Let's merge this so everyone can move forward and get everything stable in the next weeks so we can release 2.0.0. |
Whohooo! I'm on it, thanks! :-) |
a373a21
to
71c658c
Compare
Issue/544 reactive streams support
@slandelle Thank you for merging! I'm updating the Play codebase to use AHC master, will let you know if I hit any issue. |
Great! |
I believe it's November 2015, but I'll let @jroper confirm. Once I've verified that things work properly on the Play side, I'd really appreciate if you could release a 2.0.0 milestone (in case you would like to wait a bit more before cutting a 2.0.0 final). |
I can easily cut an alpha. I'm still considering some refactorings (maybe Proxies) + I might want to break a few things to improve DNS handling in Gatling. |
Sounds good. I'll ping you soon :-) |
@slandelle I've a branch in Play that is now using the new |
I just released 2.0.0-alpha9. |
Thanks @slandelle! |
@slandelle Thank you! |
Here is an initial proposal to fix #544.
I'm entirely new to both Netty and AHC, so if you notice anything weird it's very likely that I haven't understood something :-)
Other than that, something is puzzling me with the tests I wrote. Basically, if I change theCHUNK_SIZE
in https://github.com/AsyncHttpClient/async-http-client/compare/AsyncHttpClient:master...dotta:issue/544-reactive-streams-support?expand=1#diff-5133f4e3fed98f7a99081a1ae643c4c0R104 to a value around20000
(or lower), the tests start to fail because there is a mismatch between the received bytes and the expected ones. I honestly have no good explanation for this, but I thought it may have something to do with the internals of Netty (or maybe a config flag?). I'd really appreciate it if someone more experienced with Netty could have a look.EDIT: This issue is now fixed after using RxJava instead of providing my own implementation of
Publisher
in the test :-)This PR also includes @jroper commit to add support for handling response bodies.