Skip to content

Commit

Permalink
refactor(ext/http): Use HttpRecord as response body to track until bo…
Browse files Browse the repository at this point in the history
…dy completion (denoland#20822)

Use HttpRecord as response body so requests can be tracked all the way
to response body completion.

This allows Request properties to be accessed while the response body is
streaming.

Graceful shutdown now awaits a future instead of async spinning waiting
for requests to finish.

On the minimal benchmark this refactor improves performance an
additional 2% over pooling alone for a net 3% increase over the previous
deno main branch.

Builds upon denoland#20809 and
denoland#20770.

---------

Co-authored-by: Matt Mastracci <[email protected]>
  • Loading branch information
lrowe and mmastrac committed Nov 13, 2023
1 parent 0209f7b commit e581977
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 336 deletions.
35 changes: 22 additions & 13 deletions ext/http/00_serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ const {
ObjectHasOwn,
ObjectPrototypeIsPrototypeOf,
PromisePrototypeCatch,
PromisePrototypeThen,
Symbol,
TypeError,
Uint8Array,
Uint8ArrayPrototype,
} = primordials;

const {
op_http_close_after_finish,
op_http_get_request_headers,
op_http_get_request_method_and_url,
op_http_read_request_body,
Expand Down Expand Up @@ -386,9 +388,10 @@ class ServeHandlerInfo {
}
}

function fastSyncResponseOrStream(req, respBody, status) {
function fastSyncResponseOrStream(req, respBody, status, innerRequest) {
if (respBody === null || respBody === undefined) {
// Don't set the body
innerRequest?.close();
op_http_set_promise_complete(req, status);
return;
}
Expand All @@ -397,36 +400,43 @@ function fastSyncResponseOrStream(req, respBody, status) {
const body = stream.body;

if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, body)) {
innerRequest?.close();
op_http_set_response_body_bytes(req, body, status);
return;
}

if (typeof body === "string") {
innerRequest?.close();
op_http_set_response_body_text(req, body, status);
return;
}

// At this point in the response it needs to be a stream
if (!ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, stream)) {
innerRequest?.close();
throw TypeError("invalid response");
}
const resourceBacking = getReadableStreamResourceBacking(stream);
let rid, autoClose;
if (resourceBacking) {
op_http_set_response_body_resource(
req,
resourceBacking.rid,
resourceBacking.autoClose,
status,
);
rid = resourceBacking.rid;
autoClose = resourceBacking.autoClose;
} else {
const rid = resourceForReadableStream(stream);
rid = resourceForReadableStream(stream);
autoClose = true;
}
PromisePrototypeThen(
op_http_set_response_body_resource(
req,
rid,
true,
autoClose,
status,
);
}
),
() => {
innerRequest?.close();
op_http_close_after_finish(req);
},
);
}

/**
Expand Down Expand Up @@ -499,8 +509,7 @@ function mapToCallback(context, callback, onError) {
}
}

innerRequest?.close();
fastSyncResponseOrStream(req, inner.body, status);
fastSyncResponseOrStream(req, inner.body, status, innerRequest);
};
}

Expand Down
Loading

0 comments on commit e581977

Please sign in to comment.