Skip to content

Commit 7aebe1f

Browse files
committed
chore(lazer-sdk-js): responded to further PR feedback about typing exhaustivity, using a utility function for buffer creation, as well as one for adding the token to the URL
1 parent 8ec22ae commit 7aebe1f

File tree

6 files changed

+57
-51
lines changed

6 files changed

+57
-51
lines changed

lazer/sdk/js/src/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type {
1919
import { BINARY_UPDATE_FORMAT_MAGIC_LE, FORMAT_MAGICS_LE } from "./protocol.js";
2020
import type { WebSocketPoolConfig } from "./socket/websocket-pool.js";
2121
import { WebSocketPool } from "./socket/websocket-pool.js";
22-
import { IsomorphicBuffer } from "./util/index.js";
22+
import { bufferFromWebsocketData } from "./util/buffer-util.js";
2323

2424
export type BinaryResponse = {
2525
subscriptionId: number;
@@ -121,7 +121,7 @@ export class PythLazerClient {
121121
});
122122
return;
123123
}
124-
const buffData = await IsomorphicBuffer.fromWebsocketData(data);
124+
const buffData = await bufferFromWebsocketData(data);
125125
let pos = 0;
126126
const magic = buffData
127127
.subarray(pos, pos + UINT32_NUM_BYTES)

lazer/sdk/js/src/socket/resilient-websocket.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ export type ResilientWebSocketConfig = {
2929
* and falling back to using the https://www.npmjs.com/package/ws package, this
3030
* means there are API differences between the native WebSocket (the one in a web browser)
3131
* and the server-side version from the "ws" package.
32-
*
32+
*
3333
* This type creates a WebSocket type reference we use to indicate the unknown
3434
* nature of the env in which is code is run.
3535
*/
36-
type UnsafeWebSocket = (Omit<WebSocket, "terminate"> & Partial<Pick<WebSocket, "terminate">>);
36+
type UnsafeWebSocket = Omit<WebSocket, "terminate"> &
37+
Partial<Pick<WebSocket, "terminate">>;
3738

3839
export class ResilientWebSocket {
3940
private endpoint: string;
@@ -220,8 +221,8 @@ export class ResilientWebSocket {
220221
if (this.shouldLogRetry()) {
221222
this.logger.error(
222223
"Connection closed unexpectedly or because of timeout. Reconnecting after " +
223-
String(this.retryDelayMs()) +
224-
"ms.",
224+
String(this.retryDelayMs()) +
225+
"ms.",
225226
);
226227
}
227228

lazer/sdk/js/src/socket/websocket-pool.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import {
1111
DEFAULT_STREAM_SERVICE_0_URL,
1212
DEFAULT_STREAM_SERVICE_1_URL,
1313
} from "../constants.js";
14-
import { addAuthTokenToWebSocketUrl, envIsBrowserOrWorker, IsomorphicBuffer } from "../util/index.js";
14+
import {
15+
addAuthTokenToWebSocketUrl,
16+
bufferFromWebsocketData,
17+
envIsBrowserOrWorker,
18+
} from "../util/index.js";
1519

1620
const DEFAULT_NUM_CONNECTIONS = 4;
1721

@@ -72,7 +76,9 @@ export class WebSocketPool {
7276
for (let i = 0; i < numConnections; i++) {
7377
const baseUrl = urls[i % urls.length];
7478
const isBrowser = envIsBrowserOrWorker();
75-
const url = isBrowser ? addAuthTokenToWebSocketUrl(baseUrl, token) : baseUrl;
79+
const url = isBrowser
80+
? addAuthTokenToWebSocketUrl(baseUrl, token)
81+
: baseUrl;
7682
if (!url) {
7783
throw new Error(`URLs must not be null or empty`);
7884
}
@@ -151,18 +157,18 @@ export class WebSocketPool {
151157
}
152158
}
153159

160+
private async constructCacheKeyFromWebsocketData(data: WebSocket.Data) {
161+
if (typeof data === "string") return data;
162+
const buff = await bufferFromWebsocketData(data);
163+
return buff.toString("hex");
164+
}
165+
154166
/**
155167
* Handles incoming websocket messages by deduplicating identical messages received across
156168
* multiple connections before forwarding to registered handlers
157169
*/
158170
dedupeHandler = async (data: WebSocket.Data): Promise<void> => {
159-
let cacheKey = "";
160-
if (typeof data === "string") {
161-
cacheKey = data;
162-
} else {
163-
const buff = await IsomorphicBuffer.fromWebsocketData(data);
164-
cacheKey = buff.toString("hex");
165-
}
171+
const cacheKey = await this.constructCacheKeyFromWebsocketData(data);
166172

167173
if (this.cache.has(cacheKey)) {
168174
this.logger.debug("Dropping duplicate message");

lazer/sdk/js/src/util/buffer-util.ts

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,33 @@ import { Buffer as BrowserBuffer } from "buffer";
66

77
import type { Data } from "isomorphic-ws";
88

9-
const { Buffer: PossibleBuiltInBuffer } = globalThis as Partial<{
10-
Buffer: typeof Buffer;
11-
}>;
12-
13-
const BufferClassToUse = PossibleBuiltInBuffer ?? BrowserBuffer;
14-
15-
export class IsomorphicBuffer extends BufferClassToUse {
16-
/**
17-
* given a relatively unknown websocket frame data object,
18-
* returns a valid Buffer instance that is safe to use
19-
* isomorphically in any JS runtime environment
20-
*/
21-
static async fromWebsocketData(data: Data) {
22-
if (typeof data === "string") {
23-
return BufferClassToUse.from(new TextEncoder().encode(data).buffer);
24-
}
25-
if (data instanceof Blob) {
26-
// let the uncaught promise exception bubble up if there's an issue
27-
return BufferClassToUse.from(await data.arrayBuffer());
28-
}
29-
if (data instanceof ArrayBuffer) return BufferClassToUse.from(data);
30-
if (Buffer.isBuffer(data)) {
31-
const arrBuffer = new ArrayBuffer(data.length);
32-
const v = new Uint8Array(arrBuffer);
33-
for (const [i, item] of data.entries()) {
34-
v[i] = item;
35-
}
36-
return BufferClassToUse.from(arrBuffer);
37-
}
38-
throw new TypeError(
39-
"unexpected event data type found when IsomorphicBuffer.fromWebsocketData() called",
40-
);
9+
const BufferClassToUse =
10+
"Buffer" in globalThis ? globalThis.Buffer : BrowserBuffer;
11+
12+
/**
13+
* given a relatively unknown websocket frame data object,
14+
* returns a valid Buffer instance that is safe to use
15+
* isomorphically in any JS runtime environment
16+
*/
17+
export async function bufferFromWebsocketData(data: Data): Promise<Buffer> {
18+
if (typeof data === "string") {
19+
return BufferClassToUse.from(new TextEncoder().encode(data).buffer);
20+
}
21+
22+
if (data instanceof BufferClassToUse) return data;
23+
24+
if (data instanceof Blob) {
25+
// let the uncaught promise exception bubble up if there's an issue
26+
return BufferClassToUse.from(await data.arrayBuffer());
4127
}
28+
29+
if (data instanceof ArrayBuffer) return BufferClassToUse.from(data);
30+
31+
if (Array.isArray(data)) {
32+
// an array of buffers is highly unlikely, but it is a possibility
33+
// indicated by the WebSocket Data interface
34+
return BufferClassToUse.concat(data);
35+
}
36+
37+
return data;
4238
}

lazer/sdk/js/src/util/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export * from "./buffer-util.js";
22
export * from "./env-util.js";
3-
export * from "./url-util.js";
3+
export * from "./url-util.js";

lazer/sdk/js/src/util/url-util.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const ACCESS_TOKEN_QUERY_PARAM_KEY = 'ACCESS_TOKEN';
1+
const ACCESS_TOKEN_QUERY_PARAM_KEY = "ACCESS_TOKEN";
22

33
/**
44
* Given a URL to a hosted lazer stream service and a possible auth token,
@@ -7,10 +7,13 @@ const ACCESS_TOKEN_QUERY_PARAM_KEY = 'ACCESS_TOKEN';
77
* If the URL provided is nullish, it is returned as-is (in the same nullish format).
88
* If the token is nullish, the baseUrl given is returned, instead.
99
*/
10-
export function addAuthTokenToWebSocketUrl(baseUrl: string | null | undefined, authToken: string | null | undefined) {
10+
export function addAuthTokenToWebSocketUrl(
11+
baseUrl: string | null | undefined,
12+
authToken: string | null | undefined,
13+
) {
1114
if (!baseUrl || !authToken) return baseUrl;
1215
const parsedUrl = new URL(baseUrl);
1316
parsedUrl.searchParams.set(ACCESS_TOKEN_QUERY_PARAM_KEY, authToken);
1417

1518
return parsedUrl.toString();
16-
}
19+
}

0 commit comments

Comments
 (0)