3333 cast , Optional , Union , Any , Tuple
3434
3535from cachetools import TTLCache , LRUCache
36+ from httpx import Response
3637
3738from .error import SchemaRegistryError
3839
@@ -70,9 +71,15 @@ def __init__(self, conf: dict):
7071 raise ValueError ("Missing required configuration property url" )
7172 if not isinstance (base_url , string_type ):
7273 raise TypeError ("url must be a str, not " + str (type (base_url )))
73- if not base_url .startswith ('http' ) and not base_url .startswith ('mock' ):
74- raise ValueError ("Invalid url {}" .format (base_url ))
75- self .base_url = base_url .rstrip ('/' )
74+ base_urls = []
75+ for url in base_url .split (',' ):
76+ url = url .strip ().rstrip ('/' )
77+ if not url .startswith ('http' ) and not url .startswith ('mock' ):
78+ raise ValueError ("Invalid url {}" .format (url ))
79+ base_urls .append (url )
80+ if not base_urls :
81+ raise ValueError ("Missing required configuration property url" )
82+ self .base_urls = base_urls
7683
7784 self .verify = True
7885 ca = conf_copy .pop ('ssl.ca.location' , None )
@@ -93,7 +100,7 @@ def __init__(self, conf: dict):
93100 raise ValueError ("ssl.certificate.location required when"
94101 " configuring ssl.key.location" )
95102
96- parsed = urlparse (base_url )
103+ parsed = urlparse (self . base_urls [ 0 ] )
97104 try :
98105 userinfo = (unquote (parsed .username ), unquote (parsed .password ))
99106 except (AttributeError , TypeError ):
@@ -219,7 +226,7 @@ def send_request(
219226 query : dict = None
220227 ) -> Any :
221228 """
222- Sends HTTP request to the SchemaRegistry.
229+ Sends HTTP request to the SchemaRegistry, trying each base URL in turn .
223230
224231 All unsuccessful attempts will raise a SchemaRegistryError with the
225232 response contents. In most cases this will be accompanied by a
@@ -250,21 +257,22 @@ def send_request(
250257 'Content-Type' : "application/vnd.schemaregistry.v1+json" }
251258
252259 response = None
253- for i in range (self .max_retries + 1 ):
254- response = self . session . request (
255- method , url = "/" . join ([ self .base_url , url ]),
256- headers = headers , data = body , params = query )
260+ for i , base_url in enumerate (self .base_urls ):
261+ try :
262+ response = self .send_http_request (
263+ base_url , url , method , headers , body , query )
257264
258- if (is_success (response .status_code )
259- or not is_retriable (response .status_code )
260- or i >= self .max_retries ):
261- break
265+ if is_success (response .status_code ):
266+ return response .json ()
262267
263- time .sleep (full_jitter (self .retries_wait_ms , self .retries_max_wait_ms , i ) / 1000 )
268+ if not is_retriable (response .status_code ) or i == len (self .base_urls ) - 1 :
269+ break
270+ except Exception as e :
271+ if i == len (self .base_urls ) - 1 :
272+ # Raise the exception since we have no more urls to try
273+ raise e
264274
265275 try :
266- if 200 <= response .status_code <= 299 :
267- return response .json ()
268276 raise SchemaRegistryError (response .status_code ,
269277 response .json ().get ('error_code' ),
270278 response .json ().get ('message' ))
@@ -275,6 +283,48 @@ def send_request(
275283 "Unknown Schema Registry Error: "
276284 + str (response .content ))
277285
286+ def send_http_request (
287+ self , base_url : str , url : str , method : str , headers : dict ,
288+ body : Optional [str ] = None , query : dict = None
289+ ) -> Response :
290+ """
291+ Sends HTTP request to the SchemaRegistry.
292+
293+ All unsuccessful attempts will raise a SchemaRegistryError with the
294+ response contents. In most cases this will be accompanied by a
295+ Schema Registry supplied error code.
296+
297+ In the event the response is malformed an error_code of -1 will be used.
298+
299+ Args:
300+ base_url (str): Schema Registry base URL
301+
302+ url (str): Request path
303+
304+ method (str): HTTP method
305+
306+ headers (dict): Headers
307+
308+ body (str): Request content
309+
310+ query (dict): Query params to attach to the URL
311+
312+ Returns:
313+ Response: Schema Registry response content.
314+ """
315+ for i in range (self .max_retries + 1 ):
316+ response = self .session .request (
317+ method , url = "/" .join ([base_url , url ]),
318+ headers = headers , data = body , params = query )
319+
320+ if is_success (response .status_code ):
321+ return response
322+
323+ if not is_retriable (response .status_code ) or i >= self .max_retries :
324+ return response
325+
326+ time .sleep (full_jitter (self .retries_wait_ms , self .retries_max_wait_ms , i ) / 1000 )
327+
278328
279329def is_success (status_code : int ) -> bool :
280330 return 200 <= status_code <= 299
@@ -495,7 +545,7 @@ class SchemaRegistryClient(object):
495545 +------------------------------+------+-------------------------------------------------+
496546 | Property name | type | Description |
497547 +==============================+======+=================================================+
498- | ``url`` * | str | Schema Registry URL. |
548+ | ``url`` * | str | Comma-separated list of Schema Registry URLs. |
499549 +------------------------------+------+-------------------------------------------------+
500550 | | | Path to CA certificate file used |
501551 | ``ssl.ca.location`` | str | to verify the Schema Registry's |
0 commit comments