class Execution

Manages one request and its isolated worker transport.

Definitions

def initialize(endpoint, backend, request, parent)

Initialize an execution.

Signature

parameter endpoint Transport::Endpoint

The caller endpoint.

parameter backend Thread | Ractor

The isolated execution context.

parameter request Protocol::HTTP::Request

The original request.

parameter parent Async::Task

The parent task for body forwarding.

Implementation

def initialize(endpoint, backend, request, parent)
	@endpoint = endpoint
	@backend = backend
	@request = request
	@parent = parent
	@input_task = nil
	@input_close_task = nil
	@finished = false
	@mutex = Mutex.new
end

def control

Signature

attribute Channel

The control channel.

Implementation

def control
	@endpoint.control
end

def body

Signature

attribute Channel

The bidirectional body channel.

Implementation

def body
	@endpoint.body
end

def call

Start the worker request and wait for the response head.

Signature

returns Protocol::HTTP::Response

The reconstructed response.

Implementation

def call
	description = request_description(@request)
	control.write(:request, description)
	
	if description[:body]
		@input_task = @parent.async do
			forward_request_body(@request.body)
		end
	end
	
	wait_for_response
rescue
	cancel($!)
	raise
end

def stream_input(stream)

Forward upgraded-stream input after the request body phase.

Signature

parameter stream IO | Object

The caller's duplex stream.

returns Async::Task

The forwarding task.

Implementation

def stream_input(stream)
	@parent.async do
		@input_task&.wait
		
		while chunk = read_stream_chunk(stream)
			body.write(:stream_chunk, chunk)
		end
	rescue => error
		begin
			body.write(:stream_error, RemoteError.dump(error))
		rescue ClosedError
			# The worker has already finished:
		end
	ensure
		body.close_write
	end
end

def close_input

Finish the request direction once the initial request body has been forwarded.

Implementation

def close_input
	@input_close_task ||= @parent.async do
		@input_task&.wait
		body.close_write
	end
end

def finish

Finish the execution and release its transport.

Implementation

def finish
	return unless transition_to_finished
	
	@input_task&.cancel
	@input_close_task&.cancel
	@endpoint.close
	@backend.join
	return nil
end

def cancel(error = nil)

Cancel the execution and release its transport.

Signature

parameter error Exception | Nil

The cancellation reason.

Implementation

def cancel(error = nil)
	return unless transition_to_finished
	
	begin
		control.write(:cancel, error && RemoteError.dump(error))
	rescue ClosedError
		# The worker has already finished:
	end
	
	@input_task&.cancel
	@input_close_task&.cancel
	@request.close(error)
	@endpoint.close
	return nil
end