forked from kubernetes-client/python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_go_retry_asyncio_patch.diff
More file actions
99 lines (94 loc) · 3.63 KB
/
Copy pathclient_go_retry_asyncio_patch.diff
File metadata and controls
99 lines (94 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
diff --git a/kubernetes/aio/client/configuration.py b/kubernetes/aio/client/configuration.py
--- a/kubernetes/aio/client/configuration.py
+++ b/kubernetes/aio/client/configuration.py
@@ -355,6 +355,22 @@
self.retries = retries
"""Retry configuration
"""
+ self.client_go_retries = False
+ """Enable Kubernetes client-go-compatible retry semantics.
+
+ When enabled, GET and HEAD requests retry Retry-After responses.
+ The retry ceiling is read from ``retries`` when set; otherwise it
+ follows the client-go default of at most 10 retries.
+ """
+ self.client_go_retry_backoff = None
+ """Backoff for Kubernetes client-go-compatible retries.
+
+ If unset, client-go-compatible GET and HEAD retries use the
+ client-go default retry ceiling with no additional client-side
+ delay beyond Retry-After. When set, ``retries`` still overrides
+ the retry ceiling if it is not None.
+ """
+
self.trace_configs = trace_configs
"""aiohttp.TraceConfig list forwarded to ClientSession for tracing.
"""
diff --git a/kubernetes/aio/client/rest.py b/kubernetes/aio/client/rest.py
--- a/kubernetes/aio/client/rest.py
+++ b/kubernetes/aio/client/rest.py
@@ -21,6 +21,11 @@
import aiohttp
import aiohttp_retry
+from kubernetes.aio.utils.retry import (
+ is_retry_after_response,
+ on_retry_after_error,
+ retry_after_backoff,
+)
from kubernetes.aio.client.exceptions import ApiException, ApiValueError
RESTResponseType = aiohttp.ClientResponse
@@ -284,7 +289,16 @@
self.pool_manager = self._create_pool_manager()
pool_manager = self.pool_manager
- if self._effective_retry_options is not None and method in ALLOW_RETRY_METHODS:
+ client_go_read_retries = (
+ method in ['GET', 'HEAD']
+ and getattr(self.configuration, 'client_go_retries', False)
+ )
+
+ if (
+ self._effective_retry_options is not None
+ and method in ALLOW_RETRY_METHODS
+ and not client_go_read_retries
+ ):
if self.retry_client is None:
self.retry_client = aiohttp_retry.RetryClient(
client_session=self.pool_manager,
@@ -292,6 +306,38 @@
)
pool_manager = self.retry_client
- r = await pool_manager.request(**args)
+ async def read_request(check_retry_status=False):
+ response = await self.pool_manager.request(**args)
+ if check_retry_status:
+ self._raise_retry_after_response(response)
+ return response
+
+ if client_go_read_retries:
+ backoff = retry_after_backoff(
+ getattr(self.configuration, 'retries', None),
+ getattr(self.configuration, 'client_go_retry_backoff', None),
+ )
+ r = await on_retry_after_error(
+ backoff, self._is_read_retryable, lambda: read_request(True))
+ else:
+ r = await pool_manager.request(**args)
return RESTResponse(r)
+
+ @classmethod
+ def _is_read_retryable(cls, error):
+ return is_retry_after_response(error)
+
+ @staticmethod
+ def _retry_after_error(response):
+ error = ApiException(status=response.status, reason=response.reason)
+ error.headers = response.headers
+ return error
+
+ @classmethod
+ def _raise_retry_after_response(cls, response):
+ error = cls._retry_after_error(response)
+ if not is_retry_after_response(error):
+ return
+ response.release()
+ raise error