refactor: switch from async to sync http client

feat: bump version to 1.13.0
docs: update changelog with release notes
This commit is contained in:
2025-11-07 18:17:58 +01:00
parent a2468b7d5b
commit 6509ccc5d3
3 changed files with 30 additions and 27 deletions
+21 -26
View File
@@ -1,4 +1,3 @@
import asyncio
import json
import logging
import socket
@@ -10,11 +9,11 @@ from typing import Dict, Any, Optional
logger = logging.getLogger("pr")
class AsyncHTTPClient:
class SyncHTTPClient:
def __init__(self):
self.session_headers = {}
async def request(
def request(
self,
method: str,
url: str,
@@ -23,9 +22,7 @@ class AsyncHTTPClient:
json_data: Optional[Dict[str, Any]] = None,
timeout: float = 30.0,
) -> Dict[str, Any]:
"""Make an async HTTP request using urllib in a thread executor with retry logic."""
loop = asyncio.get_event_loop()
"""Make a sync HTTP request using urllib with retry logic."""
# Prepare headers
request_headers = {**self.session_headers}
if headers:
@@ -46,22 +43,20 @@ class AsyncHTTPClient:
while True:
attempt += 1
try:
# Execute in thread pool
response = await loop.run_in_executor(
None, lambda: urllib.request.urlopen(req, timeout=timeout)
)
response_data = await loop.run_in_executor(None, response.read)
response_text = response_data.decode("utf-8")
# Execute request
with urllib.request.urlopen(req, timeout=timeout) as response:
response_data = response.read()
response_text = response_data.decode("utf-8")
return {
"status": response.status,
"headers": dict(response.headers),
"text": response_text,
"json": lambda: json.loads(response_text) if response_text else None,
}
return {
"status": response.status,
"headers": dict(response.headers),
"text": response_text,
"json": lambda: json.loads(response_text) if response_text else None,
}
except urllib.error.HTTPError as e:
error_body = await loop.run_in_executor(None, e.read)
error_body = e.read()
error_text = error_body.decode("utf-8")
return {
"status": e.code,
@@ -86,7 +81,7 @@ class AsyncHTTPClient:
)
# Exponential backoff starting at 1 second
await asyncio.sleep(attempt)
time.sleep(attempt)
except Exception as e:
error_msg = str(e)
# For other exceptions, check if they might be timeout-related
@@ -106,17 +101,17 @@ class AsyncHTTPClient:
)
# Exponential backoff starting at 1 second
await asyncio.sleep(attempt)
time.sleep(attempt)
else:
# Non-timeout errors should not be retried
return {"error": True, "exception": error_msg}
async def get(
def get(
self, url: str, headers: Optional[Dict[str, str]] = None, timeout: float = 30.0
) -> Dict[str, Any]:
return await self.request("GET", url, headers=headers, timeout=timeout)
return self.request("GET", url, headers=headers, timeout=timeout)
async def post(
def post(
self,
url: str,
headers: Optional[Dict[str, str]] = None,
@@ -124,7 +119,7 @@ class AsyncHTTPClient:
json_data: Optional[Dict[str, Any]] = None,
timeout: float = 30.0,
) -> Dict[str, Any]:
return await self.request(
return self.request(
"POST", url, headers=headers, data=data, json_data=json_data, timeout=timeout
)
@@ -133,4 +128,4 @@ class AsyncHTTPClient:
# Global client instance
http_client = AsyncHTTPClient()
http_client = SyncHTTPClient()