Merge ~adam-collard/simplestreams:timeout-mirror into simplestreams:master

Proposed by Adam Collard
Status: Merged
Approved by: Paride Legovini
Approved revision: b09f3a2230be425c588a0cb3288476f35eb17ef3
Merge reported by: Server Team CI bot
Merged at revision: not available
Proposed branch: ~adam-collard/simplestreams:timeout-mirror
Merge into: simplestreams:master
Diff against target: 32 lines (+5/-2)
1 file modified
simplestreams/contentsource.py (+5/-2)
Reviewer Review Type Date Requested Status
Paride Legovini Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+397354@code.launchpad.net

Commit message

Add 10s timeout to out-going requests to avoid blocking.

Fixes LP:1908452

Description of the change

Suggestions on how to best test this are welcome

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
dann frazier (dannf) wrote :

I do wonder if it makes sense for python3-simplestreams to be instituting "One True Timeout" value for every caller, since I imagine that is application/environment-dependent. IMHO, it seems like simplestreams could expose a new timeout parameter (possibly with a non-zero default) in it's class init() methods that callers could override.

For MAAS, for example, I think a 10s timeout could still result in noticeable UI latency issues (every 4th regiond API call could hang for up to 10s during a sync), so it might want to select something smaller. However, command line tools like those included in simplestreams would likely prefer to be more patient.

Revision history for this message
dann frazier (dannf) wrote :

Oh, and regarding testing, here's the best reproducer I've come up with:
  https://bugs.launchpad.net/maas/+bug/1908452/comments/19

Unfortunately it's not a great option for an automated test case. Perhaps using a python-based https server w/ an intentionally broken handshake would work?

Revision history for this message
Paride Legovini (paride) wrote :

LGTM. It is not easy to test this in a way that is meaningful for simplestreams, and this MP is a plain implementation of what's recommended by requests for production code ([1], as ltrager pointed out). I think we can land this.

[1] https://requests.readthedocs.io/en/master/user/quickstart/#timeouts

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/simplestreams/contentsource.py b/simplestreams/contentsource.py
2index 40bf9d0..b54e898 100644
3--- a/simplestreams/contentsource.py
4+++ b/simplestreams/contentsource.py
5@@ -32,6 +32,7 @@ else:
6 urllib_error = urllib_request
7
8 READ_BUFFER_SIZE = 1024 * 10
9+TIMEOUT = 10
10
11 try:
12 # We try to use requests because we can do gzip encoding with it.
13@@ -338,7 +339,7 @@ class Urllib2UrlReader(UrlReader):
14 req.add_header('User-Agent', user_agent)
15 if offset is not None:
16 req.add_header('Range', 'bytes=%d-' % offset)
17- self.req = opener(req)
18+ self.req = opener(req, timeout=TIMEOUT)
19 except urllib_error.HTTPError as e:
20 if e.code == 404:
21 myerr = IOError("Unable to open %s" % url)
22@@ -378,7 +379,9 @@ class RequestsUrlReader(UrlReader):
23 if headers == {}:
24 headers = None
25
26- self.req = requests.get(url, stream=True, auth=auth, headers=headers)
27+ self.req = requests.get(
28+ url, stream=True, auth=auth, headers=headers, timeout=TIMEOUT
29+ )
30 self.r_iter = None
31 if buflen is None:
32 buflen = READ_BUFFER_SIZE

Subscribers

People subscribed via source and target branches