mirror of
https://github.com/openSUSE/osc.git
synced 2025-11-01 20:12:15 +01:00
Implement retries in 'git-obs'
This commit is contained in:
@@ -1,18 +1,17 @@
|
|||||||
import copy
|
import copy
|
||||||
import http.client
|
import http.client
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import urllib3
|
import urllib3
|
||||||
|
import urllib3.exceptions
|
||||||
import urllib3.response
|
import urllib3.response
|
||||||
|
|
||||||
from .conf import Login
|
from .conf import Login
|
||||||
|
|
||||||
|
|
||||||
# TODO: retry, backoff, connection pool?
|
|
||||||
|
|
||||||
|
|
||||||
class GiteaHTTPResponse:
|
class GiteaHTTPResponse:
|
||||||
"""
|
"""
|
||||||
A ``urllib3.response.HTTPResponse`` wrapper
|
A ``urllib3.response.HTTPResponse`` wrapper
|
||||||
@@ -52,6 +51,16 @@ class Connection:
|
|||||||
self.port = alternative_port if alternative_port else parsed_url.port
|
self.port = alternative_port if alternative_port else parsed_url.port
|
||||||
self.conn = ConnectionClass(host=self.host, port=self.port)
|
self.conn = ConnectionClass(host=self.host, port=self.port)
|
||||||
|
|
||||||
|
# retries; variables are named according to urllib3
|
||||||
|
self.retry_count = 3
|
||||||
|
self.retry_backoff_factor = 2
|
||||||
|
self.retry_status_forcelist = (
|
||||||
|
500, # Internal Server Error
|
||||||
|
502, # Bad Gateway
|
||||||
|
503, # Service Unavailable
|
||||||
|
504, # Gateway Timeout
|
||||||
|
)
|
||||||
|
|
||||||
if hasattr(self.conn, "set_cert"):
|
if hasattr(self.conn, "set_cert"):
|
||||||
# needed to avoid: AttributeError: 'HTTPSConnection' object has no attribute 'assert_hostname'. Did you mean: 'server_hostname'?
|
# needed to avoid: AttributeError: 'HTTPSConnection' object has no attribute 'assert_hostname'. Did you mean: 'server_hostname'?
|
||||||
self.conn.set_cert()
|
self.conn.set_cert()
|
||||||
@@ -95,9 +104,28 @@ class Connection:
|
|||||||
|
|
||||||
body = json.dumps(json_data) if json_data else None
|
body = json.dumps(json_data) if json_data else None
|
||||||
|
|
||||||
|
for retry in range(1 + self.retry_count):
|
||||||
|
# 1 regular request + ``self.retry_count`` retries
|
||||||
|
try:
|
||||||
self.conn.request(method, url, body, headers)
|
self.conn.request(method, url, body, headers)
|
||||||
response = self.conn.getresponse()
|
response = self.conn.getresponse()
|
||||||
|
|
||||||
|
if response.status not in self.retry_status_forcelist:
|
||||||
|
# we are happy with the response status -> use the response
|
||||||
|
break
|
||||||
|
|
||||||
|
if retry >= self.retry_count:
|
||||||
|
# we have reached maximum number of retries -> use the response
|
||||||
|
break
|
||||||
|
|
||||||
|
except (urllib3.exceptions.HTTPError, ConnectionResetError):
|
||||||
|
if retry >= self.retry_count:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# {backoff factor} * (2 ** ({number of previous retries}))
|
||||||
|
time.sleep(self.retry_backoff_factor * (2 ** retry))
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
if isinstance(response, http.client.HTTPResponse):
|
if isinstance(response, http.client.HTTPResponse):
|
||||||
result = GiteaHTTPResponse(urllib3.response.HTTPResponse.from_httplib(response))
|
result = GiteaHTTPResponse(urllib3.response.HTTPResponse.from_httplib(response))
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user