optimize: perform GET requests in single msg

This commit is contained in:
Spencer Pogorzelski 2023-08-14 21:00:24 -07:00
parent 36e29adcc1
commit 4e31a2a4e7
4 changed files with 45 additions and 35 deletions

View file

@ -33,6 +33,28 @@ function createBodyStream(
); );
} }
if (body instanceof ArrayBuffer) {
if (body.byteLength == 0) {
return null;
}
let remaining = body;
return new ReadableStream({
type: "bytes",
pull: (controller) => {
if (remaining.byteLength <= 0) {
return controller.close();
}
const current = remaining.slice(0, MAX_CHUNK_SIZE);
remaining = remaining.slice(MAX_CHUNK_SIZE);
controller.enqueue(new Uint8Array(current));
},
});
}
if (body instanceof FormData) {
throw new Error("formdata todo");
}
const transformer = () => const transformer = () =>
new TransformStream({ new TransformStream({
transform: async ( transform: async (
@ -73,32 +95,10 @@ function createBodyStream(
return body.pipeThrough(transformer()); return body.pipeThrough(transformer());
} }
if (body instanceof ArrayBuffer) {
if (body.byteLength == 0) {
return null;
}
let remaining = body;
return new ReadableStream({
type: "bytes",
pull: (controller) => {
if (remaining.byteLength <= 0) {
return controller.close();
}
const current = remaining.slice(0, MAX_CHUNK_SIZE);
remaining = remaining.slice(MAX_CHUNK_SIZE);
controller.enqueue(new Uint8Array(current));
},
});
}
if (body instanceof Blob) { if (body instanceof Blob) {
return body.stream().pipeThrough(transformer()); return body.stream().pipeThrough(transformer());
} }
if (body instanceof FormData) {
throw new Error("formdata todo");
}
throw new Error("Unexpected body type: " + body); throw new Error("Unexpected body type: " + body);
} }
@ -139,10 +139,6 @@ export class AdriftBareClient extends Client {
respBody = null; respBody = null;
} }
console.log("constructing Response", {
status: payload.status,
body: respBody?.byteLength,
});
return new Response(respBody, { return new Response(respBody, {
status: payload.status, status: payload.status,
statusText: payload.statusText, statusText: payload.statusText,

View file

@ -4,6 +4,7 @@ import {
C2SWSOpenPayload, C2SWSOpenPayload,
HTTPRequestPayload, HTTPRequestPayload,
HTTPResponsePayload, HTTPResponsePayload,
ProtoBareHeaders,
S2CRequestType, S2CRequestType,
S2CRequestTypes, S2CRequestTypes,
Transport, Transport,
@ -152,17 +153,22 @@ export class Connection {
} }
httprequest( httprequest(
data: HTTPRequestPayload, data: {
method: string;
requestHeaders: ProtoBareHeaders;
remote: URL;
},
body: ReadableStream<ArrayBuffer | Uint8Array> | null body: ReadableStream<ArrayBuffer | Uint8Array> | null
): Promise<{ payload: HTTPResponsePayload; body: ArrayBuffer }> { ): Promise<{ payload: HTTPResponsePayload; body: ArrayBuffer }> {
let json = JSON.stringify(data); const payload: HTTPRequestPayload = { ...data, hasBody: Boolean(body) };
let json = JSON.stringify(payload);
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
let seq = this.nextSeq(); let seq = this.nextSeq();
this.requestCallbacks[seq] = resolve; this.requestCallbacks[seq] = resolve;
await this.send(seq, C2SRequestTypes.HTTPRequestStart, new Blob([json])); await this.send(seq, C2SRequestTypes.HTTPRequestStart, new Blob([json]));
if (body) { if (payload.hasBody) {
for await (const chunk of body as unknown as NodeJS.ReadableStream) { for await (const chunk of body as unknown as NodeJS.ReadableStream) {
await this.send( await this.send(
seq, seq,
@ -170,8 +176,8 @@ export class Connection {
new Uint8Array(chunk as Uint8Array | ArrayBuffer) new Uint8Array(chunk as Uint8Array | ArrayBuffer)
); );
} }
await this.send(seq, C2SRequestTypes.HTTPRequestEnd);
} }
await this.send(seq, C2SRequestTypes.HTTPRequestEnd);
}); });
} }

View file

@ -28,6 +28,7 @@ export type HTTPRequestPayload = {
method: string; method: string;
requestHeaders: ProtoBareHeaders; requestHeaders: ProtoBareHeaders;
remote: URL; remote: URL;
hasBody: boolean;
}; };
export type HTTPResponsePayload = { export type HTTPResponsePayload = {

View file

@ -92,13 +92,20 @@ export class AdriftServer {
let resp: IncomingMessage; let resp: IncomingMessage;
try { try {
const outgoing = await (this.requestStreams[seq] = bareInitialFetch( const outgoingPromise = bareInitialFetch(
payload, payload,
abort.signal, abort.signal,
new URL(payload.remote), new URL(payload.remote),
options options
)); );
resp = await fetchResponse(outgoing); if (payload.hasBody) {
this.requestStreams[seq] = outgoingPromise;
}
const outgoingStream = await outgoingPromise;
if (!payload.hasBody) {
outgoingStream.end();
}
resp = await fetchResponse(await outgoingPromise);
} catch (e) { } catch (e) {
if (e instanceof BareError) { if (e instanceof BareError) {
return bareErrorToResponse(e); return bareErrorToResponse(e);
@ -243,10 +250,10 @@ export class AdriftServer {
resp = bareErrorToResponse(bareError); resp = bareErrorToResponse(bareError);
} }
const { payload, body } = resp; const { payload, body: responseBody } = resp;
this.sendHTTPResponseStart(seq, payload); this.sendHTTPResponseStart(seq, payload);
for await (const chunk of body) { for await (const chunk of responseBody) {
let chunkPart = null; let chunkPart = null;
let chunkRest = chunk; let chunkRest = chunk;
do { do {