socketduct 0.1.17 → 0.1.19
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 +2 -2
- package/changelog.d/20260925120000-reverse-stream-transport-resume.md +1 -0
- package/changelog.d/20260925143000-reverse-client-process-recovery.md +1 -0
- package/docs/architecture.md +20 -11
- package/docs/protocol.md +56 -11
- package/docs/reverse-gateway.md +91 -24
- package/docs/running.md +2 -2
- package/docs/security.md +22 -5
- package/docs/session-lifecycle.md +32 -10
- package/docs/socket-api.md +57 -16
- package/package.json +1 -1
- package/src/client/multiplexed-transport-set.js +13 -5
- package/src/client/virtual-socket.js +42 -0
- package/src/reverse/client.js +524 -75
- package/src/reverse/gateway.js +265 -38
- package/src/reverse/hub.js +305 -24
- package/src/reverse/runtime.js +1 -0
- package/src/spool/spool-file.js +136 -7
- package/tensorbuzz.yml +2 -1
- package/test/e2e/reverse-client-recovery-process.test.js +170 -0
- package/test/fixtures/reverse-client-recovery.mjs +123 -0
- package/test/integration/reverse-gateway.test.js +996 -28
- package/test/integration/reverse-route-class.test.js +16 -12
- package/test/unit/client/multiplexed-transport-set.test.js +12 -1
- package/test/unit/spool/spool-file.test.js +133 -0
|
@@ -7,6 +7,7 @@ import {Duplex} from "node:stream"
|
|
|
7
7
|
* @property {(streamId: number, callback: (error?: Error | null) => void) => void} _endStream - End the writable side.
|
|
8
8
|
* @property {(streamId: number, error: Error | null) => void} _destroyStream - Destroy the virtual stream.
|
|
9
9
|
* @property {(streamId: number) => void} _resumeReadable - Resume inbound flow.
|
|
10
|
+
* @property {(streamId: number, bytes: number) => void} [_consumeReadable] - Report bytes returned to the application.
|
|
10
11
|
* @property {() => {address?: string, port?: number}} physicalAddress - Current physical endpoint.
|
|
11
12
|
* @property {() => unknown} ref - Reference owner resources.
|
|
12
13
|
* @property {() => unknown} unref - Unreference owner resources.
|
|
@@ -60,6 +61,9 @@ export class VirtualSocket extends Duplex {
|
|
|
60
61
|
/** @type {boolean} */
|
|
61
62
|
#remoteEnded = false
|
|
62
63
|
|
|
64
|
+
/** @type {number} */
|
|
65
|
+
#emittedDataBytes = 0
|
|
66
|
+
|
|
63
67
|
/** @type {boolean} */
|
|
64
68
|
connecting = true
|
|
65
69
|
|
|
@@ -123,6 +127,44 @@ export class VirtualSocket extends Duplex {
|
|
|
123
127
|
this.#connection._resumeReadable(this.#streamId)
|
|
124
128
|
}
|
|
125
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Reports application consumption after Node has emitted flowing data or
|
|
132
|
+
* fulfilled a paused-mode read. Owners that need durable receive ACKs can
|
|
133
|
+
* therefore distinguish consumed bytes from process-local readable bytes.
|
|
134
|
+
* @param {number} [size] - Requested bytes.
|
|
135
|
+
* @returns {Buffer | string | null} Readable chunk.
|
|
136
|
+
* @override
|
|
137
|
+
*/
|
|
138
|
+
read(size) {
|
|
139
|
+
const emittedBefore = this.#emittedDataBytes
|
|
140
|
+
const chunk = super.read(size)
|
|
141
|
+
if (chunk !== null) {
|
|
142
|
+
const bytes = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length
|
|
143
|
+
const emittedBytes = this.#emittedDataBytes - emittedBefore
|
|
144
|
+
if (bytes > emittedBytes) this.#connection._consumeReadable?.(this.#streamId, bytes - emittedBytes)
|
|
145
|
+
}
|
|
146
|
+
return chunk
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A flowing Readable may emit directly from push() without returning a chunk
|
|
151
|
+
* through read(). Report DATA only after application listeners have run.
|
|
152
|
+
* @param {string | symbol} event - Event name.
|
|
153
|
+
* @param {...unknown} args - Event values.
|
|
154
|
+
* @returns {boolean} Whether the event had listeners.
|
|
155
|
+
* @override
|
|
156
|
+
*/
|
|
157
|
+
emit(event, ...args) {
|
|
158
|
+
const emitted = super.emit(event, ...args)
|
|
159
|
+
const chunk = args[0]
|
|
160
|
+
if (event === "data" && (typeof chunk === "string" || Buffer.isBuffer(chunk))) {
|
|
161
|
+
const bytes = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length
|
|
162
|
+
this.#emittedDataBytes += bytes
|
|
163
|
+
this.#connection._consumeReadable?.(this.#streamId, bytes)
|
|
164
|
+
}
|
|
165
|
+
return emitted
|
|
166
|
+
}
|
|
167
|
+
|
|
126
168
|
/**
|
|
127
169
|
* @override
|
|
128
170
|
* @param {Buffer | string | Uint8Array} chunk - Application bytes.
|