@@ -172,6 +172,34 @@ function set_connect_timeout(easy::Curl.Easy, timeout::Real)
172172 end
173173end
174174
175+ # Prevent reuse of this handle
176+ # Should be called if an error is detected and/or the server is likely to close connection
177+ forbid_reuse (easy:: Curl.Easy ) = Curl. setopt (easy, CURLOPT_FORBID_REUSE, Clong (1 ))
178+
179+ function get_grpc_status (easy:: Curl.Easy )
180+ grpc_status = StatusCode. OK. code
181+ grpc_message = " "
182+
183+ # parse the grpc headers
184+ @debug (" response headers" , easy. res_hdrs)
185+ for hdr in easy. res_hdrs
186+ if startswith (hdr, " grpc-status" )
187+ grpc_status = parse (Int, strip (last (split (hdr, ' :' ; limit= 2 ))))
188+ elseif startswith (hdr, " grpc-message" )
189+ grpc_message = string (strip (last (split (hdr, ' :' ; limit= 2 ))))
190+ end
191+ end
192+
193+ if (easy. code == CURLE_OPERATION_TIMEDOUT) && (grpc_status == StatusCode. OK. code)
194+ grpc_status = StatusCode. DEADLINE_EXCEEDED. code
195+ end
196+ if (grpc_status != StatusCode. OK. code) && isempty (grpc_message)
197+ grpc_message = grpc_status_message (grpc_status)
198+ end
199+
200+ return grpc_status, grpc_message
201+ end
202+
175203function grpc_request (downloader:: Downloader , url:: String , input:: Channel{T1} , output:: Channel{T2} ;
176204 maxage:: Clong = typemax (Clong),
177205 keepalive:: Clong = 60 ,
@@ -209,62 +237,30 @@ function grpc_request(downloader::Downloader, url::String, input::Channel{T1}, o
209237 nothing
210238 end
211239
212- # do send recv data
213- if VERSION < v " 1.5"
214- cleaned_up = false
215- exception = nothing
216- cleanup_once = (ex)-> begin
217- if ! cleaned_up
218- cleaned_up = true
219- exception = ex
220- cleanup ()
221- end
222- end
223-
224- @sync begin
225- @async try
226- recv_data (easy, output, max_recv_message_length)
227- catch ex
228- cleanup_once (ex)
229- end
230- @async try
231- send_data (easy, input, max_send_message_length)
232- catch ex
233- cleanup_once (ex)
234- end
235- end
240+ exception = nothing
241+ grpc_status = StatusCode. OK. code
242+ grpc_message = " "
236243
237- if exception != = nothing
238- throw (exception)
244+ # do send recv data
245+ try
246+ Base. Experimental. @sync begin
247+ @async recv_data (easy, output, max_recv_message_length)
248+ @async send_data (easy, input, max_send_message_length)
239249 end
240- else
241- try
242- Base. Experimental. @sync begin
243- @async recv_data (easy, output, max_recv_message_length)
244- @async send_data (easy, input, max_send_message_length)
245- end
246- finally # ensure handle is removed
247- cleanup ()
250+ grpc_status, grpc_message = get_grpc_status (easy)
251+ if ((easy. code != CURLE_OK) || (grpc_status != StatusCode. OK. code))
252+ forbid_reuse (easy)
248253 end
254+ catch ex
255+ forbid_reuse (easy)
256+ exception = ex
257+ finally # ensure handle is removed
258+ cleanup ()
249259 end
250260
251- @debug (" response headers" , easy. res_hdrs)
252-
253- # parse the grpc headers
254- grpc_status = StatusCode. OK. code
255- grpc_message = " "
256- for hdr in easy. res_hdrs
257- if startswith (hdr, " grpc-status" )
258- grpc_status = parse (Int, strip (last (split (hdr, ' :' ; limit= 2 ))))
259- elseif startswith (hdr, " grpc-message" )
260- grpc_message = string (strip (last (split (hdr, ' :' ; limit= 2 ))))
261- end
262- end
263- if (easy. code == CURLE_OPERATION_TIMEDOUT) && (grpc_status == StatusCode. OK. code)
264- grpc_status = StatusCode. DEADLINE_EXCEEDED. code
265- end
266- if (grpc_status != StatusCode. OK. code) && isempty (grpc_message)
267- grpc_message = grpc_status_message (grpc_status)
261+ # throw the unwrapped exception if there was one
262+ if exception != = nothing
263+ throw (exception)
268264 end
269265
270266 if ((easy. code == CURLE_OK) && (grpc_status == StatusCode. OK. code))
0 commit comments