@@ -21,9 +21,6 @@ def parse_location(location) -> Optional[str]:
2121
2222
2323class ImmunisationApi :
24- MAX_RETRIES = 5
25- STANDARD_REQUEST_DELAY_SECONDS = 1
26-
2724 url : str
2825 headers : dict
2926 auth : BaseAuthentication
@@ -50,17 +47,38 @@ def __str__(self):
5047 # The e2e tests put pressure on both test environments from APIGEE and PDS
5148 # so the chances of having rate limiting errors are high especially during
5249 # the busy times of the day.
53- def _make_request_with_backoff (
54- self ,
50+ @ staticmethod
51+ def make_request_with_backoff (
5552 http_method : str ,
5653 url : str ,
57- expected_status_code : int ,
54+ headers : dict = None ,
55+ expected_status_code : int = 200 ,
56+ expected_connection_failure : bool = False ,
57+ max_retries : int = 5 ,
58+ is_status_check : bool = False ,
5859 ** kwargs
5960 ):
60- for attempt in range (self . MAX_RETRIES ):
61+ for attempt in range (max_retries ):
6162 try :
62- response = requests .request (http_method , url , ** kwargs )
63-
63+ response = requests .request (method = http_method , url = url , headers = headers , ** kwargs )
64+
65+ # This property is false by default and only true during the mtls test to simulate a connection failure
66+ if expected_connection_failure :
67+ raise RuntimeError (
68+ f"Expected the connection to fail, "
69+ f"but it succeeded instead.\n "
70+ f"Request method: { http_method } \n "
71+ f"URL: { url } "
72+ )
73+
74+ # Sometimes it can take time for the new endpoint to activate
75+ if is_status_check :
76+ body = response .json ()
77+ if body ["status" ].lower () != "pass" :
78+ raise RuntimeError (f"Server status check at { url } returned status code { response .status_code } , "
79+ f"but status is: { body ['status' ]} " )
80+
81+ # Check if the response matches the expected status code to identify potential issues
6482 if response .status_code != expected_status_code :
6583 if response .status_code >= 500 :
6684 raise RuntimeError (f"Server error: { response .status_code } during "
@@ -72,18 +90,17 @@ def _make_request_with_backoff(
7290 return response
7391
7492 except Exception as e :
75- if attempt == self . MAX_RETRIES - 1 :
93+ if expected_connection_failure or attempt == max_retries - 1 :
7694 raise
7795
78- wait = (2 ** attempt ) + random .uniform (0 , 0.5 )
79- total_wait_time = wait + self .STANDARD_REQUEST_DELAY_SECONDS
80-
96+ # This is will be used in the retry logic of the exponential backoff
97+ delay = (3 ** attempt ) + random .uniform (0 , 0.5 )
8198 print (
8299 f"[{ datetime .now ():%Y-%m-%d %H:%M:%S} ] "
83- f"[Retry { attempt + 1 } ] { http_method .upper ()} { url } — { e } — retrying in { total_wait_time :.2f} s"
100+ f"[Retry { attempt + 1 } ] { http_method .upper ()} { url } — { e } — retrying in { delay :.2f} s"
84101 )
85102
86- time .sleep (total_wait_time )
103+ time .sleep (delay )
87104
88105 def create_immunization_resource (self , resource : dict = None ) -> str :
89106 """creates an Immunization resource and returns the resource url"""
@@ -105,19 +122,19 @@ def create_a_deleted_immunization_resource(self, resource: dict = None) -> dict:
105122 return imms
106123
107124 def get_immunization_by_id (self , event_id , expected_status_code : int = 200 ):
108- return self ._make_request_with_backoff (
109- "GET" ,
110- f"{ self .url } /Immunization/{ event_id } " ,
111- expected_status_code ,
112- headers = self . _update_headers ()
125+ return self .make_request_with_backoff (
126+ http_method = "GET" ,
127+ url = f"{ self .url } /Immunization/{ event_id } " ,
128+ headers = self . _update_headers () ,
129+ expected_status_code = expected_status_code
113130 )
114131
115132 def create_immunization (self , imms , expected_status_code : int = 201 ):
116- response = self ._make_request_with_backoff (
117- "POST" ,
118- f"{ self .url } /Immunization" ,
119- expected_status_code ,
133+ response = self .make_request_with_backoff (
134+ http_method = "POST" ,
135+ url = f"{ self .url } /Immunization" ,
120136 headers = self ._update_headers (),
137+ expected_status_code = expected_status_code ,
121138 json = imms
122139 )
123140
@@ -134,29 +151,29 @@ def create_immunization(self, imms, expected_status_code: int = 201):
134151 return response
135152
136153 def update_immunization (self , imms_id , imms , expected_status_code : int = 200 ):
137- return self ._make_request_with_backoff (
138- "PUT" ,
139- f"{ self .url } /Immunization/{ imms_id } " ,
140- expected_status_code ,
154+ return self .make_request_with_backoff (
155+ http_method = "PUT" ,
156+ url = f"{ self .url } /Immunization/{ imms_id } " ,
141157 headers = self ._update_headers (),
158+ expected_status_code = expected_status_code ,
142159 json = imms
143160 )
144161
145162 def delete_immunization (self , imms_id , expected_status_code : int = 204 ):
146- return self ._make_request_with_backoff (
147- "DELETE" ,
148- f"{ self .url } /Immunization/{ imms_id } " ,
149- expected_status_code ,
150- headers = self . _update_headers ()
163+ return self .make_request_with_backoff (
164+ http_method = "DELETE" ,
165+ url = f"{ self .url } /Immunization/{ imms_id } " ,
166+ headers = self . _update_headers () ,
167+ expected_status_code = expected_status_code ,
151168 )
152169
153170 def search_immunizations (self , patient_identifier : str , immunization_target : str , expected_status_code : int = 200 ):
154- return self ._make_request_with_backoff (
155- "GET" ,
156- f"{ self .url } /Immunization?patient.identifier={ patient_identifier_system } |{ patient_identifier } "
171+ return self .make_request_with_backoff (
172+ http_method = "GET" ,
173+ url = f"{ self .url } /Immunization?patient.identifier={ patient_identifier_system } |{ patient_identifier } "
157174 f"&-immunization.target={ immunization_target } " ,
158- expected_status_code ,
159- headers = self . _update_headers ()
175+ headers = self . _update_headers () ,
176+ expected_status_code = expected_status_code
160177 )
161178
162179 def search_immunizations_full (
@@ -171,11 +188,11 @@ def search_immunizations_full(
171188 else :
172189 url = f"{ self .url } /Immunization?{ query_string } "
173190
174- return self ._make_request_with_backoff (
175- http_method ,
176- url ,
177- expected_status_code ,
191+ return self .make_request_with_backoff (
192+ http_method = http_method ,
193+ url = url ,
178194 headers = self ._update_headers ({"Content-Type" : "application/x-www-form-urlencoded" }),
195+ expected_status_code = expected_status_code ,
179196 data = body
180197 )
181198
0 commit comments