mirror of
https://github.com/skoelle/icloud-contacts-sync.git
synced 2026-09-17 15:30:24 +00:00
sync retry logic
This commit is contained in:
+19
-11
@@ -15,6 +15,7 @@ antwortet der Server mit 403 valid-sync-token, dann fällt der Client automatisc
|
|||||||
auf einen vollständigen Re-Sync zurück.
|
auf einen vollständigen Re-Sync zurück.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
@@ -41,18 +42,25 @@ class CardDAVClient:
|
|||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.session = requests.Session()
|
self.session = requests.Session()
|
||||||
|
|
||||||
def _request(self, method: str, url: str, body: str, depth: str = "0"):
|
def _request(self, method: str, url: str, body: str, depth: str = "0", max_retries: int = 3):
|
||||||
headers = {"Depth": depth, "Content-Type": "application/xml; charset=utf-8"}
|
headers = {"Depth": depth, "Content-Type": "application/xml; charset=utf-8"}
|
||||||
resp = self.session.request(
|
for attempt in range(max_retries + 1):
|
||||||
method, url, data=body, headers=headers, auth=self.auth, timeout=self.timeout,
|
resp = self.session.request(
|
||||||
)
|
method, url, data=body, headers=headers, auth=self.auth, timeout=self.timeout,
|
||||||
if resp.status_code == 403 and "valid-sync-token" in resp.text:
|
)
|
||||||
raise SyncTokenInvalid("sync-token vom Server abgelehnt")
|
if resp.status_code == 403 and "valid-sync-token" in resp.text:
|
||||||
if resp.status_code == 503:
|
raise SyncTokenInvalid("sync-token vom Server abgelehnt")
|
||||||
retry_after = resp.headers.get("Retry-After")
|
if resp.status_code == 503 and attempt < max_retries:
|
||||||
logger.warning("503 Service Unavailable — Retry-After: %s", retry_after or "nicht angegeben")
|
retry_after = resp.headers.get("Retry-After")
|
||||||
resp.raise_for_status()
|
wait = int(retry_after) if retry_after and retry_after.isdigit() else 60
|
||||||
return ET.fromstring(resp.content)
|
logger.warning("503 Service Unavailable — warte %ds (Versuch %d/%d)", wait, attempt + 1, max_retries)
|
||||||
|
time.sleep(wait)
|
||||||
|
continue
|
||||||
|
if resp.status_code == 503:
|
||||||
|
retry_after = resp.headers.get("Retry-After")
|
||||||
|
logger.error("503 Service Unavailable — Retry-After: %s, alle %d Versuche aufgebraucht", retry_after or "nicht angegeben", max_retries)
|
||||||
|
resp.raise_for_status()
|
||||||
|
return ET.fromstring(resp.content)
|
||||||
|
|
||||||
def discover_principal(self) -> str:
|
def discover_principal(self) -> str:
|
||||||
body = """<?xml version="1.0" encoding="utf-8" ?>
|
body = """<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user