velocious 1.0.562 → 1.0.564
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/build/background-jobs/cron-expression.js +12 -13
- package/build/background-jobs/main.js +6 -6
- package/build/background-jobs/runner-graceful-shutdown.js +2 -3
- package/build/background-jobs/scheduler.js +3 -3
- package/build/background-jobs/worker.js +8 -9
- package/build/beacon/client.js +3 -4
- package/build/configuration-types.js +1 -0
- package/build/configuration.js +44 -3
- package/build/database/drivers/sqlite/web-persistence.js +2 -5
- package/build/database/pool/async-tracked-multi-connection.js +65 -15
- package/build/database/pool/base.js +23 -7
- package/build/database/query/index.js +21 -22
- package/build/database/query/model-class-query.js +5 -6
- package/build/database/record/attachments/normalize-input.js +9 -10
- package/build/database/record/attachments/store.js +2 -2
- package/build/database/record/auditing.js +7 -8
- package/build/database/record/index.js +4 -5
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +1 -2
- package/build/frontend-model-controller.js +49 -56
- package/build/frontend-models/base.js +17 -19
- package/build/frontend-models/outgoing-event-buffer.js +3 -4
- package/build/frontend-models/query.js +40 -44
- package/build/frontend-models/resource-definition.js +7 -8
- package/build/frontend-models/transport-serialization.js +10 -12
- package/build/frontend-models/websocket-channel.js +12 -13
- package/build/http-server/client/websocket-session.js +7 -8
- package/build/http-server/client-delivery-queue.js +167 -0
- package/build/http-server/server-client.js +9 -0
- package/build/http-server/websocket-event-log-store.js +4 -6
- package/build/http-server/websocket-events-host.js +42 -12
- package/build/http-server/worker-handler/in-process.js +53 -14
- package/build/http-server/worker-handler/index.js +88 -18
- package/build/http-server/worker-handler/worker-thread.js +2 -2
- package/build/plugins/sqljs-wasm-route.js +3 -5
- package/build/src/background-jobs/cron-expression.d.ts +0 -12
- package/build/src/background-jobs/cron-expression.d.ts.map +1 -1
- package/build/src/background-jobs/cron-expression.js +13 -13
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +7 -7
- package/build/src/background-jobs/runner-graceful-shutdown.d.ts +0 -6
- package/build/src/background-jobs/runner-graceful-shutdown.d.ts.map +1 -1
- package/build/src/background-jobs/runner-graceful-shutdown.js +3 -3
- package/build/src/background-jobs/scheduler.d.ts +0 -3
- package/build/src/background-jobs/scheduler.d.ts.map +1 -1
- package/build/src/background-jobs/scheduler.js +4 -4
- package/build/src/background-jobs/worker.d.ts +0 -8
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +9 -9
- package/build/src/beacon/client.d.ts +0 -4
- package/build/src/beacon/client.d.ts.map +1 -1
- package/build/src/beacon/client.js +4 -4
- 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 +34 -1
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +40 -4
- package/build/src/database/drivers/sqlite/web-persistence.d.ts +0 -14
- package/build/src/database/drivers/sqlite/web-persistence.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/web-persistence.js +3 -3
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +29 -1
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +57 -15
- package/build/src/database/pool/base.d.ts +53 -4
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +23 -6
- package/build/src/database/query/index.d.ts +18 -39
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +22 -22
- package/build/src/database/query/model-class-query.d.ts +0 -5
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +6 -6
- package/build/src/database/record/attachments/normalize-input.d.ts +0 -9
- package/build/src/database/record/attachments/normalize-input.d.ts.map +1 -1
- package/build/src/database/record/attachments/normalize-input.js +10 -10
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +2 -2
- package/build/src/database/record/auditing.d.ts +17 -24
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +8 -8
- package/build/src/database/record/index.d.ts +4 -4
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +5 -5
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +0 -39
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +2 -2
- package/build/src/frontend-model-controller.d.ts +1 -1
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +50 -50
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +18 -18
- package/build/src/frontend-models/outgoing-event-buffer.d.ts.map +1 -1
- package/build/src/frontend-models/outgoing-event-buffer.js +3 -3
- package/build/src/frontend-models/query.d.ts +56 -37
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +39 -39
- package/build/src/frontend-models/resource-definition.d.ts +0 -7
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +8 -8
- package/build/src/frontend-models/transport-serialization.d.ts +0 -10
- package/build/src/frontend-models/transport-serialization.d.ts.map +1 -1
- package/build/src/frontend-models/transport-serialization.js +11 -11
- package/build/src/frontend-models/websocket-channel.d.ts +0 -12
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +13 -13
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +8 -8
- package/build/src/http-server/client-delivery-queue.d.ts +121 -0
- package/build/src/http-server/client-delivery-queue.d.ts.map +1 -0
- package/build/src/http-server/client-delivery-queue.js +152 -0
- package/build/src/http-server/server-client.d.ts +6 -0
- package/build/src/http-server/server-client.d.ts.map +1 -1
- package/build/src/http-server/server-client.js +10 -1
- package/build/src/http-server/websocket-event-log-store.d.ts +0 -14
- package/build/src/http-server/websocket-event-log-store.d.ts.map +1 -1
- package/build/src/http-server/websocket-event-log-store.js +5 -5
- package/build/src/http-server/websocket-events-host.d.ts +15 -4
- package/build/src/http-server/websocket-events-host.d.ts.map +1 -1
- package/build/src/http-server/websocket-events-host.js +39 -13
- package/build/src/http-server/worker-handler/in-process.d.ts +19 -1
- package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/in-process.js +50 -14
- package/build/src/http-server/worker-handler/index.d.ts +36 -4
- package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/index.js +82 -18
- package/build/src/http-server/worker-handler/worker-thread.js +3 -3
- package/build/src/plugins/sqljs-wasm-route.d.ts.map +1 -1
- package/build/src/plugins/sqljs-wasm-route.js +4 -4
- package/build/src/sync/conflict-strategy.d.ts +0 -15
- package/build/src/sync/conflict-strategy.d.ts.map +1 -1
- package/build/src/sync/conflict-strategy.js +3 -3
- package/build/src/sync/device-identity.d.ts +0 -45
- package/build/src/sync/device-identity.d.ts.map +1 -1
- package/build/src/sync/device-identity.js +4 -4
- package/build/src/sync/local-mutation-log.d.ts +0 -41
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +9 -9
- package/build/src/sync/offline-grant.d.ts +0 -26
- package/build/src/sync/offline-grant.d.ts.map +1 -1
- package/build/src/sync/offline-grant.js +4 -4
- package/build/src/sync/peer-mutation-bundle.d.ts +0 -14
- package/build/src/sync/peer-mutation-bundle.d.ts.map +1 -1
- package/build/src/sync/peer-mutation-bundle.js +3 -3
- package/build/src/sync/server-change-feed.d.ts.map +1 -1
- package/build/src/sync/server-change-feed.js +33 -33
- package/build/src/sync/sync-api-client.d.ts +0 -9
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +2 -2
- package/build/src/sync/sync-envelope-replay-service.d.ts +38 -21
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +18 -18
- package/build/src/sync/sync-resource-base.d.ts +0 -7
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +2 -2
- package/build/src/sync/sync-scope-store.d.ts +0 -9
- package/build/src/sync/sync-scope-store.d.ts.map +1 -1
- package/build/src/sync/sync-scope-store.js +10 -10
- package/build/src/testing/test-filter-parser.d.ts +0 -10
- package/build/src/testing/test-filter-parser.d.ts.map +1 -1
- package/build/src/testing/test-filter-parser.js +11 -11
- package/build/src/testing/test-runner.d.ts +25 -91
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +113 -98
- package/build/src/testing/test.d.ts +8 -0
- package/build/src/testing/test.d.ts.map +1 -1
- package/build/src/testing/test.js +9 -9
- package/build/src/utils/backtrace-cleaner.d.ts.map +1 -1
- package/build/src/utils/backtrace-cleaner.js +9 -9
- package/build/src/utils/model-scope.d.ts +0 -8
- package/build/src/utils/model-scope.d.ts.map +1 -1
- package/build/src/utils/model-scope.js +3 -3
- package/build/src/utils/ransack.d.ts +52 -19
- package/build/src/utils/ransack.d.ts.map +1 -1
- package/build/src/utils/ransack.js +26 -26
- package/build/sync/conflict-strategy.js +3 -6
- package/build/sync/device-identity.js +4 -9
- package/build/sync/local-mutation-log.js +9 -14
- package/build/sync/offline-grant.js +4 -7
- package/build/sync/peer-mutation-bundle.js +2 -4
- package/build/sync/server-change-feed.js +32 -34
- package/build/sync/sync-api-client.js +1 -2
- package/build/sync/sync-envelope-replay-service.js +17 -19
- package/build/sync/sync-resource-base.js +1 -2
- package/build/sync/sync-scope-store.js +9 -10
- package/build/testing/test-filter-parser.js +10 -11
- package/build/testing/test-runner.js +116 -108
- package/build/testing/test.js +8 -9
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/utils/backtrace-cleaner.js +8 -9
- package/build/utils/model-scope.js +3 -4
- package/build/utils/ransack.js +27 -34
- package/package.json +3 -1
- package/scripts/eslint-rules/typedefs-first.js +67 -0
- package/scripts/prewarm-chromedriver.js +26 -0
- package/src/background-jobs/cron-expression.js +12 -13
- package/src/background-jobs/main.js +6 -6
- package/src/background-jobs/runner-graceful-shutdown.js +2 -3
- package/src/background-jobs/scheduler.js +3 -3
- package/src/background-jobs/worker.js +8 -9
- package/src/beacon/client.js +3 -4
- package/src/configuration-types.js +1 -0
- package/src/configuration.js +44 -3
- package/src/database/drivers/sqlite/web-persistence.js +2 -5
- package/src/database/pool/async-tracked-multi-connection.js +65 -15
- package/src/database/pool/base.js +23 -7
- package/src/database/query/index.js +21 -22
- package/src/database/query/model-class-query.js +5 -6
- package/src/database/record/attachments/normalize-input.js +9 -10
- package/src/database/record/attachments/store.js +2 -2
- package/src/database/record/auditing.js +7 -8
- package/src/database/record/index.js +4 -5
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +1 -2
- package/src/frontend-model-controller.js +49 -56
- package/src/frontend-models/base.js +17 -19
- package/src/frontend-models/outgoing-event-buffer.js +3 -4
- package/src/frontend-models/query.js +40 -44
- package/src/frontend-models/resource-definition.js +7 -8
- package/src/frontend-models/transport-serialization.js +10 -12
- package/src/frontend-models/websocket-channel.js +12 -13
- package/src/http-server/client/websocket-session.js +7 -8
- package/src/http-server/client-delivery-queue.js +167 -0
- package/src/http-server/server-client.js +9 -0
- package/src/http-server/websocket-event-log-store.js +4 -6
- package/src/http-server/websocket-events-host.js +42 -12
- package/src/http-server/worker-handler/in-process.js +53 -14
- package/src/http-server/worker-handler/index.js +88 -18
- package/src/http-server/worker-handler/worker-thread.js +2 -2
- package/src/plugins/sqljs-wasm-route.js +3 -5
- package/src/sync/conflict-strategy.js +3 -6
- package/src/sync/device-identity.js +4 -9
- package/src/sync/local-mutation-log.js +9 -14
- package/src/sync/offline-grant.js +4 -7
- package/src/sync/peer-mutation-bundle.js +2 -4
- package/src/sync/server-change-feed.js +32 -34
- package/src/sync/sync-api-client.js +1 -2
- package/src/sync/sync-envelope-replay-service.js +17 -19
- package/src/sync/sync-resource-base.js +1 -2
- package/src/sync/sync-scope-store.js +9 -10
- package/src/testing/test-filter-parser.js +10 -11
- package/src/testing/test-runner.js +116 -108
- package/src/testing/test.js +8 -9
- package/src/utils/backtrace-cleaner.js +8 -9
- package/src/utils/model-scope.js +3 -4
- package/src/utils/ransack.js +27 -34
|
@@ -5,28 +5,6 @@ import {normalizeRansackGroup, parseRansackSort} from "../utils/ransack.js"
|
|
|
5
5
|
import {isModelScopeDescriptor} from "../utils/model-scope.js"
|
|
6
6
|
import isPlainObject from "../utils/plain-object.js"
|
|
7
7
|
|
|
8
|
-
/** Error raised when a frontend-model query descriptor is malformed. */
|
|
9
|
-
export class FrontendModelQueryError extends Error {
|
|
10
|
-
/**
|
|
11
|
-
* Creates a frontend-model query error.
|
|
12
|
-
* @param {string} message - Error message.
|
|
13
|
-
*/
|
|
14
|
-
constructor(message) {
|
|
15
|
-
super(message)
|
|
16
|
-
|
|
17
|
-
this.name = "FrontendModelQueryError"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Builds a query descriptor error.
|
|
23
|
-
* @param {string} message - Error message.
|
|
24
|
-
* @returns {FrontendModelQueryError} - Query descriptor error.
|
|
25
|
-
*/
|
|
26
|
-
function frontendModelQueryError(message) {
|
|
27
|
-
return new FrontendModelQueryError(message)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
8
|
/**
|
|
31
9
|
* FrontendModelSearch type.
|
|
32
10
|
* @typedef {object} FrontendModelSearch
|
|
@@ -97,6 +75,46 @@ function frontendModelQueryError(message) {
|
|
|
97
75
|
* @property {FrontendModelEventFilterPayload | null} eventFilterPayload - Normalized event filter payload, or null when unfiltered.
|
|
98
76
|
* @property {FrontendModelProjectionPayload} projectionPayload - Normalized event serialization projection payload.
|
|
99
77
|
*/
|
|
78
|
+
/**
|
|
79
|
+
* FrontendModelSort type.
|
|
80
|
+
* @typedef {object} FrontendModelSort
|
|
81
|
+
* @property {string} column - Attribute name to sort by.
|
|
82
|
+
* @property {"asc" | "desc"} direction - Sort direction.
|
|
83
|
+
* @property {string[]} path - Relationship path from root model.
|
|
84
|
+
*/
|
|
85
|
+
/**
|
|
86
|
+
* FrontendModelGroup type.
|
|
87
|
+
* @typedef {object} FrontendModelGroup
|
|
88
|
+
* @property {string} column - Attribute name to group by.
|
|
89
|
+
* @property {string[]} path - Relationship path from root model.
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* FrontendModelPluck type.
|
|
93
|
+
* @typedef {object} FrontendModelPluck
|
|
94
|
+
* @property {string} column - Attribute name to pluck.
|
|
95
|
+
* @property {string[]} path - Relationship path from root model.
|
|
96
|
+
*/
|
|
97
|
+
/** Error raised when a frontend-model query descriptor is malformed. */
|
|
98
|
+
export class FrontendModelQueryError extends Error {
|
|
99
|
+
/**
|
|
100
|
+
* Creates a frontend-model query error.
|
|
101
|
+
* @param {string} message - Error message.
|
|
102
|
+
*/
|
|
103
|
+
constructor(message) {
|
|
104
|
+
super(message)
|
|
105
|
+
|
|
106
|
+
this.name = "FrontendModelQueryError"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Builds a query descriptor error.
|
|
112
|
+
* @param {string} message - Error message.
|
|
113
|
+
* @returns {FrontendModelQueryError} - Query descriptor error.
|
|
114
|
+
*/
|
|
115
|
+
function frontendModelQueryError(message) {
|
|
116
|
+
return new FrontendModelQueryError(message)
|
|
117
|
+
}
|
|
100
118
|
|
|
101
119
|
/**
|
|
102
120
|
* Runs the normalizePreload helper.
|
|
@@ -490,28 +508,6 @@ export function normalizeJoins(joins) {
|
|
|
490
508
|
return normalized
|
|
491
509
|
}
|
|
492
510
|
|
|
493
|
-
/**
|
|
494
|
-
* FrontendModelSort type.
|
|
495
|
-
* @typedef {object} FrontendModelSort
|
|
496
|
-
* @property {string} column - Attribute name to sort by.
|
|
497
|
-
* @property {"asc" | "desc"} direction - Sort direction.
|
|
498
|
-
* @property {string[]} path - Relationship path from root model.
|
|
499
|
-
*/
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* FrontendModelGroup type.
|
|
503
|
-
* @typedef {object} FrontendModelGroup
|
|
504
|
-
* @property {string} column - Attribute name to group by.
|
|
505
|
-
* @property {string[]} path - Relationship path from root model.
|
|
506
|
-
*/
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* FrontendModelPluck type.
|
|
510
|
-
* @typedef {object} FrontendModelPluck
|
|
511
|
-
* @property {string} column - Attribute name to pluck.
|
|
512
|
-
* @property {string[]} path - Relationship path from root model.
|
|
513
|
-
*/
|
|
514
|
-
|
|
515
511
|
/**
|
|
516
512
|
* Runs normalize sort direction.
|
|
517
513
|
* @param {?} direction - Direction value.
|
|
@@ -5,6 +5,13 @@ import FrontendModelBaseResource from "../frontend-model-resource/base-resource.
|
|
|
5
5
|
import restArgsError from "../utils/rest-args-error.js"
|
|
6
6
|
import {validateFrontendModelResourceCommandName} from "./resource-config-validation.js"
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Resolved frontend-model resource registration for a replay resource type.
|
|
10
|
+
* @typedef {object} FrontendModelResolvedResourceRegistration
|
|
11
|
+
* @property {string} modelName - Effective frontend model name (modelName override or registry key).
|
|
12
|
+
* @property {import("../configuration-types.js").FrontendModelResourceClassType} resourceClass - Registered resource class.
|
|
13
|
+
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} resourceConfiguration - Normalized resource configuration.
|
|
14
|
+
*/
|
|
8
15
|
const BASE_FRONTEND_MODEL_ABILITY_ACTIONS = ["create", "destroy", "read", "update"]
|
|
9
16
|
const SHA256_INITIAL_HASH = [
|
|
10
17
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
|
@@ -1027,14 +1034,6 @@ function normalizeFrontendModelResourcePathForMatch(path) {
|
|
|
1027
1034
|
return withLeadingSlash
|
|
1028
1035
|
}
|
|
1029
1036
|
|
|
1030
|
-
/**
|
|
1031
|
-
* Resolved frontend-model resource registration for a replay resource type.
|
|
1032
|
-
* @typedef {object} FrontendModelResolvedResourceRegistration
|
|
1033
|
-
* @property {string} modelName - Effective frontend model name (modelName override or registry key).
|
|
1034
|
-
* @property {import("../configuration-types.js").FrontendModelResourceClassType} resourceClass - Registered resource class.
|
|
1035
|
-
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} resourceConfiguration - Normalized resource configuration.
|
|
1036
|
-
*/
|
|
1037
|
-
|
|
1038
1037
|
/**
|
|
1039
1038
|
* Resolves the registered frontend-model resource class for a resource type
|
|
1040
1039
|
* across all backend projects. A resource's effective name is its
|
|
@@ -4,28 +4,26 @@ import {resolveFrontendModelClass} from "./model-registry.js"
|
|
|
4
4
|
import isPlainObject from "../utils/plain-object.js"
|
|
5
5
|
import {formatDateInTimeZone, validateTimeZone} from "../time-zone.js"
|
|
6
6
|
|
|
7
|
-
const TYPE_KEY = "__velocious_type"
|
|
8
|
-
const TYPE_DATE = "date"
|
|
9
|
-
const TYPE_UNDEFINED = "undefined"
|
|
10
|
-
const TYPE_BIGINT = "bigint"
|
|
11
|
-
const TYPE_NUMBER = "number"
|
|
12
|
-
const TYPE_FRONTEND_MODEL = "frontend_model"
|
|
13
|
-
const NUMBER_NAN = "NaN"
|
|
14
|
-
const NUMBER_POSITIVE_INFINITY = "Infinity"
|
|
15
|
-
const NUMBER_NEGATIVE_INFINITY = "-Infinity"
|
|
16
|
-
const PRELOADED_RELATIONSHIPS_KEY = "__preloadedRelationships"
|
|
17
|
-
|
|
18
7
|
/**
|
|
19
8
|
* Frontend model transport serialization options.
|
|
20
9
|
* @typedef {object} FrontendModelTransportSerializationOptions
|
|
21
10
|
* @property {string | undefined} [timeZone] - IANA timezone used when serializing Date instants.
|
|
22
11
|
*/
|
|
23
|
-
|
|
24
12
|
/**
|
|
25
13
|
* Normalized frontend model transport serialization options.
|
|
26
14
|
* @typedef {object} NormalizedFrontendModelTransportSerializationOptions
|
|
27
15
|
* @property {string | undefined} timeZone - Validated IANA timezone used when serializing Date instants.
|
|
28
16
|
*/
|
|
17
|
+
const TYPE_KEY = "__velocious_type"
|
|
18
|
+
const TYPE_DATE = "date"
|
|
19
|
+
const TYPE_UNDEFINED = "undefined"
|
|
20
|
+
const TYPE_BIGINT = "bigint"
|
|
21
|
+
const TYPE_NUMBER = "number"
|
|
22
|
+
const TYPE_FRONTEND_MODEL = "frontend_model"
|
|
23
|
+
const NUMBER_NAN = "NaN"
|
|
24
|
+
const NUMBER_POSITIVE_INFINITY = "Infinity"
|
|
25
|
+
const NUMBER_NEGATIVE_INFINITY = "-Infinity"
|
|
26
|
+
const PRELOADED_RELATIONSHIPS_KEY = "__preloadedRelationships"
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* Assign a key to a plain object without triggering the `__proto__` setter.
|
|
@@ -4,6 +4,18 @@ import VelociousWebsocketChannel from "../http-server/websocket-channel.js"
|
|
|
4
4
|
import Response from "../http-server/client/response.js"
|
|
5
5
|
import {serializeFrontendModelTransportValue} from "./transport-serialization.js"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Defines this typedef.
|
|
9
|
+
* @typedef {{action?: string, id?: string | number, matchedEventFilterKeys?: string[], record?: import("./query.js").FrontendModelTransportValue, [key: string]: import("./query.js").FrontendModelTransportValue | string[] | undefined}} FrontendModelLifecycleBroadcastBody
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Defines this typedef.
|
|
13
|
+
* @typedef {{headers?: () => Record<string, string | string[] | undefined>, remoteAddress?: () => string | undefined}} FrontendModelWebsocketUpgradeRequest
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Defines this typedef.
|
|
17
|
+
* @typedef {{headers: () => Record<string, string | string[] | undefined>, header: (name: string) => string | string[] | undefined, metadata: (key?: string) => Record<string, import("./query.js").FrontendModelTransportValue> | import("./query.js").FrontendModelTransportValue | undefined, path: () => string, httpMethod: () => string, remoteAddress: () => string | undefined, origin: () => string | string[] | undefined}} FrontendModelWebsocketSyntheticRequest
|
|
18
|
+
*/
|
|
7
19
|
const EVENT_FILTER_KEYS = new Set(["joins", "key", "searches", "where"])
|
|
8
20
|
|
|
9
21
|
// Mirrors FRONTEND_MODELS_CHANNEL_NAME in ./websocket-publishers.js, duplicated here
|
|
@@ -21,19 +33,6 @@ function transportSerializationOptionsForConfiguration(configuration) {
|
|
|
21
33
|
}
|
|
22
34
|
}
|
|
23
35
|
|
|
24
|
-
/**
|
|
25
|
-
* Defines this typedef.
|
|
26
|
-
* @typedef {{action?: string, id?: string | number, matchedEventFilterKeys?: string[], record?: import("./query.js").FrontendModelTransportValue, [key: string]: import("./query.js").FrontendModelTransportValue | string[] | undefined}} FrontendModelLifecycleBroadcastBody
|
|
27
|
-
*/
|
|
28
|
-
/**
|
|
29
|
-
* Defines this typedef.
|
|
30
|
-
* @typedef {{headers?: () => Record<string, string | string[] | undefined>, remoteAddress?: () => string | undefined}} FrontendModelWebsocketUpgradeRequest
|
|
31
|
-
*/
|
|
32
|
-
/**
|
|
33
|
-
* Defines this typedef.
|
|
34
|
-
* @typedef {{headers: () => Record<string, string | string[] | undefined>, header: (name: string) => string | string[] | undefined, metadata: (key?: string) => Record<string, import("./query.js").FrontendModelTransportValue> | import("./query.js").FrontendModelTransportValue | undefined, path: () => string, httpMethod: () => string, remoteAddress: () => string | undefined, origin: () => string | string[] | undefined}} FrontendModelWebsocketSyntheticRequest
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
36
|
/**
|
|
38
37
|
* Per-session channel subscription for frontend-model lifecycle events.
|
|
39
38
|
* Replaces the legacy `FrontendModelWebsocketChannel` (Phase 3).
|
|
@@ -9,6 +9,10 @@ import WebsocketRequest from "./websocket-request.js"
|
|
|
9
9
|
import WebsocketChannel from "../websocket-channel.js"
|
|
10
10
|
import {websocketEventLogStoreForConfiguration} from "../websocket-event-log-store.js"
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Defines this typedef.
|
|
14
|
+
* @typedef {{type: "subscribe", channel: string, lastEventId?: string, params?: Record<string, ?>} | {type: "metadata", data?: Record<string, ?>} | {type?: "request", body?: ?, headers?: Record<string, ?>, id?: string | number | null, method: string, path: string} | Record<string, ?>} WebsocketSessionMessage
|
|
15
|
+
*/
|
|
12
16
|
const WEBSOCKET_FINAL_FRAME = 0x80
|
|
13
17
|
const WEBSOCKET_OPCODE_CONTINUATION = 0x0
|
|
14
18
|
const WEBSOCKET_OPCODE_TEXT = 0x1
|
|
@@ -31,11 +35,6 @@ const WEBSOCKET_MAX_INBOUND_FRAME_BYTES_BIGINT = BigInt(WEBSOCKET_MAX_FINAL_FRAM
|
|
|
31
35
|
/** Cap on fragment count for a single fragmented message. */
|
|
32
36
|
const WEBSOCKET_MAX_FRAGMENTED_MESSAGE_FRAGMENTS = 1024
|
|
33
37
|
|
|
34
|
-
/**
|
|
35
|
-
* Defines this typedef.
|
|
36
|
-
* @typedef {{type: "subscribe", channel: string, lastEventId?: string, params?: Record<string, ?>} | {type: "metadata", data?: Record<string, ?>} | {type?: "request", body?: ?, headers?: Record<string, ?>, id?: string | number | null, method: string, path: string} | Record<string, ?>} WebsocketSessionMessage
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
38
|
/**
|
|
40
39
|
* Runs subscribe message.
|
|
41
40
|
* @param {WebsocketSessionMessage} message - Raw websocket message.
|
|
@@ -423,7 +422,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
423
422
|
sendGoodbye(client) {
|
|
424
423
|
const frame = Buffer.from([WEBSOCKET_FINAL_FRAME | WEBSOCKET_OPCODE_CLOSE, 0x00])
|
|
425
424
|
|
|
426
|
-
client.events.emit("output", frame)
|
|
425
|
+
client.events.emit("output", frame, {websocketFrame: true})
|
|
427
426
|
}
|
|
428
427
|
|
|
429
428
|
/**
|
|
@@ -967,7 +966,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
967
966
|
header[0] = WEBSOCKET_FINAL_FRAME | opcode
|
|
968
967
|
header[1] = payload.length
|
|
969
968
|
|
|
970
|
-
this.client.events.emit("output", Buffer.concat([header, payload]))
|
|
969
|
+
this.client.events.emit("output", Buffer.concat([header, payload]), {websocketFrame: true})
|
|
971
970
|
}
|
|
972
971
|
|
|
973
972
|
/**
|
|
@@ -1012,7 +1011,7 @@ export default class VelociousHttpServerClientWebsocketSession {
|
|
|
1012
1011
|
|
|
1013
1012
|
header[0] = WEBSOCKET_FINAL_FRAME | WEBSOCKET_OPCODE_TEXT
|
|
1014
1013
|
|
|
1015
|
-
this.client.events.emit("output", Buffer.concat([header, payload]))
|
|
1014
|
+
this.client.events.emit("output", Buffer.concat([header, payload]), {websocketFrame: true})
|
|
1016
1015
|
}
|
|
1017
1016
|
|
|
1018
1017
|
/**
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} DeliveryTask
|
|
3
|
+
* @property {number} byteLength - Retained complete-buffer bytes.
|
|
4
|
+
* @property {boolean} countedFrame - Whether this task is an outbound frame.
|
|
5
|
+
* @property {() => Promise<void>} delivery - Delivery operation.
|
|
6
|
+
* @property {(error?: Error) => void} settle - Settles the enqueue promise.
|
|
7
|
+
*/
|
|
8
|
+
// @ts-check
|
|
9
|
+
|
|
10
|
+
export class ClientDeliveryQueueOverflowError extends Error {
|
|
11
|
+
/**
|
|
12
|
+
* Builds an outbound queue overflow error.
|
|
13
|
+
* @param {object} args - Overflow details.
|
|
14
|
+
* @param {number} args.clientCount - Client identifier.
|
|
15
|
+
* @param {number} args.maxBytes - Configured byte high-water mark.
|
|
16
|
+
* @param {number} args.maxFrames - Configured frame high-water mark.
|
|
17
|
+
* @param {number} args.pendingBytes - Bytes retained before rejecting the frame.
|
|
18
|
+
* @param {number} args.pendingFrames - Frames retained before rejecting the frame.
|
|
19
|
+
* @param {number} args.rejectedBytes - Rejected frame size.
|
|
20
|
+
*/
|
|
21
|
+
constructor({clientCount, maxBytes, maxFrames, pendingBytes, pendingFrames, rejectedBytes}) {
|
|
22
|
+
super(`WebSocket client ${clientCount} exceeded its outbound queue limit (${pendingFrames}/${maxFrames} frames, ${pendingBytes}/${maxBytes} bytes; rejected ${rejectedBytes} bytes)`)
|
|
23
|
+
this.name = "ClientDeliveryQueueOverflowError"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default class ClientDeliveryQueue {
|
|
28
|
+
/**
|
|
29
|
+
* Builds a per-client delivery queue.
|
|
30
|
+
* @param {object} args - Queue options.
|
|
31
|
+
* @param {number} args.clientCount - Client identifier.
|
|
32
|
+
* @param {number} args.maxBytes - Byte high-water mark.
|
|
33
|
+
* @param {number} args.maxFrames - Frame high-water mark.
|
|
34
|
+
* @param {(error: ClientDeliveryQueueOverflowError) => void} args.onOverflow - Overflow handler.
|
|
35
|
+
*/
|
|
36
|
+
constructor({clientCount, maxBytes, maxFrames, onOverflow}) {
|
|
37
|
+
this.clientCount = clientCount
|
|
38
|
+
this.maxBytes = maxBytes
|
|
39
|
+
this.maxFrames = maxFrames
|
|
40
|
+
this.onOverflow = onOverflow
|
|
41
|
+
/** @type {DeliveryTask[]} */
|
|
42
|
+
this.tasks = []
|
|
43
|
+
/** @type {DeliveryTask | undefined} */
|
|
44
|
+
this.activeTask = undefined
|
|
45
|
+
this.pendingBytes = 0
|
|
46
|
+
this.pendingFrames = 0
|
|
47
|
+
this.destroyed = false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Enqueues one complete output buffer.
|
|
52
|
+
* @param {object} args - Delivery details.
|
|
53
|
+
* @param {number} args.byteLength - Exact buffer byte length.
|
|
54
|
+
* @param {() => Promise<void>} args.delivery - Delivery operation.
|
|
55
|
+
* @returns {Promise<void>} - Settles after delivery or teardown.
|
|
56
|
+
*/
|
|
57
|
+
enqueueFrame({byteLength, delivery}) {
|
|
58
|
+
if (this.destroyed) return Promise.resolve()
|
|
59
|
+
|
|
60
|
+
if (this.pendingFrames + 1 > this.maxFrames || this.pendingBytes + byteLength > this.maxBytes) {
|
|
61
|
+
const error = new ClientDeliveryQueueOverflowError({
|
|
62
|
+
clientCount: this.clientCount,
|
|
63
|
+
maxBytes: this.maxBytes,
|
|
64
|
+
maxFrames: this.maxFrames,
|
|
65
|
+
pendingBytes: this.pendingBytes,
|
|
66
|
+
pendingFrames: this.pendingFrames,
|
|
67
|
+
rejectedBytes: byteLength
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
this.onOverflow(error)
|
|
71
|
+
return Promise.reject(error)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.pendingFrames += 1
|
|
75
|
+
this.pendingBytes += byteLength
|
|
76
|
+
return this._enqueue({byteLength, countedFrame: true, delivery})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Enqueues an ordering-only operation that retains no complete output frame.
|
|
81
|
+
* @param {() => Promise<void>} delivery - Delivery operation.
|
|
82
|
+
* @returns {Promise<void>} - Settles after delivery or teardown.
|
|
83
|
+
*/
|
|
84
|
+
enqueueControl(delivery) {
|
|
85
|
+
if (this.destroyed) return Promise.resolve()
|
|
86
|
+
|
|
87
|
+
return this._enqueue({byteLength: 0, countedFrame: false, delivery})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Releases queued and active accounting during explicit client teardown.
|
|
92
|
+
* @returns {void}
|
|
93
|
+
*/
|
|
94
|
+
destroy() {
|
|
95
|
+
if (this.destroyed) return
|
|
96
|
+
|
|
97
|
+
this.destroyed = true
|
|
98
|
+
const tasks = this.activeTask ? [this.activeTask, ...this.tasks] : this.tasks
|
|
99
|
+
|
|
100
|
+
this.activeTask = undefined
|
|
101
|
+
this.tasks = []
|
|
102
|
+
this.pendingBytes = 0
|
|
103
|
+
this.pendingFrames = 0
|
|
104
|
+
|
|
105
|
+
for (const task of tasks) task.settle()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Gets current retained-buffer accounting.
|
|
110
|
+
* @returns {{pendingBytes: number, pendingFrames: number}} - Current retained-buffer accounting.
|
|
111
|
+
*/
|
|
112
|
+
snapshot() {
|
|
113
|
+
return {pendingBytes: this.pendingBytes, pendingFrames: this.pendingFrames}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Enqueues a delivery task.
|
|
118
|
+
* @param {Omit<DeliveryTask, "settle">} task - Task to enqueue.
|
|
119
|
+
* @returns {Promise<void>} - Task completion.
|
|
120
|
+
*/
|
|
121
|
+
_enqueue(task) {
|
|
122
|
+
const promise = new Promise((resolve, reject) => {
|
|
123
|
+
this.tasks.push({
|
|
124
|
+
...task,
|
|
125
|
+
settle: (error) => error ? reject(error) : resolve(undefined)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
this._drain()
|
|
130
|
+
return promise
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Starts the next task when idle.
|
|
135
|
+
* @returns {void} - No return value.
|
|
136
|
+
*/
|
|
137
|
+
_drain() {
|
|
138
|
+
if (this.destroyed || this.activeTask) return
|
|
139
|
+
|
|
140
|
+
const task = this.tasks.shift()
|
|
141
|
+
if (!task) return
|
|
142
|
+
|
|
143
|
+
this.activeTask = task
|
|
144
|
+
void task.delivery().then(
|
|
145
|
+
() => this._finish(task),
|
|
146
|
+
(error) => this._finish(task, error)
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Finishes the active delivery task.
|
|
152
|
+
* @param {DeliveryTask} task - Completed task.
|
|
153
|
+
* @param {Error} [error] - Delivery error.
|
|
154
|
+
* @returns {void}
|
|
155
|
+
*/
|
|
156
|
+
_finish(task, error) {
|
|
157
|
+
if (this.destroyed || this.activeTask !== task) return
|
|
158
|
+
|
|
159
|
+
this.activeTask = undefined
|
|
160
|
+
if (task.countedFrame) {
|
|
161
|
+
this.pendingBytes -= task.byteLength
|
|
162
|
+
this.pendingFrames -= 1
|
|
163
|
+
}
|
|
164
|
+
task.settle(error)
|
|
165
|
+
this._drain()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -76,6 +76,15 @@ export default class ServerClient {
|
|
|
76
76
|
})
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Immediately destroys the socket and all transport-owned write buffers.
|
|
81
|
+
* @param {Error} error - Destruction reason.
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*/
|
|
84
|
+
destroy(error) {
|
|
85
|
+
if (!this.socket.destroyed) this.socket.destroy(error)
|
|
86
|
+
}
|
|
87
|
+
|
|
79
88
|
/**
|
|
80
89
|
* On socket data.
|
|
81
90
|
* @param {Buffer} chunk - Chunk.
|
|
@@ -4,11 +4,6 @@ import {randomUUID} from "crypto"
|
|
|
4
4
|
import TableData from "../database/table-data/index.js"
|
|
5
5
|
import Logger from "../logger.js"
|
|
6
6
|
|
|
7
|
-
const EVENTS_TABLE = "websocket_channel_events"
|
|
8
|
-
const REPLAY_CHANNELS_TABLE = "websocket_replay_channels"
|
|
9
|
-
const DEFAULT_RETENTION_MS = 10 * 60 * 1000
|
|
10
|
-
const stores = new WeakMap()
|
|
11
|
-
|
|
12
7
|
/**
|
|
13
8
|
* WebsocketEventRow type.
|
|
14
9
|
* @typedef {object} WebsocketEventRow
|
|
@@ -18,12 +13,15 @@ const stores = new WeakMap()
|
|
|
18
13
|
* @property {string} payload_json - Serialized payload.
|
|
19
14
|
* @property {number | string} sequence - Sequence number.
|
|
20
15
|
*/
|
|
21
|
-
|
|
22
16
|
/**
|
|
23
17
|
* WebsocketReplayChannelRow type.
|
|
24
18
|
* @typedef {object} WebsocketReplayChannelRow
|
|
25
19
|
* @property {string} channel - Channel name.
|
|
26
20
|
*/
|
|
21
|
+
const EVENTS_TABLE = "websocket_channel_events"
|
|
22
|
+
const REPLAY_CHANNELS_TABLE = "websocket_replay_channels"
|
|
23
|
+
const DEFAULT_RETENTION_MS = 10 * 60 * 1000
|
|
24
|
+
const stores = new WeakMap()
|
|
27
25
|
|
|
28
26
|
/**
|
|
29
27
|
* Runs the websocketEventLogStoreForConfiguration helper.
|
|
@@ -8,6 +8,10 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
8
8
|
* Narrows the runtime value to the documented type.
|
|
9
9
|
* @type {Set<import("./worker-handler/index.js").default>} */
|
|
10
10
|
this.handlers = new Set()
|
|
11
|
+
/**
|
|
12
|
+
* Broadcast handlers grouped by the configuration that owns them.
|
|
13
|
+
* @type {Map<import("../configuration.js").default, Set<import("./worker-handler/index.js").default>>} */
|
|
14
|
+
this.broadcastHandlersByConfiguration = new Map()
|
|
11
15
|
this.publishQueue = Promise.resolve()
|
|
12
16
|
}
|
|
13
17
|
|
|
@@ -30,8 +34,23 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
30
34
|
*/
|
|
31
35
|
register(handler) {
|
|
32
36
|
this.handlers.add(handler)
|
|
37
|
+
let configurationHandlers = this.broadcastHandlersByConfiguration.get(handler.configuration)
|
|
38
|
+
|
|
39
|
+
if (!configurationHandlers) {
|
|
40
|
+
configurationHandlers = new Set()
|
|
41
|
+
this.broadcastHandlersByConfiguration.set(handler.configuration, configurationHandlers)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
configurationHandlers.add(handler)
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
this.handlers.delete(handler)
|
|
48
|
+
configurationHandlers.delete(handler)
|
|
33
49
|
|
|
34
|
-
|
|
50
|
+
if (configurationHandlers.size === 0) {
|
|
51
|
+
this.broadcastHandlersByConfiguration.delete(handler.configuration)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
35
54
|
}
|
|
36
55
|
|
|
37
56
|
/**
|
|
@@ -69,17 +88,24 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
69
88
|
* @param {string} args.channel - Channel name.
|
|
70
89
|
* @param {Record<string, ?>} args.broadcastParams - Routing filter params.
|
|
71
90
|
* @param {?} args.body - Message body.
|
|
91
|
+
* @param {import("../configuration.js").default} args.configuration - Originating configuration.
|
|
72
92
|
* @returns {void}
|
|
73
93
|
*/
|
|
74
|
-
broadcastV2({body, broadcastParams, channel}) {
|
|
94
|
+
broadcastV2({body, broadcastParams, channel, configuration}) {
|
|
75
95
|
// Chain onto publishQueue so persistence completes before
|
|
76
96
|
// the next broadcast — without this, a subscriber that connects
|
|
77
97
|
// immediately after a broadcast could miss the just-persisted
|
|
78
98
|
// event when replaying from lastEventId on a slow DB.
|
|
79
99
|
this._queuePublish(async () => {
|
|
80
|
-
const persistedEvent = await this._persistV2EventIfNeeded({body, channel})
|
|
100
|
+
const persistedEvent = await this._persistV2EventIfNeeded({body, channel, configuration})
|
|
101
|
+
const dispatchedTargets = new Set()
|
|
81
102
|
|
|
82
|
-
for (const handler of this.
|
|
103
|
+
for (const handler of this.broadcastHandlersByConfiguration.get(configuration) || []) {
|
|
104
|
+
const dispatchKey = handler.websocketV2BroadcastDispatchKey()
|
|
105
|
+
|
|
106
|
+
if (dispatchedTargets.has(dispatchKey)) continue
|
|
107
|
+
|
|
108
|
+
dispatchedTargets.add(dispatchKey)
|
|
83
109
|
handler.dispatchWebsocketV2Broadcast({
|
|
84
110
|
body,
|
|
85
111
|
broadcastParams,
|
|
@@ -88,18 +114,19 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
88
114
|
createdAt: persistedEvent?.createdAt
|
|
89
115
|
})
|
|
90
116
|
}
|
|
91
|
-
}, "Failed to persist/broadcast V2 event")
|
|
117
|
+
}, "Failed to persist/broadcast V2 event", configuration)
|
|
92
118
|
}
|
|
93
119
|
|
|
94
120
|
/**
|
|
95
121
|
* Runs queue publish.
|
|
96
122
|
* @param {() => Promise<void>} callback - Publish work to run in order.
|
|
97
123
|
* @param {string} errorMessage - Message logged when publish work fails.
|
|
124
|
+
* @param {import("../configuration.js").default} [originatingConfiguration] - Configuration whose context owns the work.
|
|
98
125
|
* @returns {void}
|
|
99
126
|
*/
|
|
100
|
-
_queuePublish(callback, errorMessage) {
|
|
127
|
+
_queuePublish(callback, errorMessage, originatingConfiguration) {
|
|
101
128
|
const handler = this.handlers.values().next().value
|
|
102
|
-
const configuration = handler?.configuration
|
|
129
|
+
const configuration = originatingConfiguration || handler?.configuration
|
|
103
130
|
|
|
104
131
|
this.publishQueue = this.publishQueue
|
|
105
132
|
.then(async () => {
|
|
@@ -120,10 +147,11 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
120
147
|
* @param {object} args - Options.
|
|
121
148
|
* @param {?} args.body - Event body.
|
|
122
149
|
* @param {string} args.channel - Channel name.
|
|
150
|
+
* @param {import("../configuration.js").default} args.configuration - Originating configuration.
|
|
123
151
|
* @returns {Promise<{createdAt: string, id: string} | null>} - Persisted event metadata when storage is enabled.
|
|
124
152
|
*/
|
|
125
|
-
async _persistV2EventIfNeeded({body, channel}) {
|
|
126
|
-
return await this._persistChannelEventIfNeeded({channel, payload: body})
|
|
153
|
+
async _persistV2EventIfNeeded({body, channel, configuration}) {
|
|
154
|
+
return await this._persistChannelEventIfNeeded({channel, payload: body, configuration})
|
|
127
155
|
}
|
|
128
156
|
|
|
129
157
|
/**
|
|
@@ -142,14 +170,16 @@ export class VelociousHttpServerWebsocketEventsHost {
|
|
|
142
170
|
* @param {object} args - Options object.
|
|
143
171
|
* @param {string} args.channel - Channel name.
|
|
144
172
|
* @param {?} args.payload - Payload data.
|
|
173
|
+
* @param {import("../configuration.js").default} [args.configuration] - Configuration owning the event store.
|
|
145
174
|
* @returns {Promise<{createdAt: string, id: string} | null>} - Persisted event metadata.
|
|
146
175
|
*/
|
|
147
|
-
async _persistChannelEventIfNeeded({channel, payload}) {
|
|
176
|
+
async _persistChannelEventIfNeeded({channel, payload, configuration}) {
|
|
148
177
|
const handler = this.handlers.values().next().value
|
|
178
|
+
const eventConfiguration = configuration || handler?.configuration
|
|
149
179
|
|
|
150
|
-
if (!
|
|
180
|
+
if (!eventConfiguration) return null
|
|
151
181
|
|
|
152
|
-
const websocketEventLogStore = websocketEventLogStoreForConfiguration(
|
|
182
|
+
const websocketEventLogStore = websocketEventLogStoreForConfiguration(eventConfiguration)
|
|
153
183
|
const shouldPersist = await websocketEventLogStore.shouldPersistChannel(channel)
|
|
154
184
|
|
|
155
185
|
if (!shouldPersist) return null
|