Skip to content
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

Ignore :into collectable for non-200 responses #435

Merged
merged 4 commits into from
Nov 24, 2024

Conversation

jonatanklosko
Copy link
Contributor

Currently when we pass into: collectable, the body is streamed into the collectable, regardless the status. This can be problematics for collectables with side effects. For example, I imagine a common use case may be into: File.stream!(path) to download a file, and in case of an error, we would save error message body instead.

There is one concern, that I'm not sure how to solve, hence a draft (details in separate comment).

{:status, status}, {acc, req, resp} ->
{acc, req, %{resp | status: status}}
{:status, 200}, {nil, req, resp} ->
{acc, collector} = Collectable.into(collectable)
Copy link
Contributor Author

@jonatanklosko jonatanklosko Nov 22, 2024

Choose a reason for hiding this comment

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

Technically we should call collector.(:halt) in case of an error. It wasn't the case in the existing code, but I assume that's unexpected.

The issue is that Finch.stream doesn't return the accumulator in case of errors, so we have no access to {acc, collector}. In the previous code this could've been fixed, because we call Collectable.into(collectable) at the top, but with the new code it's not possible. However, I do think we should only call Collectable.into(collectable) if we know the status is 200, since this call may have side effects (such as creating a file).

@wojtekmach @josevalim any ideas?

Choose a reason for hiding this comment

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

Maybe we should change Finch to return the accumulator? Or do you mean the Collector never returns the accumulator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe we should change Finch to return the accumulator?

Yeah, I think that's exactly what we would need, I'm just not sure if that breaking change is acceptable :D

Choose a reason for hiding this comment

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

It is not v1.0 yet. Plus, who is halting a collectable anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

FTR I will send a PR to finch. I guess it's not blocking this PR, since we hasn't been halting so far either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

test/req/finch_test.exs Outdated Show resolved Hide resolved
test/req/finch_test.exs Outdated Show resolved Hide resolved
@wojtekmach
Copy link
Owner

cc @acalejos, I think you run into this recently!

@acalejos
Copy link

cc @acalejos, I think you run into this recently!

Yes I think I did! When a redirect occurred, if they body of the redirecting URL wasn't empty it would trigger the :into function. Expected behavior IMO would be for it to only trigger after all redirects, but Im not sure if it's possible for it to be aware of any redirects at the point when :into is called since it's called before response steps and redirects aren't always enabled

@jonatanklosko
Copy link
Contributor Author

jonatanklosko commented Nov 23, 2024

it would trigger the :into function

@acalejos you mean into: fn {:data, data}, {req, resp} ->, right? Since you have resp at that point, you could just pattern match on the resp status, and if it's not 200, you ignore the data, so a redirect would just go through. Though one could make an argument that it should only be called on 200 as well, and if needed we can have a option into_on_any_status: true applicable to both. But then the final question is what about :self, perhaps on non-200 req receives all messages itself and doesn't return async body? @wojtekmach I can send PR for any of these, just let me know :)

That said, this PR does fix the redirect case for into: collectable. Previously a redirect could result in the collectable invoked multiple times. Now, it will only happen for the final 200 response.

@acalejos
Copy link

@jonatanklosko

Yes, it was :into a function for my case (seen here: https://github.com/acalejos/Reed/blob/64832bc789916e0b2a7ab5347328833846846113/lib/reed/req_plugin.ex#L44)

You're right I should pattern match on the status in the resp. I think for now Im just letting the XML parser error on the data and rescuing it and letting that be the way to ignore it, so I should change that 😅

@wojtekmach wojtekmach merged commit a044101 into wojtekmach:main Nov 24, 2024
2 checks passed
@wojtekmach
Copy link
Owner

Thank you!

@jonatanklosko jonatanklosko deleted the jk-into-collectable-errors branch November 25, 2024 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants