@replit/river 0.23.16 → 0.23.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/{chunk-R47IZD67.js → chunk-7MJYOL32.js} +5 -6
- package/dist/{chunk-R47IZD67.js.map → chunk-7MJYOL32.js.map} +1 -1
- package/dist/{chunk-UDXM64QK.js → chunk-AVL32IMG.js} +6 -4
- package/dist/{chunk-UDXM64QK.js.map → chunk-AVL32IMG.js.map} +1 -1
- package/dist/{chunk-JA7XGTAL.js → chunk-DPKOJQWF.js} +5 -5
- package/dist/chunk-DPKOJQWF.js.map +1 -0
- package/dist/{chunk-LTSLICON.js → chunk-EV5HW4IC.js} +5 -468
- package/dist/chunk-EV5HW4IC.js.map +1 -0
- package/dist/{chunk-WN77AT67.js → chunk-J6N6H2WU.js} +3 -3
- package/dist/{chunk-YXDAOVP7.js → chunk-MW5JXLHY.js} +3 -2
- package/dist/chunk-MW5JXLHY.js.map +1 -0
- package/dist/{chunk-TXSQRTZB.js → chunk-R2HAS3GM.js} +2 -2
- package/dist/{chunk-TXSQRTZB.js.map → chunk-R2HAS3GM.js.map} +1 -1
- package/dist/{chunk-MQCGG6KL.js → chunk-RJOWZIWB.js} +5 -5
- package/dist/chunk-RJOWZIWB.js.map +1 -0
- package/dist/{client-0926d3d6.d.ts → client-5776a6bb.d.ts} +1 -1
- package/dist/{connection-99a67d3e.d.ts → connection-bd35d442.d.ts} +1 -1
- package/dist/{connection-d738cc08.d.ts → connection-df85db7e.d.ts} +1 -1
- package/dist/{handshake-75d0124f.d.ts → handshake-a947c234.d.ts} +4 -0
- package/dist/router/index.cjs +4 -468
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +8 -47
- package/dist/router/index.d.ts +8 -47
- package/dist/router/index.js +2 -4
- package/dist/{server-3740c5d9.d.ts → server-53cd5b7e.d.ts} +1 -1
- package/dist/{services-75e84a9f.d.ts → services-38b3f758.d.ts} +6 -6
- package/dist/transport/impls/uds/client.cjs +7 -4
- package/dist/transport/impls/uds/client.cjs.map +1 -1
- package/dist/transport/impls/uds/client.d.cts +3 -3
- package/dist/transport/impls/uds/client.d.ts +3 -3
- package/dist/transport/impls/uds/client.js +5 -5
- package/dist/transport/impls/uds/server.cjs +7 -4
- package/dist/transport/impls/uds/server.cjs.map +1 -1
- package/dist/transport/impls/uds/server.d.cts +3 -3
- package/dist/transport/impls/uds/server.d.ts +3 -3
- package/dist/transport/impls/uds/server.js +5 -5
- package/dist/transport/impls/ws/client.cjs +6 -6
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +3 -3
- package/dist/transport/impls/ws/client.d.ts +3 -3
- package/dist/transport/impls/ws/client.js +5 -5
- package/dist/transport/impls/ws/server.cjs +6 -6
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +3 -3
- package/dist/transport/impls/ws/server.d.ts +3 -3
- package/dist/transport/impls/ws/server.js +5 -5
- package/dist/transport/index.cjs +4 -3
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +3 -3
- package/dist/transport/index.d.ts +3 -3
- package/dist/transport/index.js +5 -5
- package/dist/util/testHelpers.cjs +2 -1
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +4 -4
- package/dist/util/testHelpers.d.ts +4 -4
- package/dist/util/testHelpers.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-JA7XGTAL.js.map +0 -1
- package/dist/chunk-LTSLICON.js.map +0 -1
- package/dist/chunk-MQCGG6KL.js.map +0 -1
- package/dist/chunk-YXDAOVP7.js.map +0 -1
- /package/dist/{chunk-WN77AT67.js.map → chunk-J6N6H2WU.js.map} +0 -0
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ Before proceeding, ensure you have TypeScript 5 installed and configured appropr
|
|
|
80
80
|
First, we create a service using `ServiceSchema`:
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
import {
|
|
83
|
+
import { ServiceSchema, Procedure, Ok } from '@replit/river';
|
|
84
84
|
import { Type } from '@sinclair/typebox';
|
|
85
85
|
|
|
86
86
|
export const ExampleService = ServiceSchema.define(
|
|
@@ -134,17 +134,17 @@ In another file for the client (to create a separate entrypoint),
|
|
|
134
134
|
```ts
|
|
135
135
|
import { WebSocketClientTransport } from '@replit/river/transport/ws/client';
|
|
136
136
|
import { createClient } from '@replit/river';
|
|
137
|
-
import
|
|
137
|
+
import { WebSocket } from 'ws';
|
|
138
138
|
|
|
139
139
|
const transport = new WebSocketClientTransport(
|
|
140
140
|
async () => new WebSocket('ws://localhost:3000'),
|
|
141
141
|
'my-client-id',
|
|
142
142
|
);
|
|
143
143
|
|
|
144
|
-
const client = createClient
|
|
144
|
+
const client = createClient(
|
|
145
145
|
transport,
|
|
146
146
|
'SERVER', // transport id of the server in the previous step
|
|
147
|
-
true, // whether to eagerly connect to the server on creation (optional argument)
|
|
147
|
+
{ eagerlyConnect: true }, // whether to eagerly connect to the server on creation (optional argument)
|
|
148
148
|
);
|
|
149
149
|
|
|
150
150
|
// we get full type safety on `client`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Connection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MW5JXLHY.js";
|
|
4
4
|
|
|
5
5
|
// transport/impls/ws/connection.ts
|
|
6
6
|
var WebSocketConnection = class extends Connection {
|
|
@@ -41,12 +41,11 @@ var WebSocketConnection = class extends Connection {
|
|
|
41
41
|
this.errorCb = cb;
|
|
42
42
|
}
|
|
43
43
|
send(payload) {
|
|
44
|
-
if (this.ws.readyState
|
|
45
|
-
this.ws.send(payload);
|
|
46
|
-
return true;
|
|
47
|
-
} else {
|
|
44
|
+
if (this.ws.readyState !== this.ws.OPEN) {
|
|
48
45
|
return false;
|
|
49
46
|
}
|
|
47
|
+
this.ws.send(payload);
|
|
48
|
+
return true;
|
|
50
49
|
}
|
|
51
50
|
close() {
|
|
52
51
|
this.ws.close();
|
|
@@ -56,4 +55,4 @@ var WebSocketConnection = class extends Connection {
|
|
|
56
55
|
export {
|
|
57
56
|
WebSocketConnection
|
|
58
57
|
};
|
|
59
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-7MJYOL32.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../transport/impls/ws/connection.ts"],"sourcesContent":["import { Connection } from '../../session';\nimport { WsLike } from './wslike';\n\nexport class WebSocketConnection extends Connection {\n errorCb: null | ((err: Error) => void) = null;\n closeCb: null | (() => void) = null;\n\n ws: WsLike;\n\n constructor(ws: WsLike) {\n super();\n this.ws = ws;\n this.ws.binaryType = 'arraybuffer';\n\n // Websockets are kinda shitty, they emit error events with no\n // information other than it errored, so we have to do some extra\n // work to figure out what happened.\n let didError = false;\n this.ws.onerror = () => {\n didError = true;\n };\n this.ws.onclose = ({ code, reason }) => {\n if (didError && this.errorCb) {\n this.errorCb(\n new Error(\n `websocket closed with code and reason: ${code} - ${reason}`,\n ),\n );\n }\n\n if (this.closeCb) {\n this.closeCb();\n }\n };\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.ws.onmessage = (msg) => cb(msg.data as Uint8Array);\n }\n\n removeDataListener(): void {\n this.ws.onmessage = null;\n }\n\n addCloseListener(cb: () => void): void {\n this.closeCb = cb;\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.errorCb = cb;\n }\n\n send(payload: Uint8Array) {\n if (this.ws.readyState
|
|
1
|
+
{"version":3,"sources":["../transport/impls/ws/connection.ts"],"sourcesContent":["import { Connection } from '../../session';\nimport { WsLike } from './wslike';\n\nexport class WebSocketConnection extends Connection {\n errorCb: null | ((err: Error) => void) = null;\n closeCb: null | (() => void) = null;\n\n ws: WsLike;\n\n constructor(ws: WsLike) {\n super();\n this.ws = ws;\n this.ws.binaryType = 'arraybuffer';\n\n // Websockets are kinda shitty, they emit error events with no\n // information other than it errored, so we have to do some extra\n // work to figure out what happened.\n let didError = false;\n this.ws.onerror = () => {\n didError = true;\n };\n this.ws.onclose = ({ code, reason }) => {\n if (didError && this.errorCb) {\n this.errorCb(\n new Error(\n `websocket closed with code and reason: ${code} - ${reason}`,\n ),\n );\n }\n\n if (this.closeCb) {\n this.closeCb();\n }\n };\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.ws.onmessage = (msg) => cb(msg.data as Uint8Array);\n }\n\n removeDataListener(): void {\n this.ws.onmessage = null;\n }\n\n addCloseListener(cb: () => void): void {\n this.closeCb = cb;\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.errorCb = cb;\n }\n\n send(payload: Uint8Array) {\n if (this.ws.readyState !== this.ws.OPEN) {\n return false;\n }\n this.ws.send(payload);\n return true;\n }\n\n close() {\n this.ws.close();\n }\n}\n"],"mappings":";;;;;AAGO,IAAM,sBAAN,cAAkC,WAAW;AAAA,EAClD,UAAyC;AAAA,EACzC,UAA+B;AAAA,EAE/B;AAAA,EAEA,YAAY,IAAY;AACtB,UAAM;AACN,SAAK,KAAK;AACV,SAAK,GAAG,aAAa;AAKrB,QAAI,WAAW;AACf,SAAK,GAAG,UAAU,MAAM;AACtB,iBAAW;AAAA,IACb;AACA,SAAK,GAAG,UAAU,CAAC,EAAE,MAAM,OAAO,MAAM;AACtC,UAAI,YAAY,KAAK,SAAS;AAC5B,aAAK;AAAA,UACH,IAAI;AAAA,YACF,0CAA0C,IAAI,MAAM,MAAM;AAAA,UAC5D;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB,IAA+B;AAC7C,SAAK,GAAG,YAAY,CAAC,QAAQ,GAAG,IAAI,IAAkB;AAAA,EACxD;AAAA,EAEA,qBAA2B;AACzB,SAAK,GAAG,YAAY;AAAA,EACtB;AAAA,EAEA,iBAAiB,IAAsB;AACrC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,iBAAiB,IAAgC;AAC/C,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAK,SAAqB;AACxB,QAAI,KAAK,GAAG,eAAe,KAAK,GAAG,MAAM;AACvC,aAAO;AAAA,IACT;AACA,SAAK,GAAG,KAAK,OAAO;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ;AACN,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Connection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MW5JXLHY.js";
|
|
4
4
|
|
|
5
5
|
// transport/transforms/messageFraming.ts
|
|
6
6
|
import { Transform } from "node:stream";
|
|
@@ -90,9 +90,11 @@ var UdsConnection = class extends Connection {
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
send(payload) {
|
|
93
|
-
if (this.framer.destroyed || !this.sock.writable)
|
|
93
|
+
if (this.framer.destroyed || !this.sock.writable || this.sock.closed) {
|
|
94
94
|
return false;
|
|
95
|
-
|
|
95
|
+
}
|
|
96
|
+
this.sock.write(MessageFramer.write(payload));
|
|
97
|
+
return true;
|
|
96
98
|
}
|
|
97
99
|
close() {
|
|
98
100
|
this.sock.destroy();
|
|
@@ -103,4 +105,4 @@ var UdsConnection = class extends Connection {
|
|
|
103
105
|
export {
|
|
104
106
|
UdsConnection
|
|
105
107
|
};
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-AVL32IMG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../transport/transforms/messageFraming.ts","../transport/impls/uds/connection.ts"],"sourcesContent":["import { Transform, TransformCallback, TransformOptions } from 'node:stream';\n\nexport interface LengthEncodedOptions extends TransformOptions {\n /** Maximum in-memory buffer size before we throw */\n maxBufferSizeBytes: number;\n}\n\n/**\n * A transform stream that emits data each time a message with a network/BigEndian uint32 length prefix is received.\n * @extends Transform\n */\nexport class Uint32LengthPrefixFraming extends Transform {\n receivedBuffer: Buffer;\n maxBufferSizeBytes: number;\n\n constructor({ maxBufferSizeBytes, ...options }: LengthEncodedOptions) {\n super(options);\n this.maxBufferSizeBytes = maxBufferSizeBytes;\n this.receivedBuffer = Buffer.alloc(0);\n }\n\n _transform(chunk: Buffer, _encoding: BufferEncoding, cb: TransformCallback) {\n if (\n this.receivedBuffer.byteLength + chunk.byteLength >\n this.maxBufferSizeBytes\n ) {\n const err = new Error(\n `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`,\n );\n\n this.emit('error', err);\n cb(err);\n return;\n }\n\n this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);\n\n // ensure there's enough for a length prefix\n while (this.receivedBuffer.length > 4) {\n // read length from buffer (accounting for uint32 prefix)\n const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;\n if (this.receivedBuffer.length >= claimedMessageLength) {\n // slice the buffer to extract the message\n const message = this.receivedBuffer.subarray(4, claimedMessageLength);\n this.push(message);\n this.receivedBuffer =\n this.receivedBuffer.subarray(claimedMessageLength);\n } else {\n // not enough data for a complete message, wait for more data\n break;\n }\n }\n\n cb();\n }\n\n _flush(cb: TransformCallback) {\n // if there's any leftover data that doesn't form a complete message\n if (this.receivedBuffer.length) {\n this.emit('error', new Error('got incomplete message while flushing'));\n }\n\n this.receivedBuffer = Buffer.alloc(0);\n cb();\n }\n\n _destroy(error: Error | null, callback: (error: Error | null) => void): void {\n this.receivedBuffer = Buffer.alloc(0);\n super._destroy(error, callback);\n }\n}\n\nfunction createLengthEncodedStream(options?: Partial<LengthEncodedOptions>) {\n return new Uint32LengthPrefixFraming({\n maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024, // 16MB\n });\n}\n\nexport const MessageFramer = {\n createFramedStream: createLengthEncodedStream,\n write: (buf: Uint8Array) => {\n const lengthPrefix = Buffer.alloc(4);\n lengthPrefix.writeUInt32BE(buf.length, 0);\n return Buffer.concat([lengthPrefix, buf]);\n },\n};\n","import { Connection } from '../../session';\nimport { type Socket } from 'node:net';\nimport stream from 'node:stream';\nimport {\n MessageFramer,\n Uint32LengthPrefixFraming,\n} from '../../transforms/messageFraming';\n\nexport class UdsConnection extends Connection {\n sock: Socket;\n input: stream.Readable;\n framer: Uint32LengthPrefixFraming;\n\n constructor(sock: Socket) {\n super();\n this.framer = MessageFramer.createFramedStream();\n this.sock = sock;\n this.input = sock.pipe(this.framer);\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.input.on('data', cb);\n }\n\n removeDataListener(cb: (msg: Uint8Array) => void): void {\n this.input.off('data', cb);\n }\n\n addCloseListener(cb: () => void): void {\n this.sock.on('close', cb);\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.sock.on('error', (err) => {\n if (err instanceof Error && 'code' in err && err.code === 'EPIPE') {\n // Ignore EPIPE errors\n return;\n }\n\n cb(err);\n });\n }\n\n send(payload: Uint8Array) {\n if (this.framer.destroyed || !this.sock.writable) return false;\n
|
|
1
|
+
{"version":3,"sources":["../transport/transforms/messageFraming.ts","../transport/impls/uds/connection.ts"],"sourcesContent":["import { Transform, TransformCallback, TransformOptions } from 'node:stream';\n\nexport interface LengthEncodedOptions extends TransformOptions {\n /** Maximum in-memory buffer size before we throw */\n maxBufferSizeBytes: number;\n}\n\n/**\n * A transform stream that emits data each time a message with a network/BigEndian uint32 length prefix is received.\n * @extends Transform\n */\nexport class Uint32LengthPrefixFraming extends Transform {\n receivedBuffer: Buffer;\n maxBufferSizeBytes: number;\n\n constructor({ maxBufferSizeBytes, ...options }: LengthEncodedOptions) {\n super(options);\n this.maxBufferSizeBytes = maxBufferSizeBytes;\n this.receivedBuffer = Buffer.alloc(0);\n }\n\n _transform(chunk: Buffer, _encoding: BufferEncoding, cb: TransformCallback) {\n if (\n this.receivedBuffer.byteLength + chunk.byteLength >\n this.maxBufferSizeBytes\n ) {\n const err = new Error(\n `buffer overflow: ${this.receivedBuffer.byteLength}B > ${this.maxBufferSizeBytes}B`,\n );\n\n this.emit('error', err);\n cb(err);\n return;\n }\n\n this.receivedBuffer = Buffer.concat([this.receivedBuffer, chunk]);\n\n // ensure there's enough for a length prefix\n while (this.receivedBuffer.length > 4) {\n // read length from buffer (accounting for uint32 prefix)\n const claimedMessageLength = this.receivedBuffer.readUInt32BE(0) + 4;\n if (this.receivedBuffer.length >= claimedMessageLength) {\n // slice the buffer to extract the message\n const message = this.receivedBuffer.subarray(4, claimedMessageLength);\n this.push(message);\n this.receivedBuffer =\n this.receivedBuffer.subarray(claimedMessageLength);\n } else {\n // not enough data for a complete message, wait for more data\n break;\n }\n }\n\n cb();\n }\n\n _flush(cb: TransformCallback) {\n // if there's any leftover data that doesn't form a complete message\n if (this.receivedBuffer.length) {\n this.emit('error', new Error('got incomplete message while flushing'));\n }\n\n this.receivedBuffer = Buffer.alloc(0);\n cb();\n }\n\n _destroy(error: Error | null, callback: (error: Error | null) => void): void {\n this.receivedBuffer = Buffer.alloc(0);\n super._destroy(error, callback);\n }\n}\n\nfunction createLengthEncodedStream(options?: Partial<LengthEncodedOptions>) {\n return new Uint32LengthPrefixFraming({\n maxBufferSizeBytes: options?.maxBufferSizeBytes ?? 16 * 1024 * 1024, // 16MB\n });\n}\n\nexport const MessageFramer = {\n createFramedStream: createLengthEncodedStream,\n write: (buf: Uint8Array) => {\n const lengthPrefix = Buffer.alloc(4);\n lengthPrefix.writeUInt32BE(buf.length, 0);\n return Buffer.concat([lengthPrefix, buf]);\n },\n};\n","import { Connection } from '../../session';\nimport { type Socket } from 'node:net';\nimport stream from 'node:stream';\nimport {\n MessageFramer,\n Uint32LengthPrefixFraming,\n} from '../../transforms/messageFraming';\n\nexport class UdsConnection extends Connection {\n sock: Socket;\n input: stream.Readable;\n framer: Uint32LengthPrefixFraming;\n\n constructor(sock: Socket) {\n super();\n this.framer = MessageFramer.createFramedStream();\n this.sock = sock;\n this.input = sock.pipe(this.framer);\n }\n\n addDataListener(cb: (msg: Uint8Array) => void) {\n this.input.on('data', cb);\n }\n\n removeDataListener(cb: (msg: Uint8Array) => void): void {\n this.input.off('data', cb);\n }\n\n addCloseListener(cb: () => void): void {\n this.sock.on('close', cb);\n }\n\n addErrorListener(cb: (err: Error) => void): void {\n this.sock.on('error', (err) => {\n if (err instanceof Error && 'code' in err && err.code === 'EPIPE') {\n // Ignore EPIPE errors\n return;\n }\n\n cb(err);\n });\n }\n\n send(payload: Uint8Array) {\n if (this.framer.destroyed || !this.sock.writable || this.sock.closed) {\n return false;\n }\n this.sock.write(MessageFramer.write(payload));\n return true;\n }\n\n close() {\n this.sock.destroy();\n this.framer.destroy();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProtocolError,
|
|
3
3
|
Transport
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-J6N6H2WU.js";
|
|
5
5
|
import {
|
|
6
6
|
defaultClientTransportOptions
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MW5JXLHY.js";
|
|
8
8
|
import {
|
|
9
9
|
ControlMessageHandshakeResponseSchema,
|
|
10
10
|
SESSION_STATE_MISMATCH,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
getPropagationContext,
|
|
13
13
|
handshakeRequestMessage,
|
|
14
14
|
tracing_default
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-R2HAS3GM.js";
|
|
16
16
|
|
|
17
17
|
// transport/client.ts
|
|
18
18
|
import { SpanStatusCode } from "@opentelemetry/api";
|
|
@@ -135,7 +135,7 @@ var ClientTransport = class extends Transport {
|
|
|
135
135
|
{ ...conn.loggingMetadata, clientId: this.clientId, connectedTo: to }
|
|
136
136
|
);
|
|
137
137
|
conn.close();
|
|
138
|
-
}, this.options.
|
|
138
|
+
}, this.options.handshakeTimeoutMs);
|
|
139
139
|
const handshakeHandler = (data) => {
|
|
140
140
|
const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
|
|
141
141
|
clearTimeout(handshakeTimeout);
|
|
@@ -473,4 +473,4 @@ var ClientTransport = class extends Transport {
|
|
|
473
473
|
export {
|
|
474
474
|
ClientTransport
|
|
475
475
|
};
|
|
476
|
-
//# sourceMappingURL=chunk-
|
|
476
|
+
//# sourceMappingURL=chunk-DPKOJQWF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../transport/client.ts","../transport/rateLimit.ts"],"sourcesContent":["import { SpanStatusCode } from '@opentelemetry/api';\nimport { ClientHandshakeOptions } from '../router/handshake';\nimport {\n ControlMessageHandshakeResponseSchema,\n SESSION_STATE_MISMATCH,\n TransportClientId,\n handshakeRequestMessage,\n} from './message';\nimport {\n ClientTransportOptions,\n ProvidedClientTransportOptions,\n defaultClientTransportOptions,\n} from './options';\nimport { LeakyBucketRateLimit } from './rateLimit';\nimport { Connection, Session } from './session';\nimport { Transport } from './transport';\nimport { coerceErrorString } from '../util/stringify';\nimport { ProtocolError } from './events';\nimport { Value } from '@sinclair/typebox/value';\nimport tracer, { getPropagationContext } from '../tracing';\n\nexport abstract class ClientTransport<\n ConnType extends Connection,\n> extends Transport<ConnType> {\n /**\n * The options for this transport.\n */\n protected options: ClientTransportOptions;\n\n /**\n * The map of reconnect promises for each client ID.\n */\n inflightConnectionPromises: Map<TransportClientId, Promise<ConnType>>;\n retryBudget: LeakyBucketRateLimit;\n\n /**\n * A flag indicating whether the transport should automatically reconnect\n * when a connection is dropped.\n * Realistically, this should always be true for clients unless you are writing\n * tests or a special case where you don't want to reconnect.\n */\n reconnectOnConnectionDrop = true;\n\n /**\n * Optional handshake options for this client.\n */\n handshakeExtensions?: ClientHandshakeOptions;\n\n constructor(\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.options = {\n ...defaultClientTransportOptions,\n ...providedOptions,\n };\n this.inflightConnectionPromises = new Map();\n this.retryBudget = new LeakyBucketRateLimit(this.options);\n }\n\n extendHandshake(options: ClientHandshakeOptions) {\n this.handshakeExtensions = options;\n }\n\n protected handleConnection(conn: ConnType, to: TransportClientId): void {\n if (this.getStatus() !== 'open') return;\n let session: Session<ConnType> | undefined = undefined;\n\n // kill the conn after the grace period if we haven't received a handshake\n const handshakeTimeout = setTimeout(() => {\n if (session) return;\n this.log?.warn(\n `connection to ${to} timed out waiting for handshake, closing`,\n { ...conn.loggingMetadata, clientId: this.clientId, connectedTo: to },\n );\n conn.close();\n }, this.options.handshakeTimeoutMs);\n\n const handshakeHandler = (data: Uint8Array) => {\n const maybeSession = this.receiveHandshakeResponseMessage(data, conn);\n clearTimeout(handshakeTimeout);\n if (!maybeSession) {\n conn.close();\n return;\n } else {\n session = maybeSession;\n }\n\n // when we are done handshake sequence,\n // remove handshake listener and use the normal message listener\n conn.removeDataListener(handshakeHandler);\n conn.addDataListener((data) => {\n const parsed = this.parseMsg(data, conn);\n if (!parsed) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'message parse failure',\n });\n conn.close();\n return;\n }\n\n this.handleMsg(parsed, conn);\n });\n };\n\n conn.addDataListener(handshakeHandler);\n conn.addCloseListener(() => {\n if (session) {\n this.onDisconnect(conn, session);\n }\n\n const willReconnect =\n this.reconnectOnConnectionDrop && this.getStatus() === 'open';\n\n this.log?.info(\n `connection to ${to} disconnected` +\n (willReconnect ? ', reconnecting' : ''),\n {\n ...conn.loggingMetadata,\n ...session?.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n\n this.inflightConnectionPromises.delete(to);\n if (this.reconnectOnConnectionDrop) {\n void this.connect(to);\n }\n });\n conn.addErrorListener((err) => {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'connection error',\n });\n this.log?.warn(\n `error in connection to ${to}: ${coerceErrorString(err)}`,\n {\n ...conn.loggingMetadata,\n ...session?.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n });\n }\n\n receiveHandshakeResponseMessage(\n data: Uint8Array,\n conn: ConnType,\n ): Session<ConnType> | false {\n const parsed = this.parseMsg(data, conn);\n if (!parsed) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'non-transport message',\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'received non-transport message',\n );\n return false;\n }\n\n if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'invalid handshake response',\n });\n this.log?.warn(`received invalid handshake resp`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n validationErrors: [\n ...Value.Errors(\n ControlMessageHandshakeResponseSchema,\n parsed.payload,\n ),\n ],\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'invalid handshake resp',\n );\n return false;\n }\n\n const previousSession = this.sessions.get(parsed.from);\n if (!parsed.payload.status.ok) {\n if (parsed.payload.status.reason === SESSION_STATE_MISMATCH) {\n if (previousSession) {\n // The server has told us that we cannot continue with the session because it has the\n // wrong state. We should delete this session and start fresh.\n this.deleteSession({\n session: previousSession,\n closeHandshakingConnection: true,\n });\n }\n\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: parsed.payload.status.reason,\n });\n } else {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'handshake rejected',\n });\n }\n this.log?.warn(\n `received handshake rejection: ${parsed.payload.status.reason}`,\n {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n },\n );\n this.protocolError(\n ProtocolError.HandshakeFailed,\n parsed.payload.status.reason,\n );\n return false;\n }\n\n // before we claim victory and we deem that the handshake is fully established, check that our\n // session matches the remote's. if they do not match, proactively close the connection.\n // otherwise we will end up breaking a lot of invariants.\n //\n // TODO: Remove this once we finish rolling out the handshake-initiated session agreement.\n if (\n previousSession?.advertisedSessionId &&\n previousSession.advertisedSessionId !== parsed.payload.status.sessionId\n ) {\n this.deleteSession({\n session: previousSession,\n closeHandshakingConnection: true,\n });\n\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'session id mismatch',\n });\n this.log?.warn(`handshake from ${parsed.from} session id mismatch`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n });\n this.protocolError(ProtocolError.HandshakeFailed, 'session id mismatch');\n return false;\n }\n\n this.log?.debug(`handshake from ${parsed.from} ok`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n });\n\n const { session, isTransparentReconnect } = this.getOrCreateSession({\n to: parsed.from,\n conn,\n sessionId: parsed.payload.status.sessionId,\n });\n\n this.onConnect(conn, session, isTransparentReconnect);\n\n // After a successful connection, we start restoring the budget\n // so that the next time we try to connect, we don't hit the client\n // with backoff forever.\n this.retryBudget.startRestoringBudget(session.to);\n return session;\n }\n\n /**\n * Abstract method that creates a new {@link Connection} object.\n * This should call {@link handleConnection} when the connection is created.\n * The downstream client implementation needs to implement this.\n *\n * @param to The client ID of the node to connect to.\n * @returns The new connection object.\n */\n protected abstract createNewOutgoingConnection(\n to: TransportClientId,\n ): Promise<ConnType>;\n\n /**\n * Manually attempts to connect to a client.\n * @param to The client ID of the node to connect to.\n */\n async connect(to: TransportClientId): Promise<void> {\n if (this.connections.has(to)) {\n this.log?.info(`already connected to ${to}, skipping connect attempt`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n return;\n }\n\n const canProceedWithConnection = () => this.getStatus() === 'open';\n if (!canProceedWithConnection()) {\n this.log?.info(\n `transport state is no longer open, cancelling attempt to connect to ${to}`,\n { clientId: this.clientId, connectedTo: to },\n );\n return;\n }\n\n let reconnectPromise = this.inflightConnectionPromises.get(to);\n if (!reconnectPromise) {\n // check budget\n if (!this.retryBudget.hasBudget(to)) {\n const budgetConsumed = this.retryBudget.getBudgetConsumed(to);\n const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;\n this.log?.error(errMsg, { clientId: this.clientId, connectedTo: to });\n this.protocolError(ProtocolError.RetriesExceeded, errMsg);\n return;\n }\n\n let sleep = Promise.resolve();\n const backoffMs = this.retryBudget.getBackoffMs(to);\n if (backoffMs > 0) {\n sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n\n this.log?.info(\n `attempting connection to ${to} (${backoffMs}ms backoff)`,\n {\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n this.retryBudget.consumeBudget(to);\n reconnectPromise = tracer.startActiveSpan('connect', async (span) => {\n try {\n span.addEvent('backoff', { backoffMs });\n await sleep;\n if (!canProceedWithConnection()) {\n throw new Error('transport state is no longer open');\n }\n\n span.addEvent('connecting');\n const conn = await this.createNewOutgoingConnection(to);\n if (!canProceedWithConnection()) {\n this.log?.info(\n `transport state is no longer open, closing pre-handshake connection to ${to}`,\n {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n conn.close();\n throw new Error('transport state is no longer open');\n }\n\n span.addEvent('sending handshake');\n const ok = await this.sendHandshake(to, conn);\n if (!ok) {\n conn.close();\n throw new Error('failed to send handshake');\n }\n\n return conn;\n } catch (err) {\n // rethrow the error so that the promise is rejected\n // as it was before we wrapped it in a span\n const errStr = coerceErrorString(err);\n span.recordException(errStr);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw err;\n } finally {\n span.end();\n }\n });\n\n this.inflightConnectionPromises.set(to, reconnectPromise);\n } else {\n this.log?.info(\n `attempting connection to ${to} (reusing previous attempt)`,\n {\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n }\n\n try {\n await reconnectPromise;\n } catch (error: unknown) {\n this.inflightConnectionPromises.delete(to);\n const errStr = coerceErrorString(error);\n\n if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {\n this.log?.warn(`connection to ${to} failed (${errStr})`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n } else {\n this.log?.warn(`connection to ${to} failed (${errStr}), retrying`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n await this.connect(to);\n }\n }\n }\n\n protected deleteSession({\n session,\n closeHandshakingConnection,\n handshakingConn,\n }: {\n session: Session<ConnType>;\n closeHandshakingConnection: boolean;\n handshakingConn?: ConnType;\n }) {\n this.inflightConnectionPromises.delete(session.to);\n super.deleteSession({\n session,\n closeHandshakingConnection,\n handshakingConn,\n });\n }\n\n protected async sendHandshake(to: TransportClientId, conn: ConnType) {\n let metadata: unknown = undefined;\n\n if (this.handshakeExtensions) {\n metadata = await this.handshakeExtensions.construct();\n if (!Value.Check(this.handshakeExtensions.schema, metadata)) {\n this.log?.error(`constructed handshake metadata did not match schema`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n validationErrors: [\n ...Value.Errors(this.handshakeExtensions.schema, metadata),\n ],\n tags: ['invariant-violation'],\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'handshake metadata did not match schema',\n );\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'handshake meta mismatch',\n });\n return false;\n }\n }\n\n // don't pass conn here as we dont want the session to start using the conn\n // until we have finished the handshake. Still, let the session know that\n // it is semi-associated with the conn, and it can close it if .close() is called.\n const { session } = this.getOrCreateSession({ to, handshakingConn: conn });\n const requestMsg = handshakeRequestMessage({\n from: this.clientId,\n to,\n sessionId: session.id,\n expectedSessionState: {\n reconnect: session.advertisedSessionId !== undefined,\n nextExpectedSeq: session.nextExpectedSeq,\n },\n metadata,\n tracing: getPropagationContext(session.telemetry.ctx),\n });\n this.log?.debug(`sending handshake request to ${to}`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n transportMessage: requestMsg,\n });\n conn.send(this.codec.toBuffer(requestMsg));\n return true;\n }\n\n close() {\n this.retryBudget.close();\n super.close();\n }\n}\n","import { TransportClientId } from './message';\n\n/**\n * Options to control the backoff and retry behavior of the client transport's connection behaviour.\n *\n * River implements exponential backoff with jitter to prevent flooding the server\n * when there's an issue with connection establishment.\n *\n * The backoff is calculated via the following:\n * backOff = min(jitter + {@link baseIntervalMs} * 2 ^ budget_consumed, {@link maxBackoffMs})\n *\n * We use a leaky bucket rate limit with a budget of {@link attemptBudgetCapacity} reconnection attempts.\n * Budget only starts to restore after a successful handshake at a rate of one budget per {@link budgetRestoreIntervalMs}.\n */\nexport interface ConnectionRetryOptions {\n /**\n * The base interval to wait before retrying a connection.\n */\n baseIntervalMs: number;\n\n /**\n * The maximum random jitter to add to the total backoff time.\n */\n maxJitterMs: number;\n\n /**\n * The maximum amount of time to wait before retrying a connection.\n * This does not include the jitter.\n */\n maxBackoffMs: number;\n\n /**\n * The max number of times to attempt a connection before a successful handshake.\n * This persists across connections but starts restoring budget after a successful handshake.\n * The restoration interval depends on {@link budgetRestoreIntervalMs}\n */\n attemptBudgetCapacity: number;\n\n /**\n * After a successful connection attempt, how long to wait before we restore a single budget.\n */\n budgetRestoreIntervalMs: number;\n}\n\nexport class LeakyBucketRateLimit {\n private budgetConsumed: Map<TransportClientId, number>;\n private intervalHandles: Map<\n TransportClientId,\n ReturnType<typeof setInterval>\n >;\n private readonly options: ConnectionRetryOptions;\n\n constructor(options: ConnectionRetryOptions) {\n this.options = options;\n this.budgetConsumed = new Map();\n this.intervalHandles = new Map();\n }\n\n getBackoffMs(user: TransportClientId) {\n if (!this.budgetConsumed.has(user)) return 0;\n\n const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);\n const jitter = Math.floor(Math.random() * this.options.maxJitterMs);\n const backoffMs = Math.min(\n this.options.baseIntervalMs * 2 ** exponent,\n this.options.maxBackoffMs,\n );\n\n return backoffMs + jitter;\n }\n\n get totalBudgetRestoreTime() {\n return (\n this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity\n );\n }\n\n consumeBudget(user: TransportClientId) {\n // If we're consuming again, let's ensure that we're not leaking\n this.stopLeak(user);\n this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);\n }\n\n getBudgetConsumed(user: TransportClientId) {\n return this.budgetConsumed.get(user) ?? 0;\n }\n\n hasBudget(user: TransportClientId) {\n return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;\n }\n\n startRestoringBudget(user: TransportClientId) {\n if (this.intervalHandles.has(user)) {\n return;\n }\n\n const restoreBudgetForUser = () => {\n const currentBudget = this.budgetConsumed.get(user);\n if (!currentBudget) {\n this.stopLeak(user);\n return;\n }\n\n const newBudget = currentBudget - 1;\n if (newBudget === 0) {\n this.budgetConsumed.delete(user);\n return;\n }\n\n this.budgetConsumed.set(user, newBudget);\n };\n\n const intervalHandle = setInterval(\n restoreBudgetForUser,\n this.options.budgetRestoreIntervalMs,\n );\n\n this.intervalHandles.set(user, intervalHandle);\n }\n\n private stopLeak(user: TransportClientId) {\n if (!this.intervalHandles.has(user)) {\n return;\n }\n\n clearInterval(this.intervalHandles.get(user));\n this.intervalHandles.delete(user);\n }\n\n close() {\n for (const user of this.intervalHandles.keys()) {\n this.stopLeak(user);\n }\n }\n}\n"],"mappings":"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","names":["data"]}
|