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

Improve RequestsFetcher cleanup mechanisms #1303

Closed
sechkova opened this issue Mar 11, 2021 · 4 comments
Closed

Improve RequestsFetcher cleanup mechanisms #1303

sechkova opened this issue Mar 11, 2021 · 4 comments
Labels
client Related to the client (updater) implementation enhancement

Comments

@sechkova
Copy link
Contributor

Description or feature request:
Implement RequestsFetcher as a context manager and/or provide public cleanup method to be called by its users (for ex. fetcher.close() )

Current behavior:
RequestsFetcher internlly tracks all exit paths to release allocated resources which is error prone.

Expected behavior:
Reliably release all resources allocated by RequestsFetcher.

@sechkova sechkova added client Related to the client (updater) implementation enhancement labels Mar 11, 2021
@jku
Copy link
Member

jku commented Mar 11, 2021

I think fetch() being a CM might make sense (if it makes the client code nicer) but I don't believe it makes it any easier to handle cleanup...

The only resource (that requires handling) in RequestsFetcher is the requests.Response: this is tricky because we return a generator function that owns the Response but otherwise I think there's nothing that requires attention.

fetcher.close() could not solve any issues I believe: there is no object level "context" in fetcher itself that is problematic. fetch() does have to handle the Response but that can't be fixed with more methods as once we return the generator that owns the Response, it is no longer something the fetcher should or can worry about.

@sechkova sechkova mentioned this issue Mar 15, 2021
17 tasks
@sechkova
Copy link
Contributor Author

Reviving this issue after having a look at RequestsFetcher after a while.
Implementing fetch() as a context manager makes the default TUF implementation look better because now response is closed in a single place. For example:

requests_fetcher.py:

    @contextmanager
    def fetch(self, url, required_length):
        ...
        try:
            response.raise_for_status()
            yield self._chunks(response, required_length)

        except requests.HTTPError as e:
            status = e.response.status_code
            raise exceptions.FetcherHTTPError(str(e), status)

        finally:
            response.close()

download.py:

-            chunks = self._fetcher.fetch(url, required_length)
-            for chunk in chunks:
-                temp_file.write(chunk)
-                number_of_bytes_received += len(chunk)
+            with self._fetcher.fetch(url, required_length) as chunks:
+                for chunk in chunks:
+                    temp_file.write(chunk)
+                    number_of_bytes_received += len(chunk)
+

But this also means adding a requirement to FetcherInterface.fetch() to be a context manager and I can't decide if it is adding enough value?

@jku
Copy link
Member

jku commented Sep 14, 2021

@sechkova do you think this is still an active issue -- I think moving the download methods into Fetcher have solved the issues around this? I don't see our code having trouble with unclosed things currently

@sechkova
Copy link
Contributor Author

Yeah, with download_file() being context manager and RequestsFetcher correctly cleaning up sockets, I think this is solved. Closing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client Related to the client (updater) implementation enhancement
Projects
None yet
Development

No branches or pull requests

2 participants