-
Notifications
You must be signed in to change notification settings - Fork 119
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
Initial implementation of streaming request #107
Conversation
748643d
to
fb226cf
Compare
This provides initial implementation of streaming request. The tests are missing and also possibly there may be issues with this code. This is a work in progress.
fb226cf
to
9ce2de9
Compare
Great write up! I don't think Mint would want to change to support these timeouts either, but I'm interested to hear what change you would suggest for that. To me the |
Then, we're done here. Minus HTTP2 support that I think we need to do to. @sneako any other feedback / suggestions or that's good to go? |
FYI I added some more tests and started working on HTTP2 support. |
The whole goal of Mint is so we don't spawn processes, so if our solution is to spawn processes, then I would prefer if it is kept outside of Finch/Mint, because it goes against the model we are trying to work with. As far as I understand, you can emulate the process model even if we keep things stateless in Mint, because you can make the stream itself stateful but using things like Stream.resource. So, in my mind, I would keep the model in Finch as simple as possible, so all we do is Enumerable.reduce, not even using suspend, and leave all complexity to the stream itself. |
@josevalim I understand that, we could move the whole logic of fetching the next batch of bytes to send to stream and we may want to do that. I need to think on how this will work with HTTP2 however. I don't think we care about window size / amount of bytes returned by stream in HTTP1 but HTTP2 seems to have different way to control the flow and if we send too much bytes we end up with window size errors. Correct me if I am wrong, but that leaves us with need to transform the stream / enumerable to respect window sizes ideally and moving that to the stream itself may be actually complicating things. |
@hubertlepicki http2 is a different ball game. The streaming approach with back-pressure is the best way to do it, even if with non streaming payloads (see #88). HTTP2 is also process-based, so I think you want to stream on the client and send the pieces to the server. I think you want to tackle those separately, just because of how different they are. |
Yes. Okay. I can do that. Ref. HTTP2: I actually don't know what's the policy here in this project on adding a feature that works on HTTP1 but not HTTP2. The public API is the same for both protocols. @keathley @sneako are we okay to have streaming requests working on HTTP1, but not on HTTP2 for a while, or do we want to have both merged / done at the same time? We could also accept |
I'm ok with just adding this for HTTP/1 initially and documenting that it isn't supported for H2 yet, since H2 really needs these window size updates before it can be as robust as our current HTTP/1 support is, but let's see what @keathley thinks too. |
Suggested by @josevalim, streaming request now leaves the option to generate the chunks of data to stream itself, reducing amount of logic we need to add to this module.
Is this what you had in mind @josevalim ? keathley@ea42f8f#diff-48431cc1d91063480b5006d7585c96ea39433e319aca2b5e3a6c597fdbd7e10fR146 |
any update on this guys? Can it be merged? |
There are still some outstanding comments to be addressed... |
Yes, i am aware. Will look into it later today.
niedz., 13 gru 2020, 14:29 użytkownik nico piderman <
notifications@github.com> napisał:
… any update on this guys? Can it be merged?
There are still some outstanding comments to be addressed...
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/keathley/finch/pull/107#issuecomment-744007999>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAID6RTZJH24Y3FNKQXOSDSUS6STANCNFSM4UFZV5TQ>
.
|
No rush, that was just meant as a reply to @ijunaid8989 😁 |
I have responded to him too on Elixir forum, that another pair of eyes on
this would be welcome too. It kinda feels like I am the only one using it
so far (because, i probably am) and more eyes / use of this would be great.
niedz., 13 gru 2020, 16:03 użytkownik nico piderman <
notifications@github.com> napisał:
… Yes, i am aware. Will look into it later today.
niedz., 13 gru 2020, 14:29 użytkownik nico piderman <
***@***.***> napisał:
any update on this guys? Can it be merged?
There are still some outstanding comments to be addressed...
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#107 (comment)
<https://github.com/keathley/finch/pull/107#issuecomment-744007999>, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAAID6RTZJH24Y3FNKQXOSDSUS6STANCNFSM4UFZV5TQ
.
No rush, that was just meant as a reply to @ijunaid8989
<https://github.com/ijunaid8989> 😁
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/keathley/finch/pull/107#issuecomment-744020312>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAID6QRYZNSAENDBRDUNI3SUTJVXANCNFSM4UFZV5TQ>
.
|
Renames function track_response_telemetry into handle_response, also uses Enum.reduce_while instead of Enumerable.reduce directly. Both things requested druring code review.
@sneako whenever you have some time, I did two of 3 requested things. I think the third thing, i.e. Telemetry.stop(:request) should in fact stay the way it is now. Let me know otherwise |
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.
Nice, I think this is getting very close to ready now. I would like to see just a bit of documentation about passing the :stream tuple as the request body and also a note that only HTTP/1 supports this at the moment
@sneako perfect, I'll do that. I also plan to have a go at adding some more over all documentation and examples after that to this project, unless you want to stop me for some reason. I think at the moment it's pretty sparse over all. |
A follow up PR improving the existing documentation would definitely be appreciated, I agree it is a bit sparse at the moment, thanks! |
Hi sorry for commenting here but its stream related. Right now in HTTPoison, we are doing this.
is it possible to do streaming in finch especially in this PR. |
@ijunaid8989 yes, and you don't need that PR for that. The PR is for sending out the data in streaming fashion. You want to read the data in streaming fashion it seems. You can also do both (on this pr/branch so far). For streaming responses you need to replace your request function call with "stream" function call: https://hexdocs.pm/finch/Finch.html#stream/5 |
@hubertlepicki Okay great thank you. so after this merge, We can send a POST multipart request, and nothing will change just, where the body was json, it will accept such data as well
this is a result of |
@ijunaid8989 did you try simply building and sending a request with this body? I think the ElixirForum, or Slack are probably more appropriate places to continue your discussion as to not derail our discussion here. |
No, I have not tried. I also don't think this is in any way related to the PR nor it is a good place to further discuss it either. I also think this may not be a stream in first place but a binary. |
Co-authored-by: nico piderman <nico.piderman@gmail.com>
Co-authored-by: nico piderman <nico.piderman@gmail.com>
Co-authored-by: nico piderman <nico.piderman@gmail.com>
Remove unnecessary anonymous function call. Extract stream_request_body/3 function to let us replace pipe to case with a `with` clause. mix format.
Final tweaks to request streaming before merge
@hubertlepicki thanks for working through this with me, really appreciate the contribution! |
A pleasure.
If you want to wait with making a release, I can deploy the master to our
staging system to test it in real life. I don't suppose anything breaks, as
it's already running production on my branch without some recent tweaks,
but I will do it anyway tomorrow.
wt., 15 gru 2020, 21:16 użytkownik nico piderman <notifications@github.com>
napisał:
… @hubertlepicki <https://github.com/hubertlepicki> thanks for working
through this with me, really appreciate the contribution!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/keathley/finch/pull/107#issuecomment-745541182>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAID6VJCNNWAXVHGKTKB43SU67YRANCNFSM4UFZV5TQ>
.
|
Ah sorry, I missed your comment. Appreciate the offer, but I have already released version 0.6.0 Let me know how it goes! |
No worries, I will do and report back tomorrow. Thanks!
wt., 15 gru 2020, 21:24 użytkownik nico piderman <notifications@github.com>
napisał:
… Ah sorry, I missed your comment. Appreciate the offer, but I have already
released version 0.6.0
Let me know how it goes!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/keathley/finch/pull/107#issuecomment-745545939>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAID6WRMWVDTFPDVLJ4OODSU7AYVANCNFSM4UFZV5TQ>
.
|
@sneako I am about to test this thing on staging, so far so good. Will keep you posted. One thing I noticed is that you have forgotten to push a tag v0.6.0 to GitHub so that it doesn't show up on the list. There's couple of semi-related things I'd like to discuss, will open a separate tickets instead of continuing here. |
|
👍 Great thank you, that makes easier to figure out for people what they are actually using. Ref. the other things, I actually opened an issue on Tesla. I would be interested in hearing from you (and / or @keathley ) what your view is on the idea: elixir-tesla/tesla#437 |
Extracting that module to a separate lib makes sense to me. I don't think we would want to add similar functionality directly to Finch, so your proposal could be a good way around that 👍 |
This provides support for streaming request body with Elixir streams and Enumerable.reduce like @josevalim suggested.
I have tested this with fairly large files and it doesn't seem to be having any negative effect on memory with or without wrapping the streaming of body into Task.
@sneako suggested we don't do Task to to wrap streaming request body. @josevalim suggested we'd better wrap the whole operation in a process if we want to control the timeout on streaming request body. Here is the conversation for reference: https://elixirforum.com/t/memory-leak-binaries-that-only-recon-bin-leak-1-helps-with/35804/10
I am, however, getting to conclusion that maybe we should not be handling that directly in Finch, and instead have a
timeout
parameter on Mint.HTTP.stream_request_body/3. This is so we are consistent with what we do on both sending and receiving sides. Mint accepts atimeout
option when receiving the payload, or establishing a connection, but does not accept a timeout option when sending payload to the server (or making a request in general), or streaming.I think what we should be doing on Finch and other higher-level clients is to appropriately handle splitting / calculating overall and individual timeouts per chunks of data we send, but add option to Mint itself to have timeout option available when we send data to server. So, we'd add the option here, maybe also here and then to appropriate transport, in our case http1 so places like here and several other places.
So I suggest we don't try to solve this in Finch now, instead build building blocks for easily solving it in Mint, and then come back to improve the library with timeout options on sending request payload.
There is a problem here, however, in that
:gen_tcp
does not support timeout on send either. So this would have to be entirely contained within Mint I think.There is also option to play with
send_timeout
, which I think defaults to something like 3 hours:If we want to do it, however, entirely in Finch, then I don't see problem with using Task / spawned process that streams the data from it. According to my tests it works just fine.
What do you folks think?