Skip to content

Commit 91c0617

Browse files
committed
Avoid unnecessary async for no-op body decoding, and drop encoded data
We now drop encoded data entirely after it's been decoded, which ensures we don't duplicate data storage here especially for large body cases.
1 parent 1430de0 commit 91c0617

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

src/model/events/bodies.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ export function testEncodings(message: ExchangeMessage): EncodedBodySizes | unde
3131
// Will be undefined, but ensures we're subscribed to the observable
3232
return sizesObservable.get();
3333
}
34+
}
35+
36+
export function decodingRequired(encodedBuffer: Buffer, encodings: string[]): boolean {
37+
return !(
38+
encodings.length === 0 || // No encoding
39+
(encodings.length === 1 && encodings[0] === 'identity') || // No-op only encoding
40+
encodedBuffer.length === 0 // Empty body (e.g. HEAD, 204, etc)
41+
);
3442
}

src/model/http/http-body.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919

2020
import { logError } from '../../errors';
2121
import { decodeBody } from '../../services/ui-worker-api';
22+
import { decodingRequired } from '../events/bodies';
2223

2324
export class HttpBody implements MessageBody {
2425

@@ -116,13 +117,17 @@ export class HttpBody implements MessageBody {
116117
// One is always set - so if _decoded is not set, _encoded must be.
117118
const encodedBuffer = this._encoded as Buffer;
118119

119-
// Temporarily change to a fake buffer, while the web worker takes the data to decode
120+
// Change to a fake buffer, while the web worker takes the data to decode. If we
121+
// decoded successfully, we never put this back (to avoid duplicting the data).
120122
const encodedLength = encodedBuffer.byteLength;
121123
this._encoded = fakeBuffer(encodedLength);
122124

123125
try {
124-
const { decoded, encoded } = await decodeBody(encodedBuffer, this._contentEncoding);
125-
this._encoded = encoded;
126+
// We short-circuit (to avoid the render+async+re-render) if we know that
127+
// decoding is not actually required here.
128+
const { decoded } = decodingRequired(encodedBuffer, this._contentEncoding)
129+
? await decodeBody(encodedBuffer, this._contentEncoding)
130+
: { decoded: encodedBuffer };
126131

127132
runInAction(() => {
128133
this._decoded = decoded;

src/services/ui-worker-api.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
import { Headers, Omit } from '../types';
2525
import type { ApiMetadata, ApiSpec } from '../model/api/api-interfaces';
2626
import { WorkerFormatterKey } from './ui-worker-formatters';
27+
import { decodingRequired } from '../model/events/bodies';
2728

2829
const worker = new Worker(new URL('./ui-worker', import.meta.url));
2930

@@ -68,11 +69,7 @@ function callApi<
6869
* original encoded data (transferred back) in a new buffer.
6970
*/
7071
export async function decodeBody(encodedBuffer: Buffer, encodings: string[]) {
71-
if (
72-
encodings.length === 0 || // No encoding
73-
(encodings.length === 1 && encodings[0] === 'identity') || // No-op only encoding
74-
encodedBuffer.length === 0 // Empty body (e.g. HEAD, 204, etc)
75-
) {
72+
if (!decodingRequired(encodedBuffer, encodings)) {
7673
// Shortcut to skip decoding when we know it's not required:
7774
return { encoded: encodedBuffer, decoded: encodedBuffer };
7875
}

0 commit comments

Comments
 (0)