Class: PatientHttp::SynchronousExecutor
- Inherits:
-
Object
- Object
- PatientHttp::SynchronousExecutor
- Includes:
- RedirectHelper
- Defined in:
- lib/patient_http/synchronous_executor.rb
Overview
Handles synchronous/inline execution of HTTP requests.
Used for testing or when synchronous execution is needed. Accepts configuration and optional callback hooks so it has no dependency on any module-level singleton state.
Instance Method Summary collapse
-
#call ⇒ void
Execute the request synchronously.
-
#initialize(task, config:, on_complete: nil, on_error: nil) ⇒ SynchronousExecutor
constructor
A new instance of SynchronousExecutor.
Constructor Details
#initialize(task, config:, on_complete: nil, on_error: nil) ⇒ SynchronousExecutor
Returns a new instance of SynchronousExecutor.
16 17 18 19 20 21 22 |
# File 'lib/patient_http/synchronous_executor.rb', line 16 def initialize(task, config:, on_complete: nil, on_error: nil) @task = task @config = config @on_complete = on_complete @on_error = on_error @proxy_client = nil end |
Instance Method Details
#call ⇒ void
This method returns an undefined value.
Execute the request synchronously.
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/patient_http/synchronous_executor.rb', line 26 def call Async do start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) begin http_client = nil response_data = nil loop do http_client&.close @proxy_client&.close @proxy_client = nil http_client = create_http_client timeout = @task.request.timeout || @config.request_timeout response_data = Async::Task.current.with_timeout(timeout) do headers = @task.request.headers.to_h.merge("x-request-id" => @task.id) headers["user-agent"] ||= @config.user_agent if @config.user_agent body = Protocol::HTTP::Body::Buffered.wrap([@task.request.body.to_s]) if @task.request.body endpoint = Async::HTTP::Endpoint.parse(@task.request.url) endpoint = configure_endpoint(endpoint) if @config.connection_timeout verb = @task.request.http_method.to_s.upcase = { headers: headers, body: body, scheme: endpoint.scheme, authority: endpoint. } request = Protocol::HTTP::Request[verb, endpoint.path, **] async_response = http_client.call(request) headers_hash = async_response.headers.to_h.transform_values(&:to_s) body_content = read_response_body(async_response, headers_hash) { status: async_response.status, headers: headers_hash, body: body_content } end # Check for redirect break unless should_follow_redirect?(@task, response_data) redirect_error = check_redirect_error(@task, response_data) if redirect_error invoke_callback(redirect_error, :error) return end location = response_data[:headers]["location"] @task = @task.redirect_task(location: location, status: response_data[:status]) end end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) duration = end_time - start_time response = Response.new( status: response_data[:status], headers: response_data[:headers], body: response_data[:body], duration: duration, request_id: @task.id, url: @task.request.url, http_method: @task.request.http_method, callback_args: @task.callback_args, redirects: @task.redirects ) if @task.raise_error_responses && !response.success? http_error = HttpError.new(response) invoke_callback(http_error, :error) else invoke_callback(response, :response) end rescue => e end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) duration = end_time - start_time error = RequestError.from_exception( e, request_id: @task.id, duration: duration, url: @task.request.url, http_method: @task.request.http_method, callback_args: @task.callback_args ) invoke_callback(error, :error) ensure http_client&.close @proxy_client&.close @proxy_client = nil end end end |