Skip to content

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

Merged

Conversation

dotta
Copy link
Contributor

@dotta dotta commented Sep 1, 2015

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 the CHUNK_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 around 20000 (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.


private static final Logger LOGGER = LoggerFactory.getLogger(QueueBackedSubscriber.class);

private final BlockingQueue<ByteBuffer> queue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking, really?

Copy link
Contributor Author

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.

Copy link
Contributor

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. :)

Copy link
Contributor Author

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 :-)

@slandelle
Copy link
Contributor

Hi Mirko,

I think your ReactiveStreamBodyGenerator is broken. Are you sure it cannot be implemented on top of FeedableBodyGenerator?

// don't overflow the passed buffer
if(buffer.remaining() <= lastElement.remaining()) {
int bufferSize = buffer.remaining();
buffer.put(lastElement.array(), lastElement.position(), bufferSize);
Copy link
Contributor

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?

Copy link
Contributor Author

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?)

Copy link
Contributor

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.

Copy link

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.

Copy link
Contributor

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 :)

Copy link

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:).

@dotta
Copy link
Contributor Author

dotta commented Sep 1, 2015

Hi @slandelle, thanks a lot for the feedback!

I think your ReactiveStreamBodyGenerator is broken. Are you sure it cannot be implemented on top of FeedableBodyGenerator?

Do you mean the implementation of ReactiveStreamBodyGenerator.StreamedBody? After looking at the FeedableBodyGenerator.PushBody, I feel like I should be able to reuse it. I'll have a deeper look now.

@slandelle
Copy link
Contributor

Do you mean the implementation of ReactiveStreamBodyGenerator.StreamedBody? After looking at the FeedableBodyGenerator.PushBody, I feel like I should be able to reuse it. I'll have a deeper look now.

Yeah, they serve the same purpose, so I guess existing code could be reuse/extended/wrapped. FeedableBodyGenerator.PushBody currently has a known issue that the reading buffer has to be larger than the payload, but that's something that can/should be fixed.

executor.execute(new Runnable() {
@Override
public void run() {
subscription.request(1);
Copy link
Contributor Author

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?

Copy link
Contributor

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.

@dotta
Copy link
Contributor Author

dotta commented Sep 1, 2015

@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 {
Copy link
Contributor

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).

Copy link
Contributor Author

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.
Copy link
Contributor

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".

@dotta dotta force-pushed the issue/544-reactive-streams-support branch from a7b7b08 to f91bac1 Compare September 2, 2015 14:58
@dotta
Copy link
Contributor Author

dotta commented Sep 2, 2015

@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
Copy link
Contributor

@dotta @jroper Sorry, busy day. Will have a look this week-end.

@dotta
Copy link
Contributor Author

dotta commented Sep 7, 2015

@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!

@slandelle
Copy link
Contributor

@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.

@dotta
Copy link
Contributor Author

dotta commented Sep 7, 2015

Whohooo! I'm on it, thanks! :-)

@dotta dotta force-pushed the issue/544-reactive-streams-support branch from a373a21 to 71c658c Compare September 7, 2015 13:49
@slandelle slandelle added this to the 2.0.0 milestone Sep 7, 2015
slandelle added a commit that referenced this pull request Sep 7, 2015
@slandelle slandelle merged commit fc870d8 into AsyncHttpClient:master Sep 7, 2015
@dotta dotta deleted the issue/544-reactive-streams-support branch September 7, 2015 14:15
@slandelle
Copy link
Contributor

@jroper @dotta Thanks guys!

@dotta
Copy link
Contributor Author

dotta commented Sep 7, 2015

@slandelle Thank you for merging!

I'm updating the Play codebase to use AHC master, will let you know if I hit any issue.

@slandelle
Copy link
Contributor

Great!
What's your timeline for Play 2.5?

@dotta
Copy link
Contributor Author

dotta commented Sep 7, 2015

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).

@slandelle
Copy link
Contributor

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.

@dotta
Copy link
Contributor Author

dotta commented Sep 7, 2015

Sounds good. I'll ping you soon :-)

@dotta
Copy link
Contributor Author

dotta commented Sep 8, 2015

@slandelle I've a branch in Play that is now using the new StreamedAsyncHandler, and it seems to be working just fine (and I'm really pleased with the result, the code is much, much, much easier to read now!). Could you cut a release so that I can push that work in Play?

@slandelle
Copy link
Contributor

I just released 2.0.0-alpha9.
Cheers!

@jroper
Copy link
Contributor

jroper commented Sep 8, 2015

Thanks @slandelle!

@dotta
Copy link
Contributor Author

dotta commented Sep 9, 2015

@slandelle Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Backpressure in AsyncHandler
4 participants