velocious 1.0.565 → 1.0.567
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 +5 -1
- package/bin/velocious.js +28 -1
- package/build/bin/velocious.js +28 -1
- package/build/configuration-types.js +1 -0
- package/build/configuration.js +20 -0
- package/build/http-server/client/websocket-session.js +455 -69
- package/build/src/configuration-types.d.ts +8 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +2 -1
- package/build/src/configuration.d.ts +12 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +19 -1
- package/build/src/http-server/client/websocket-session.d.ts +102 -4
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +404 -67
- package/package.json +1 -1
- package/src/configuration-types.js +1 -0
- package/src/configuration.js +20 -0
- package/src/http-server/client/websocket-session.js +455 -69
package/README.md
CHANGED
|
@@ -1180,6 +1180,8 @@ Evaluate inline JavaScript (Rails-style runner) with initialized app/database co
|
|
|
1180
1180
|
npx velocious runner "const users = await db.query('SELECT COUNT(*) AS count FROM users'); console.log(users[0].count)"
|
|
1181
1181
|
```
|
|
1182
1182
|
|
|
1183
|
+
Successful CLI commands exit with status `0`. If command execution rejects, Velocious marks the process failed and always runs final database cleanup. Successful cleanup preserves and rethrows the original command error unchanged; if cleanup also fails, an `AggregateError` retains the command error first and as its `cause`, followed by the cleanup error. Cleanup-only failures also exit nonzero. These failures therefore remain nonzero even when application code installs an `uncaughtException` listener that reports and consumes the error. See [CLI process exit behavior](docs/cli.md#process-exit-behavior).
|
|
1184
|
+
|
|
1183
1185
|
By default, migrations write `db/structure-<identifier>.sql` files for each database in non-test environments. Test skips these automatic writes unless you explicitly opt in. Configure allow/deny lists in your configuration:
|
|
1184
1186
|
|
|
1185
1187
|
```js
|
|
@@ -1568,7 +1570,7 @@ database: {
|
|
|
1568
1570
|
|
|
1569
1571
|
Velocious includes a lightweight websocket entry point for API-style calls and server-side events.
|
|
1570
1572
|
|
|
1571
|
-
Inbound frames remain ordered when TCP splits a frame across reads. Velocious limits a single final client data frame and a reassembled fragmented message to 16 MiB; larger payloads close the connection.
|
|
1573
|
+
Inbound frames remain ordered when TCP splits a frame across reads. Velocious limits a single final client data frame and a reassembled fragmented message to 16 MiB; larger payloads close the connection. Decoded inbound work is bounded independently per session before authorization or request handling: the defaults retain at most 256 active/queued messages or 16 MiB of raw UTF-8 payload bytes. Exact FIFO is preserved within the limits. A next message exceeding either limit is rejected before decoding and permanently closes that session with status `1008` and reason `Inbound message backlog exceeded`. Configure positive safe integers with `httpServer.websocketInboundQueue.maxPendingMessages` and `maxPendingBytes`.
|
|
1572
1574
|
|
|
1573
1575
|
Server-to-client WebSocket delivery is bounded independently per client. The defaults retain at most 256 queued/in-flight completed frames or 16 MiB of serialized frame output; the HTTP 101 upgrade response and ordinary HTTP/file output remain outside that budget, while exact FIFO is preserved. A slow client that exceeds either limit is reported through the framework error events and deterministically closed without affecting other clients. V2 channel broadcast delivery and persistence remain isolated to the originating configuration when several applications share a process. Configure positive safe integers with `httpServer.websocketOutboundQueue.maxPendingFrames` and `maxPendingBytes`. See [WebSocket connections](docs/websocket-connections.md) for configuration and wire-protocol details.
|
|
1574
1576
|
|
|
@@ -1712,6 +1714,8 @@ configuration.getErrorEvents().on("all-error", ({error, errorType}) => {
|
|
|
1712
1714
|
|
|
1713
1715
|
Genuinely unexpected frontend-model command failures reach this bus too. The frontend-model controller catches them to return a client-safe `Request failed.` response, but it also emits them as `framework-error`/`all-error` (with `context.frontendModelEndpoint === true`) so they are reported instead of being silently swallowed. Expected user-flow errors are excluded: validation failures are forwarded with their real message (for example `Name can't be blank`), invalid client query descriptors are returned as frontend-model query errors, and `error.velocious`-annotated / `safeToExpose` / `errorType`-marked errors keep their expected-error status — none of these reach the error bus.
|
|
1714
1716
|
|
|
1717
|
+
Unexpected inbound decoded WebSocket dispatch failures emit one `framework-error` and one matching `all-error`. Established expected client-flow errors remain excluded from both events.
|
|
1718
|
+
|
|
1715
1719
|
## Use the Websocket client API (HTTP-like)
|
|
1716
1720
|
|
|
1717
1721
|
```js
|
package/bin/velocious.js
CHANGED
|
@@ -39,10 +39,37 @@ const cli = new Cli({
|
|
|
39
39
|
processArgs
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
+
let commandError
|
|
43
|
+
let commandFailed = false
|
|
44
|
+
|
|
42
45
|
try {
|
|
43
46
|
await cli.execute()
|
|
44
|
-
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
commandError = error
|
|
49
|
+
commandFailed = true
|
|
50
|
+
process.exitCode = 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let cleanupError
|
|
54
|
+
let cleanupFailed = false
|
|
55
|
+
|
|
56
|
+
try {
|
|
45
57
|
await configuration.closeDatabaseConnections()
|
|
58
|
+
} catch (error) {
|
|
59
|
+
cleanupError = error
|
|
60
|
+
cleanupFailed = true
|
|
61
|
+
process.exitCode = 1
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (commandFailed && cleanupFailed) {
|
|
65
|
+
throw new AggregateError(
|
|
66
|
+
[commandError, cleanupError],
|
|
67
|
+
"Velocious CLI command execution and database cleanup both failed",
|
|
68
|
+
{cause: commandError}
|
|
69
|
+
)
|
|
46
70
|
}
|
|
47
71
|
|
|
72
|
+
if (commandFailed) throw commandError
|
|
73
|
+
if (cleanupFailed) throw cleanupError
|
|
74
|
+
|
|
48
75
|
process.exit(0)
|
package/build/bin/velocious.js
CHANGED
|
@@ -39,10 +39,37 @@ const cli = new Cli({
|
|
|
39
39
|
processArgs
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
+
let commandError
|
|
43
|
+
let commandFailed = false
|
|
44
|
+
|
|
42
45
|
try {
|
|
43
46
|
await cli.execute()
|
|
44
|
-
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
commandError = error
|
|
49
|
+
commandFailed = true
|
|
50
|
+
process.exitCode = 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let cleanupError
|
|
54
|
+
let cleanupFailed = false
|
|
55
|
+
|
|
56
|
+
try {
|
|
45
57
|
await configuration.closeDatabaseConnections()
|
|
58
|
+
} catch (error) {
|
|
59
|
+
cleanupError = error
|
|
60
|
+
cleanupFailed = true
|
|
61
|
+
process.exitCode = 1
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (commandFailed && cleanupFailed) {
|
|
65
|
+
throw new AggregateError(
|
|
66
|
+
[commandError, cleanupError],
|
|
67
|
+
"Velocious CLI command execution and database cleanup both failed",
|
|
68
|
+
{cause: commandError}
|
|
69
|
+
)
|
|
46
70
|
}
|
|
47
71
|
|
|
72
|
+
if (commandFailed) throw commandError
|
|
73
|
+
if (cleanupFailed) throw cleanupError
|
|
74
|
+
|
|
48
75
|
process.exit(0)
|
|
@@ -255,6 +255,7 @@
|
|
|
255
255
|
* @property {boolean} [inProcess] - Run HTTP handlers in the main thread instead of worker threads.
|
|
256
256
|
* @property {number} [maxWorkers] - Backward-compatible alias for workers.
|
|
257
257
|
* @property {number} [port] - Port to bind the HTTP server to.
|
|
258
|
+
* @property {{maxPendingBytes?: number, maxPendingMessages?: number}} [websocketInboundQueue] - Per-session retained inbound WebSocket message limits.
|
|
258
259
|
* @property {{maxPendingBytes?: number, maxPendingFrames?: number}} [websocketOutboundQueue] - Per-client retained outbound WebSocket frame limits.
|
|
259
260
|
* @property {number} [workers] - Worker handlers to start for the HTTP server.
|
|
260
261
|
*/
|
package/build/configuration.js
CHANGED
|
@@ -114,6 +114,8 @@ function resolveBeaconUnreachableReportMs(value) {
|
|
|
114
114
|
return 30_000
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
const DEFAULT_WEBSOCKET_INBOUND_MAX_PENDING_BYTES = 16 * 1024 * 1024
|
|
118
|
+
const DEFAULT_WEBSOCKET_INBOUND_MAX_PENDING_MESSAGES = 256
|
|
117
119
|
const DEFAULT_WEBSOCKET_OUTBOUND_MAX_PENDING_BYTES = 16 * 1024 * 1024
|
|
118
120
|
const DEFAULT_WEBSOCKET_OUTBOUND_MAX_PENDING_FRAMES = 256
|
|
119
121
|
|
|
@@ -228,10 +230,15 @@ export default class VelociousConfiguration {
|
|
|
228
230
|
* @type {Promise<void> | undefined}
|
|
229
231
|
*/
|
|
230
232
|
this._initializePromise = undefined
|
|
233
|
+
const websocketInboundQueue = httpServer?.websocketInboundQueue
|
|
231
234
|
const websocketOutboundQueue = httpServer?.websocketOutboundQueue
|
|
232
235
|
|
|
233
236
|
this.httpServer = {
|
|
234
237
|
...(httpServer || {}),
|
|
238
|
+
websocketInboundQueue: {
|
|
239
|
+
maxPendingBytes: positiveSafeInteger(websocketInboundQueue?.maxPendingBytes, "httpServer.websocketInboundQueue.maxPendingBytes", DEFAULT_WEBSOCKET_INBOUND_MAX_PENDING_BYTES),
|
|
240
|
+
maxPendingMessages: positiveSafeInteger(websocketInboundQueue?.maxPendingMessages, "httpServer.websocketInboundQueue.maxPendingMessages", DEFAULT_WEBSOCKET_INBOUND_MAX_PENDING_MESSAGES)
|
|
241
|
+
},
|
|
235
242
|
websocketOutboundQueue: {
|
|
236
243
|
maxPendingBytes: positiveSafeInteger(websocketOutboundQueue?.maxPendingBytes, "httpServer.websocketOutboundQueue.maxPendingBytes", DEFAULT_WEBSOCKET_OUTBOUND_MAX_PENDING_BYTES),
|
|
237
244
|
maxPendingFrames: positiveSafeInteger(websocketOutboundQueue?.maxPendingFrames, "httpServer.websocketOutboundQueue.maxPendingFrames", DEFAULT_WEBSOCKET_OUTBOUND_MAX_PENDING_FRAMES)
|
|
@@ -2370,6 +2377,19 @@ export default class VelociousConfiguration {
|
|
|
2370
2377
|
*/
|
|
2371
2378
|
getWebsocketSessionHeartbeatSeconds() { return this._websocketSessionHeartbeatSeconds }
|
|
2372
2379
|
|
|
2380
|
+
/**
|
|
2381
|
+
* Gets per-session WebSocket inbound message queue limits.
|
|
2382
|
+
* @returns {{maxBytes: number, maxMessages: number}} - Per-session inbound queue high-water marks.
|
|
2383
|
+
*/
|
|
2384
|
+
getWebsocketInboundQueueLimits() {
|
|
2385
|
+
const queue = this.httpServer.websocketInboundQueue
|
|
2386
|
+
|
|
2387
|
+
return {
|
|
2388
|
+
maxBytes: queue.maxPendingBytes,
|
|
2389
|
+
maxMessages: queue.maxPendingMessages
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2373
2393
|
/**
|
|
2374
2394
|
* Gets per-client WebSocket outbound queue limits.
|
|
2375
2395
|
* @returns {{maxBytes: number, maxFrames: number}} - Per-client outbound queue high-water marks.
|