@zlink-systems/framework 0.30.0 → 0.30.1
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/LICENSE +150 -68
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
- package/dist/contracts/Channels/Calls.d.ts +2 -1
- package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
- package/dist/contracts/Handlers/Attributes.d.ts +5 -13
- package/dist/contracts/Handlers/Attributes.js +7 -11
- package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
- package/dist/contracts/Handlers/JsonContract.js +4 -153
- package/dist/contracts/Spots/Contracts.d.ts +2 -1
- package/dist/nest-integration.d.ts +1 -1
- package/dist/nest-integration.js +2 -1
- package/dist/runtime/actors/actor-client.d.ts +1 -1
- package/dist/runtime/actors/actor-client.js +14 -12
- package/dist/runtime/actors/actor-handoff.d.ts +1 -1
- package/dist/runtime/actors/actor-handoff.js +7 -4
- package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
- package/dist/runtime/actors/actor-local-native-join.js +9 -12
- package/dist/runtime/actors/actor-remote-wire.js +15 -0
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
- package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
- package/dist/runtime/actors/index.d.ts +2 -1
- package/dist/runtime/actors/index.js +18 -6
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
- package/dist/runtime/admission.d.ts +1 -1
- package/dist/runtime/admission.js +15 -5
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
- package/dist/runtime/application-jobs/contracts.d.ts +10 -1
- package/dist/runtime/backend/contracts/index.d.ts +18 -9
- package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
- package/dist/runtime/backend/mesh-completion-table.js +149 -49
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
- package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
- package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
- package/dist/runtime/backend/runtime-message.d.ts +1 -0
- package/dist/runtime/backend/runtime-message.js +5 -0
- package/dist/runtime/backend/runtime-values.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.js +2 -1
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +58 -21
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
- package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
- package/dist/runtime/channels/channel-dispatch-services.js +45 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
- package/dist/runtime/channels/channel-dispatchers.js +27 -26
- package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
- package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +83 -8
- package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
- package/dist/runtime/channels/channel-runtime-manager.js +12 -12
- package/dist/runtime/channels/channel-transports.d.ts +18 -15
- package/dist/runtime/channels/channel-transports.js +48 -31
- package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/local-spot-route-transport.js +2 -1
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
- package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
- package/dist/runtime/channels/source-spot-router.d.ts +2 -2
- package/dist/runtime/channels/source-spot-router.js +4 -4
- package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-node-route-transport.js +4 -4
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
- package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
- package/dist/runtime/execution/serial-execution-queue.js +1 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
- package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
- package/dist/runtime/foundation/durable-service-request.js +98 -0
- package/dist/runtime/foundation/operation-identity.d.ts +1 -0
- package/dist/runtime/foundation/operation-identity.js +5 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
- package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
- package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
- package/dist/runtime/foundation/service-topology-registry.js +61 -27
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
- package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
- package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
- package/dist/runtime/handlers/handler-instance-scope.js +54 -11
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
- package/dist/runtime/host/application-job-queue.d.ts +19 -7
- package/dist/runtime/host/application-job-queue.js +150 -42
- package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
- package/dist/runtime/host/entry-actor-runtime.js +3 -0
- package/dist/runtime/host/index.d.ts +7 -1
- package/dist/runtime/host/index.js +142 -118
- package/dist/runtime/host/remote-bound-session-relay.js +2 -18
- package/dist/runtime/host/route-mesh-runtime.js +1 -1
- package/dist/runtime/host/service-relocation-control.d.ts +1 -0
- package/dist/runtime/host/service-relocation-control.js +10 -4
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
- package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
- package/dist/runtime/host/spot-address-transport.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
- package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
- package/dist/runtime/locations/actor-location-claims.js +34 -19
- package/dist/runtime/locations/lifecycle.d.ts +1 -2
- package/dist/runtime/locations/lifecycle.js +2 -5
- package/dist/runtime/locations/runtime.d.ts +1 -1
- package/dist/runtime/locations/runtime.js +24 -23
- package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
- package/dist/runtime/messaging/framework-json-v1.js +38 -294
- package/dist/runtime/messaging/packet-name.d.ts +1 -1
- package/dist/runtime/messaging/packet-name.js +8 -24
- package/dist/runtime/messaging/request-result.d.ts +2 -0
- package/dist/runtime/messaging/request-result.js +54 -0
- package/dist/runtime/messaging/submission-result.d.ts +1 -0
- package/dist/runtime/messaging/submission-result.js +5 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
- package/dist/runtime/spots/index.d.ts +3 -0
- package/dist/runtime/spots/index.js +9 -2
- package/dist/runtime/spots/spot-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-activation.js +17 -8
- package/dist/runtime/spots/spot-entry-activation.js +6 -2
- package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
- package/dist/runtime/spots/spot-handler-registry.js +18 -8
- package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
- package/dist/runtime/spots/spot-outbound.d.ts +3 -0
- package/dist/runtime/spots/spot-outbound.js +24 -15
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
- package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
- package/dist/runtime/spots/spot-timer.js +1 -0
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
- package/dist/runtime/streams/stream-session-runtime.js +13 -27
- package/package.json +2 -2
- package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
- package/src/contracts/Channels/Calls.ts +2 -1
- package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
- package/src/contracts/Handlers/Attributes.ts +14 -21
- package/src/contracts/Handlers/JsonContract.ts +8 -216
- package/src/contracts/Spots/Contracts.ts +2 -1
- package/src/nest-integration.ts +1 -0
- package/src/runtime/actors/actor-client.ts +40 -16
- package/src/runtime/actors/actor-handoff.ts +9 -4
- package/src/runtime/actors/actor-join-relocation.ts +1 -0
- package/src/runtime/actors/actor-local-native-join.ts +17 -26
- package/src/runtime/actors/actor-remote-wire.ts +17 -0
- package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
- package/src/runtime/actors/actor-routed-json-request.ts +10 -2
- package/src/runtime/actors/index.ts +19 -5
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
- package/src/runtime/admission.ts +18 -5
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
- package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +53 -14
- package/src/runtime/backend/mesh-completion-table.ts +156 -57
- package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
- package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
- package/src/runtime/backend/raw-binding-port.ts +7 -2
- package/src/runtime/backend/runtime-message.ts +6 -0
- package/src/runtime/backend/runtime-values.ts +1 -0
- package/src/runtime/channels/channel-clients.ts +90 -41
- package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
- package/src/runtime/channels/channel-dispatch-services.ts +69 -1
- package/src/runtime/channels/channel-dispatchers.ts +29 -27
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
- package/src/runtime/channels/channel-envelope.ts +133 -8
- package/src/runtime/channels/channel-outbound-operations.ts +22 -8
- package/src/runtime/channels/channel-runtime-manager.ts +29 -12
- package/src/runtime/channels/channel-transports.ts +128 -60
- package/src/runtime/channels/local-spot-route-transport.ts +3 -1
- package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
- package/src/runtime/channels/source-spot-router.ts +8 -4
- package/src/runtime/channels/spot-node-route-transport.ts +8 -4
- package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
- package/src/runtime/execution/serial-execution-queue.ts +2 -0
- package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
- package/src/runtime/foundation/durable-service-request.ts +137 -0
- package/src/runtime/foundation/operation-identity.ts +5 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
- package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
- package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
- package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
- package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
- package/src/runtime/foundation/service-topology-registry.ts +91 -36
- package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
- package/src/runtime/handlers/handler-instance-scope.ts +67 -16
- package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
- package/src/runtime/host/application-job-queue.ts +175 -41
- package/src/runtime/host/entry-actor-runtime.ts +4 -0
- package/src/runtime/host/index.ts +201 -156
- package/src/runtime/host/remote-bound-session-relay.ts +2 -23
- package/src/runtime/host/route-mesh-runtime.ts +1 -1
- package/src/runtime/host/service-relocation-control.ts +11 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
- package/src/runtime/host/spot-address-transport.ts +4 -2
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/locations/actor-location-claims.ts +52 -30
- package/src/runtime/locations/lifecycle.ts +8 -26
- package/src/runtime/locations/runtime.ts +28 -24
- package/src/runtime/messaging/framework-json-v1.ts +5 -325
- package/src/runtime/messaging/packet-name.ts +5 -25
- package/src/runtime/messaging/request-result.ts +58 -0
- package/src/runtime/messaging/submission-result.ts +5 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
- package/src/runtime/spots/index.ts +14 -2
- package/src/runtime/spots/spot-activation.ts +28 -10
- package/src/runtime/spots/spot-entry-activation.ts +9 -2
- package/src/runtime/spots/spot-handler-registry.ts +41 -8
- package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
- package/src/runtime/spots/spot-outbound.ts +36 -16
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
- package/src/runtime/spots/spot-runtime-ports.ts +1 -0
- package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
- package/src/runtime/spots/spot-timer.ts +5 -1
- package/src/runtime/streams/stream-session-runtime.ts +12 -29
|
@@ -54,8 +54,7 @@ function encodeNodeSendHeader() {
|
|
|
54
54
|
function encodeNodeRequestHeader(correlation) {
|
|
55
55
|
return withU64(prefix(exports.M6aServiceWireCommand.nodeRequest), correlation, 'correlation');
|
|
56
56
|
}
|
|
57
|
-
function decodeNodeRequestHeader(frame) {
|
|
58
|
-
const header = decodeHeader(frame);
|
|
57
|
+
function decodeNodeRequestHeader(frame, header = decodeHeader(frame)) {
|
|
59
58
|
if (header.command !== exports.M6aServiceWireCommand.nodeRequest ||
|
|
60
59
|
header.flags !== 0 ||
|
|
61
60
|
frame.byteLength !== 13) {
|
|
@@ -66,8 +65,7 @@ function decodeNodeRequestHeader(frame) {
|
|
|
66
65
|
function encodeChannelSendHeader(channelName) {
|
|
67
66
|
return concat(prefix(exports.M6aServiceWireCommand.channelSend), encodeText8(channelName, 'channelName'));
|
|
68
67
|
}
|
|
69
|
-
function decodeChannelSendHeader(frame) {
|
|
70
|
-
const header = decodeHeader(frame);
|
|
68
|
+
function decodeChannelSendHeader(frame, header = decodeHeader(frame)) {
|
|
71
69
|
if (header.command !== exports.M6aServiceWireCommand.channelSend || header.flags !== 0) {
|
|
72
70
|
fail('Invalid channelSend header.');
|
|
73
71
|
}
|
|
@@ -79,8 +77,7 @@ function decodeChannelSendHeader(frame) {
|
|
|
79
77
|
function encodeChannelRequestHeader(correlation, channelName) {
|
|
80
78
|
return concat(withU64(prefix(exports.M6aServiceWireCommand.channelRequest), correlation, 'correlation'), encodeText8(channelName, 'channelName'));
|
|
81
79
|
}
|
|
82
|
-
function decodeChannelRequestHeader(frame) {
|
|
83
|
-
const header = decodeHeader(frame);
|
|
80
|
+
function decodeChannelRequestHeader(frame, header = decodeHeader(frame)) {
|
|
84
81
|
if (header.command !== exports.M6aServiceWireCommand.channelRequest || header.flags !== 0) {
|
|
85
82
|
fail('Invalid channelRequest header.');
|
|
86
83
|
}
|
|
@@ -127,22 +124,8 @@ function decodeReplyHeader(frame) {
|
|
|
127
124
|
return result;
|
|
128
125
|
}
|
|
129
126
|
function encodeApplicationPayload(payload) {
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
if (payload.payload.byteLength > MAX_U32)
|
|
133
|
-
fail('Application payload exceeds u32.');
|
|
134
|
-
const bodyLength = packetName.byteLength + contentType.byteLength + 4 + payload.payload.byteLength;
|
|
135
|
-
if (bodyLength > MAX_U32)
|
|
136
|
-
fail('Application payload body exceeds u32.');
|
|
137
|
-
const result = Buffer.alloc(5 + bodyLength);
|
|
138
|
-
result[0] = exports.APPLICATION_PAYLOAD_VERSION;
|
|
139
|
-
result.writeUInt32BE(bodyLength, 1);
|
|
140
|
-
let offset = 5;
|
|
141
|
-
offset += packetName.copy(result, offset);
|
|
142
|
-
offset += contentType.copy(result, offset);
|
|
143
|
-
result.writeUInt32BE(payload.payload.byteLength, offset);
|
|
144
|
-
offset += 4;
|
|
145
|
-
Buffer.from(payload.payload.buffer, payload.payload.byteOffset, payload.payload.byteLength).copy(result, offset);
|
|
127
|
+
const result = allocateApplicationPayload(payload.packetName, payload.contentType, payload.payload.byteLength);
|
|
128
|
+
result.set(payload.payload, result.byteLength - payload.payload.byteLength);
|
|
146
129
|
return result;
|
|
147
130
|
}
|
|
148
131
|
/**
|
|
@@ -155,8 +138,6 @@ function encodeMultipartApplicationPayload(parts, packetName, contentType) {
|
|
|
155
138
|
fail('Multipart payload must contain at least one part.');
|
|
156
139
|
if (parts.length > MAX_U32)
|
|
157
140
|
fail('Multipart part count exceeds u32.');
|
|
158
|
-
const packetNameBytes = encodeText8(packetName, 'packetName');
|
|
159
|
-
const contentTypeBytes = encodeText8(contentType, 'contentType');
|
|
160
141
|
let multipartLength = 4;
|
|
161
142
|
for (const part of parts) {
|
|
162
143
|
if (part.byteLength > MAX_U32)
|
|
@@ -165,27 +146,44 @@ function encodeMultipartApplicationPayload(parts, packetName, contentType) {
|
|
|
165
146
|
if (multipartLength > MAX_U32)
|
|
166
147
|
fail('Multipart payload exceeds u32.');
|
|
167
148
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
fail('Application payload body exceeds u32.');
|
|
171
|
-
const result = Buffer.alloc(5 + bodyLength);
|
|
172
|
-
result[0] = exports.APPLICATION_PAYLOAD_VERSION;
|
|
173
|
-
result.writeUInt32BE(bodyLength, 1);
|
|
174
|
-
let offset = 5;
|
|
175
|
-
offset += packetNameBytes.copy(result, offset);
|
|
176
|
-
offset += contentTypeBytes.copy(result, offset);
|
|
177
|
-
result.writeUInt32BE(multipartLength, offset);
|
|
178
|
-
offset += 4;
|
|
149
|
+
const result = allocateApplicationPayload(packetName, contentType, multipartLength);
|
|
150
|
+
let offset = result.byteLength - multipartLength;
|
|
179
151
|
result.writeUInt32BE(parts.length, offset);
|
|
180
152
|
offset += 4;
|
|
181
153
|
for (const part of parts) {
|
|
182
154
|
result.writeUInt32BE(part.byteLength, offset);
|
|
183
155
|
offset += 4;
|
|
184
|
-
|
|
156
|
+
result.set(part, offset);
|
|
185
157
|
offset += part.byteLength;
|
|
186
158
|
}
|
|
187
159
|
return result;
|
|
188
160
|
}
|
|
161
|
+
function allocateApplicationPayload(packetName, contentType, payloadLength) {
|
|
162
|
+
const packetNameBytes = (0, service_wire_binary_primitives_1.encodeCanonicalServiceWireText)(packetName, 'packetName', service_wire_binary_primitives_1.SERVICE_WIRE_TEXT8_MAX_BYTES, fail);
|
|
163
|
+
const contentTypeBytes = (0, service_wire_binary_primitives_1.encodeCanonicalServiceWireText)(contentType, 'contentType', service_wire_binary_primitives_1.SERVICE_WIRE_TEXT8_MAX_BYTES, fail);
|
|
164
|
+
if (payloadLength > MAX_U32)
|
|
165
|
+
fail('Application payload exceeds u32.');
|
|
166
|
+
const frameLength = exports.APPLICATION_PAYLOAD_MINIMUM_FIELD_BYTES +
|
|
167
|
+
packetNameBytes.byteLength +
|
|
168
|
+
contentTypeBytes.byteLength +
|
|
169
|
+
payloadLength;
|
|
170
|
+
const prefixLength = 1 + APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES;
|
|
171
|
+
const bodyLength = frameLength - prefixLength;
|
|
172
|
+
if (bodyLength > MAX_U32)
|
|
173
|
+
fail('Application payload body exceeds u32.');
|
|
174
|
+
const result = Buffer.alloc(frameLength);
|
|
175
|
+
result[0] = exports.APPLICATION_PAYLOAD_VERSION;
|
|
176
|
+
result.writeUInt32BE(bodyLength, 1);
|
|
177
|
+
let offset = prefixLength;
|
|
178
|
+
result[offset++] = packetNameBytes.byteLength;
|
|
179
|
+
result.set(packetNameBytes, offset);
|
|
180
|
+
offset += packetNameBytes.byteLength;
|
|
181
|
+
result[offset++] = contentTypeBytes.byteLength;
|
|
182
|
+
result.set(contentTypeBytes, offset);
|
|
183
|
+
offset += contentTypeBytes.byteLength;
|
|
184
|
+
result.writeUInt32BE(payloadLength, offset);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
189
187
|
function decodeApplicationPayload(frame) {
|
|
190
188
|
const decoded = decodeApplicationPayloadView(frame);
|
|
191
189
|
return {
|
|
@@ -419,7 +417,7 @@ function encodeU64(value) {
|
|
|
419
417
|
return result;
|
|
420
418
|
}
|
|
421
419
|
function encodeText8(value, field) {
|
|
422
|
-
const bytes = (0, service_wire_binary_primitives_1.encodeCanonicalServiceWireText)(value, field,
|
|
420
|
+
const bytes = (0, service_wire_binary_primitives_1.encodeCanonicalServiceWireText)(value, field, service_wire_binary_primitives_1.SERVICE_WIRE_TEXT8_MAX_BYTES, fail);
|
|
423
421
|
return concat(Buffer.of(bytes.byteLength), bytes);
|
|
424
422
|
}
|
|
425
423
|
function encodeText16(value, field) {
|
|
@@ -430,7 +428,7 @@ function tlv(id, value) {
|
|
|
430
428
|
return concat(Buffer.of(id), encodeU32(value.byteLength), value);
|
|
431
429
|
}
|
|
432
430
|
function concat(...parts) {
|
|
433
|
-
return Buffer.concat(parts
|
|
431
|
+
return Buffer.concat(parts);
|
|
434
432
|
}
|
|
435
433
|
function readNonZeroU64(bytes, offset, field) {
|
|
436
434
|
const result = bytes.readBigUInt64BE(offset);
|
|
@@ -5,9 +5,17 @@ export interface ZLinkHandlerInstanceScope {
|
|
|
5
5
|
resolve<T>(type: Type<T>): Promise<T>;
|
|
6
6
|
dispose(): Promise<void>;
|
|
7
7
|
}
|
|
8
|
+
interface ZLinkHandlerInstanceScopeFactory {
|
|
9
|
+
prepare?(type: Type): void | (() => unknown);
|
|
10
|
+
create(context?: ZLinkMessageContext): ZLinkHandlerInstanceScope;
|
|
11
|
+
}
|
|
12
|
+
export declare function registerHandlerInstanceScopeFactory(providerResolver: ZLinkProviderResolver, factory: ZLinkHandlerInstanceScopeFactory): void;
|
|
13
|
+
export declare function prepareHandlerInstance<T>(providerResolver: ZLinkProviderResolver | undefined, type: Type<T>): (() => T) | undefined;
|
|
8
14
|
export declare function runInHandlerInstanceScope<T>(providerResolver: ZLinkProviderResolver | undefined, context: ZLinkMessageContext | undefined, callback: (scope: ZLinkHandlerInstanceScope) => Promise<T>): Promise<T>;
|
|
9
15
|
export declare function resolveLifecycleHandler<T>(owner: object, type: Type<T>, providerResolver?: ZLinkProviderResolver): Promise<T>;
|
|
10
16
|
export declare function runWithLifecycleHandler<THandler, TResult>(owner: object, type: Type<THandler>, providerResolver: ZLinkProviderResolver | undefined, callback: (handler: THandler) => Promise<TResult>): Promise<TResult>;
|
|
11
17
|
export declare function disposeLifecycleHandlers(owner: object, detachedTaskRunner: ZLinkDetachedTaskRunner): Promise<void>;
|
|
12
18
|
export declare function disposeOwnedInstance(instance: unknown): Promise<void>;
|
|
19
|
+
export declare function handlerInstanceCleanup(instance: unknown): (() => unknown) | undefined;
|
|
13
20
|
export declare function disposeOwnedInstances(instances: readonly unknown[]): Promise<void>;
|
|
21
|
+
export {};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerHandlerInstanceScopeFactory = registerHandlerInstanceScopeFactory;
|
|
4
|
+
exports.prepareHandlerInstance = prepareHandlerInstance;
|
|
3
5
|
exports.runInHandlerInstanceScope = runInHandlerInstanceScope;
|
|
4
6
|
exports.resolveLifecycleHandler = resolveLifecycleHandler;
|
|
5
7
|
exports.runWithLifecycleHandler = runWithLifecycleHandler;
|
|
6
8
|
exports.disposeLifecycleHandlers = disposeLifecycleHandlers;
|
|
7
9
|
exports.disposeOwnedInstance = disposeOwnedInstance;
|
|
10
|
+
exports.handlerInstanceCleanup = handlerInstanceCleanup;
|
|
8
11
|
exports.disposeOwnedInstances = disposeOwnedInstances;
|
|
9
12
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
10
13
|
const HANDLER_SCOPE_FACTORY = Symbol.for('@zlink-systems/framework.handler-instance-scope-factory');
|
|
@@ -13,10 +16,27 @@ const activeLifecycleScope = new node_async_hooks_1.AsyncLocalStorage();
|
|
|
13
16
|
const detachedLifecycleResource = new node_async_hooks_1.AsyncResource('zlink:handler-instance-scope');
|
|
14
17
|
const dispatchScopes = new WeakMap();
|
|
15
18
|
const lifecycleScopes = new WeakMap();
|
|
19
|
+
function registerHandlerInstanceScopeFactory(providerResolver, factory) {
|
|
20
|
+
Object.defineProperty(providerResolver, HANDLER_SCOPE_FACTORY, {
|
|
21
|
+
value: factory,
|
|
22
|
+
enumerable: false
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function prepareHandlerInstance(providerResolver, type) {
|
|
26
|
+
if (providerResolver === undefined)
|
|
27
|
+
return () => new type();
|
|
28
|
+
const factory = providerResolver[HANDLER_SCOPE_FACTORY];
|
|
29
|
+
if (isHandlerInstanceScopeFactory(factory)) {
|
|
30
|
+
const activate = factory.prepare?.(type);
|
|
31
|
+
if (activate !== undefined)
|
|
32
|
+
return activate;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
16
36
|
async function runInHandlerInstanceScope(providerResolver, context, callback) {
|
|
17
37
|
const active = activeHandlerScope.getStore();
|
|
18
38
|
if (active !== undefined) {
|
|
19
|
-
return callback(active
|
|
39
|
+
return callback(active);
|
|
20
40
|
}
|
|
21
41
|
if (context !== undefined) {
|
|
22
42
|
const existing = dispatchScopes.get(context);
|
|
@@ -29,7 +49,7 @@ async function runInHandlerInstanceScope(providerResolver, context, callback) {
|
|
|
29
49
|
dispatchScopes.set(context, scope);
|
|
30
50
|
}
|
|
31
51
|
try {
|
|
32
|
-
return await activeHandlerScope.run(
|
|
52
|
+
return await activeHandlerScope.run(scope, () => callback(scope));
|
|
33
53
|
}
|
|
34
54
|
finally {
|
|
35
55
|
if (context !== undefined && dispatchScopes.get(context) === scope) {
|
|
@@ -94,14 +114,15 @@ class DefaultHandlerInstanceScope {
|
|
|
94
114
|
return existing;
|
|
95
115
|
const activation = createDeferred();
|
|
96
116
|
this.instances.set(type, activation.promise);
|
|
97
|
-
|
|
117
|
+
this.activate(type, activation);
|
|
98
118
|
return activation.promise;
|
|
99
119
|
}
|
|
100
120
|
async dispose() {
|
|
101
121
|
if (this.disposed)
|
|
102
122
|
return;
|
|
103
123
|
this.disposed = true;
|
|
104
|
-
|
|
124
|
+
if (this.owned.length !== this.instances.size)
|
|
125
|
+
await Promise.allSettled(this.instances.values());
|
|
105
126
|
try {
|
|
106
127
|
await disposeOwnedInstances(this.owned);
|
|
107
128
|
}
|
|
@@ -110,21 +131,37 @@ class DefaultHandlerInstanceScope {
|
|
|
110
131
|
this.instances.clear();
|
|
111
132
|
}
|
|
112
133
|
}
|
|
113
|
-
|
|
114
|
-
let instance;
|
|
134
|
+
activate(type, activation) {
|
|
115
135
|
try {
|
|
116
136
|
const created = this.providerResolver?.create?.(type);
|
|
117
|
-
|
|
137
|
+
if (created === undefined) {
|
|
138
|
+
this.completeActivation(new type(), activation);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
void this.activatePending(created, activation);
|
|
142
|
+
}
|
|
118
143
|
}
|
|
119
144
|
catch (error) {
|
|
120
145
|
activation.reject(error);
|
|
121
|
-
return;
|
|
122
146
|
}
|
|
147
|
+
}
|
|
148
|
+
async activatePending(created, activation) {
|
|
149
|
+
try {
|
|
150
|
+
this.completeActivation(await created, activation);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
activation.reject(error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
completeActivation(instance, activation) {
|
|
123
157
|
if (!this.disposed) {
|
|
124
158
|
this.owned.push(instance);
|
|
125
159
|
activation.resolve(instance);
|
|
126
160
|
return;
|
|
127
161
|
}
|
|
162
|
+
void this.disposeLateActivation(instance, activation);
|
|
163
|
+
}
|
|
164
|
+
async disposeLateActivation(instance, activation) {
|
|
128
165
|
try {
|
|
129
166
|
await disposeOwnedInstance(instance);
|
|
130
167
|
activation.reject(new Error('Handler instance scope was disposed during activation.'));
|
|
@@ -240,18 +277,24 @@ function startOutsideLifecycleInvocation(work) {
|
|
|
240
277
|
return detachedLifecycleResource.runInAsyncScope(work);
|
|
241
278
|
}
|
|
242
279
|
async function disposeOwnedInstance(instance) {
|
|
280
|
+
const cleanup = handlerInstanceCleanup(instance);
|
|
281
|
+
if (cleanup !== undefined)
|
|
282
|
+
await cleanup.call(instance);
|
|
283
|
+
}
|
|
284
|
+
function handlerInstanceCleanup(instance) {
|
|
243
285
|
if (instance === null || instance === undefined)
|
|
244
286
|
return;
|
|
245
287
|
const value = instance;
|
|
246
288
|
if (typeof value.dispose === 'function') {
|
|
247
|
-
|
|
289
|
+
return value.dispose;
|
|
248
290
|
}
|
|
249
291
|
else if (typeof value.close === 'function') {
|
|
250
|
-
|
|
292
|
+
return value.close;
|
|
251
293
|
}
|
|
252
294
|
else if (typeof value.onModuleDestroy === 'function') {
|
|
253
|
-
|
|
295
|
+
return value.onModuleDestroy;
|
|
254
296
|
}
|
|
297
|
+
return undefined;
|
|
255
298
|
}
|
|
256
299
|
async function disposeOwnedInstances(instances) {
|
|
257
300
|
const failures = [];
|
|
@@ -149,9 +149,9 @@ class ZLinkActorRuntimeOptionsFactory {
|
|
|
149
149
|
staleActorRefReporter: (_meshName, actorId) => this.options.actorHandoff.recordStaleFailure(actorId),
|
|
150
150
|
staleActorRefPredicate: (meshName, actor) => this.actorBelongsToMesh(meshName, actor.actorId) &&
|
|
151
151
|
this.options.actorHandoff.isKnownStale(actor),
|
|
152
|
-
handoffCapture: (meshName, actorId, parts, returnResponse, actor, deadlineUnixMs) => this.actorBelongsToMesh(meshName, actorId) &&
|
|
152
|
+
handoffCapture: (meshName, actorId, parts, returnResponse, actor, deadlineUnixMs, onAdmitted) => this.actorBelongsToMesh(meshName, actorId) &&
|
|
153
153
|
!this.options.actorHandoff.isProvisional(actorId)
|
|
154
|
-
? this.options.actorHandoff.capture('local', actorId, parts, returnResponse, undefined, actor, deadlineUnixMs)
|
|
154
|
+
? this.options.actorHandoff.capture('local', actorId, parts, returnResponse, undefined, actor, deadlineUnixMs, undefined, undefined, onAdmitted)
|
|
155
155
|
: undefined,
|
|
156
156
|
sendErrorReporter: this.options.reportPostCommitError
|
|
157
157
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApplicationJobOrigin, ApplicationJobPermitPort, ApplicationJobQueuePort } from '../application-jobs/contracts';
|
|
1
|
+
import type { ApplicationJobOrigin, ApplicationJobPermitPort, ApplicationJobReceiveRotationPort, ApplicationJobQueuePort } from '../application-jobs/contracts';
|
|
2
2
|
export type ApplicationJobQueueProfileValue = 'compact' | 'low_latency' | 'balanced' | 'throughput';
|
|
3
3
|
export interface ApplicationJobQueueOptions {
|
|
4
4
|
readonly profile?: ApplicationJobQueueProfileValue;
|
|
@@ -40,12 +40,17 @@ export declare function resolveApplicationJobQueueConfiguration(options?: Applic
|
|
|
40
40
|
export declare class ApplicationJobQueuePermit implements ApplicationJobPermitPort {
|
|
41
41
|
private readonly owner;
|
|
42
42
|
readonly origin: ApplicationJobOrigin;
|
|
43
|
+
private readonly reusable;
|
|
44
|
+
detachedForHandlerTurn: boolean;
|
|
43
45
|
private state;
|
|
44
|
-
constructor(owner: ApplicationJobQueue, origin: ApplicationJobOrigin);
|
|
46
|
+
constructor(owner: ApplicationJobQueue, origin: ApplicationJobOrigin, reusable?: boolean);
|
|
47
|
+
reserveStorage(): boolean;
|
|
48
|
+
releaseStorage(): void;
|
|
49
|
+
detachForHandlerTurn(): void;
|
|
45
50
|
markApplicationQueued(): void;
|
|
46
51
|
releaseBeforeHandler(): void;
|
|
47
52
|
releaseAfterInternalProcessing(): void;
|
|
48
|
-
|
|
53
|
+
takeReleaseState(): 'reserved' | 'queued' | undefined;
|
|
49
54
|
}
|
|
50
55
|
/**
|
|
51
56
|
* Host-instance owner of the ordinary-ingress queue permit lifecycle.
|
|
@@ -59,9 +64,10 @@ export declare class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
59
64
|
private readonly loggerFailureReporter?;
|
|
60
65
|
private localWaiters;
|
|
61
66
|
private localBacklogLogged;
|
|
62
|
-
private
|
|
63
|
-
private
|
|
64
|
-
private
|
|
67
|
+
private readonly permitCounts;
|
|
68
|
+
private readonly limitCount;
|
|
69
|
+
private readonly pauseCount;
|
|
70
|
+
private readonly resumeCount;
|
|
65
71
|
private capacityWaitCount;
|
|
66
72
|
private capacityWaitDurationSeconds;
|
|
67
73
|
private metricsEpoch;
|
|
@@ -79,6 +85,9 @@ export declare class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
79
85
|
private readonly receiveFlowController;
|
|
80
86
|
constructor(configuration: ApplicationJobQueueConfiguration, nowMs?: () => number, handlerStartGate?: (() => boolean) | undefined, loggerFailureReporter?: ((error: unknown) => void) | undefined);
|
|
81
87
|
shouldHoldPermitBeforeHandler(): boolean;
|
|
88
|
+
createReceiveRotation(capacity: number, origin: ApplicationJobOrigin): ApplicationJobReceiveRotationPort;
|
|
89
|
+
receiveRotationCapacity(capacity: number): number;
|
|
90
|
+
reserveReceiveRotation(count: number): void;
|
|
82
91
|
registerReceiveFlowTarget(identity: object, applyState: (state: ApplicationJobQueuePressureState) => void, failureSink?: (error: unknown) => void): boolean;
|
|
83
92
|
unregisterReceiveFlowTarget(identity: object): void;
|
|
84
93
|
acquire(signal: AbortSignal | undefined, origin: ApplicationJobOrigin): Promise<ApplicationJobQueuePermit>;
|
|
@@ -90,9 +99,12 @@ export declare class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
90
99
|
onPressureStateChange(listener: (state: ApplicationJobQueuePressureState, sequence: bigint) => void): () => void;
|
|
91
100
|
recordFlowStateConfigFailure(): void;
|
|
92
101
|
markQueued(): void;
|
|
93
|
-
|
|
102
|
+
releasePermit(permit: ApplicationJobQueuePermit): void;
|
|
103
|
+
releaseUnusedReceiveRotation(grants: readonly (ApplicationJobQueuePermit | undefined)[], consumed: number, granted: number): void;
|
|
104
|
+
release(state: 'reserved' | 'queued', count?: number): void;
|
|
94
105
|
private limit;
|
|
95
106
|
private permitsInUse;
|
|
107
|
+
private reserveSupply;
|
|
96
108
|
private reserve;
|
|
97
109
|
private drainWaiters;
|
|
98
110
|
private cancel;
|
|
@@ -53,10 +53,31 @@ function resolveApplicationJobQueueConfiguration(options = {}, effectiveProcesso
|
|
|
53
53
|
class ApplicationJobQueuePermit {
|
|
54
54
|
owner;
|
|
55
55
|
origin;
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
reusable;
|
|
57
|
+
detachedForHandlerTurn = false;
|
|
58
|
+
state;
|
|
59
|
+
constructor(owner, origin, reusable = false) {
|
|
58
60
|
this.owner = owner;
|
|
59
61
|
this.origin = origin;
|
|
62
|
+
this.reusable = reusable;
|
|
63
|
+
this.state = reusable ? 'idle' : 'reserved';
|
|
64
|
+
}
|
|
65
|
+
reserveStorage() {
|
|
66
|
+
if (this.state !== 'idle')
|
|
67
|
+
return false;
|
|
68
|
+
this.state = 'reserved';
|
|
69
|
+
this.detachedForHandlerTurn = false;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
releaseStorage() {
|
|
73
|
+
if (!this.reusable || this.state === 'idle')
|
|
74
|
+
return;
|
|
75
|
+
if (this.state !== 'released')
|
|
76
|
+
throw new Error('Reservation storage still owns queue capacity.');
|
|
77
|
+
this.state = 'idle';
|
|
78
|
+
}
|
|
79
|
+
detachForHandlerTurn() {
|
|
80
|
+
this.detachedForHandlerTurn = true;
|
|
60
81
|
}
|
|
61
82
|
markApplicationQueued() {
|
|
62
83
|
if (this.state !== 'reserved') {
|
|
@@ -68,19 +89,75 @@ class ApplicationJobQueuePermit {
|
|
|
68
89
|
releaseBeforeHandler() {
|
|
69
90
|
if (this.owner.shouldHoldPermitBeforeHandler())
|
|
70
91
|
return;
|
|
71
|
-
this.
|
|
92
|
+
this.owner.releasePermit(this);
|
|
72
93
|
}
|
|
73
94
|
releaseAfterInternalProcessing() {
|
|
74
|
-
this.
|
|
95
|
+
this.owner.releasePermit(this);
|
|
75
96
|
}
|
|
76
|
-
|
|
77
|
-
if (this.state === 'released')
|
|
78
|
-
return;
|
|
79
|
-
this.
|
|
97
|
+
takeReleaseState() {
|
|
98
|
+
if (this.state === 'released' || this.state === 'idle')
|
|
99
|
+
return undefined;
|
|
100
|
+
const state = this.state;
|
|
80
101
|
this.state = 'released';
|
|
102
|
+
return state;
|
|
81
103
|
}
|
|
82
104
|
}
|
|
83
105
|
exports.ApplicationJobQueuePermit = ApplicationJobQueuePermit;
|
|
106
|
+
/** Connection-owned storage; queue accounting remains with the host queue. */
|
|
107
|
+
class ApplicationJobReceiveRotation {
|
|
108
|
+
owner;
|
|
109
|
+
capacity;
|
|
110
|
+
origin;
|
|
111
|
+
storage = [];
|
|
112
|
+
grants;
|
|
113
|
+
granted = 0;
|
|
114
|
+
consumed = 0;
|
|
115
|
+
constructor(owner, capacity, origin) {
|
|
116
|
+
this.owner = owner;
|
|
117
|
+
this.capacity = capacity;
|
|
118
|
+
this.origin = origin;
|
|
119
|
+
this.grants = new Array(capacity);
|
|
120
|
+
this.prepareStorage();
|
|
121
|
+
}
|
|
122
|
+
prepareStorage() {
|
|
123
|
+
for (let index = 0; index < this.capacity; index++)
|
|
124
|
+
this.storage.push(new ApplicationJobQueuePermit(this.owner, this.origin, true));
|
|
125
|
+
}
|
|
126
|
+
reserve() {
|
|
127
|
+
this.releaseUnused();
|
|
128
|
+
const count = this.owner.receiveRotationCapacity(this.capacity);
|
|
129
|
+
if (count === 0)
|
|
130
|
+
return;
|
|
131
|
+
for (let index = 0; index < this.storage.length; index++) {
|
|
132
|
+
const permit = this.storage[index];
|
|
133
|
+
if (permit.reserveStorage())
|
|
134
|
+
this.grants[this.granted++] = permit;
|
|
135
|
+
if (this.granted === count)
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
if (this.granted < count) {
|
|
139
|
+
const start = this.storage.length;
|
|
140
|
+
this.prepareStorage();
|
|
141
|
+
for (let index = start; this.granted < count; index++) {
|
|
142
|
+
const permit = this.storage[index];
|
|
143
|
+
permit.reserveStorage();
|
|
144
|
+
this.grants[this.granted++] = permit;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.owner.reserveReceiveRotation(count);
|
|
148
|
+
}
|
|
149
|
+
take() {
|
|
150
|
+
if (this.consumed === this.granted)
|
|
151
|
+
return undefined;
|
|
152
|
+
return this.grants[this.consumed++];
|
|
153
|
+
}
|
|
154
|
+
releaseUnused() {
|
|
155
|
+
this.owner.releaseUnusedReceiveRotation(this.grants, this.consumed, this.granted);
|
|
156
|
+
// Keep the prepared grant slots and reset only the logical count.
|
|
157
|
+
this.granted = 0;
|
|
158
|
+
this.consumed = 0;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
84
161
|
/**
|
|
85
162
|
* Host-instance owner of the ordinary-ingress queue permit lifecycle.
|
|
86
163
|
* It reserves capacity before receive/claim and transfers released capacity
|
|
@@ -93,9 +170,11 @@ class ApplicationJobQueue {
|
|
|
93
170
|
loggerFailureReporter;
|
|
94
171
|
localWaiters = 0;
|
|
95
172
|
localBacklogLogged = false;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
173
|
+
// The contract bounds capacity by INT32_MAX; public snapshots remain bigint.
|
|
174
|
+
permitCounts = new Uint32Array(3 /* QueuePermitCount.Size */);
|
|
175
|
+
limitCount;
|
|
176
|
+
pauseCount;
|
|
177
|
+
resumeCount;
|
|
99
178
|
capacityWaitCount = 0n;
|
|
100
179
|
capacityWaitDurationSeconds = 0;
|
|
101
180
|
metricsEpoch = 0n;
|
|
@@ -116,11 +195,27 @@ class ApplicationJobQueue {
|
|
|
116
195
|
this.nowMs = nowMs;
|
|
117
196
|
this.handlerStartGate = handlerStartGate;
|
|
118
197
|
this.loggerFailureReporter = loggerFailureReporter;
|
|
198
|
+
this.limitCount = Number(configuration.effectiveMaxQueuedApplicationJobs);
|
|
199
|
+
this.pauseCount = Number(configuration.pausePermitCount);
|
|
200
|
+
this.resumeCount = Number(configuration.resumePermitCount);
|
|
119
201
|
this.receiveFlowController = new receive_flow_controller_1.ApplicationJobReceiveFlowController(this, (state) => state);
|
|
120
202
|
}
|
|
121
203
|
shouldHoldPermitBeforeHandler() {
|
|
122
204
|
return this.handlerStartGate?.() === true;
|
|
123
205
|
}
|
|
206
|
+
createReceiveRotation(capacity, origin) {
|
|
207
|
+
if (!Number.isSafeInteger(capacity) || capacity < 1)
|
|
208
|
+
throw new RangeError('Receive capacity must be positive.');
|
|
209
|
+
return new ApplicationJobReceiveRotation(this, capacity, origin);
|
|
210
|
+
}
|
|
211
|
+
receiveRotationCapacity(capacity) {
|
|
212
|
+
if (this.waiters.length !== 0)
|
|
213
|
+
return 0;
|
|
214
|
+
return Math.min(capacity, this.limitCount - this.permitsInUse());
|
|
215
|
+
}
|
|
216
|
+
reserveReceiveRotation(count) {
|
|
217
|
+
this.reserveSupply(count);
|
|
218
|
+
}
|
|
124
219
|
registerReceiveFlowTarget(identity, applyState, failureSink) {
|
|
125
220
|
this.unregisterReceiveFlowTarget(identity);
|
|
126
221
|
const target = {
|
|
@@ -173,7 +268,7 @@ class ApplicationJobQueue {
|
|
|
173
268
|
reject(abortReason(signal));
|
|
174
269
|
return undefined;
|
|
175
270
|
}
|
|
176
|
-
if (this.waiters.length === 0 && this.permitsInUse() < this.
|
|
271
|
+
if (this.waiters.length === 0 && this.permitsInUse() < this.limitCount) {
|
|
177
272
|
return this.reserve(origin);
|
|
178
273
|
}
|
|
179
274
|
new Promise((resolve, reject) => {
|
|
@@ -204,10 +299,10 @@ class ApplicationJobQueue {
|
|
|
204
299
|
const now = this.nowMs();
|
|
205
300
|
return Object.freeze({
|
|
206
301
|
...this.configuration,
|
|
207
|
-
reservedSupplyPermits: this.
|
|
208
|
-
queuedApplicationJobs: this.
|
|
209
|
-
permitsInUse,
|
|
210
|
-
peakPermitsInUse: this.
|
|
302
|
+
reservedSupplyPermits: BigInt(this.permitCounts[0 /* QueuePermitCount.Reserved */]),
|
|
303
|
+
queuedApplicationJobs: BigInt(this.permitCounts[1 /* QueuePermitCount.Queued */]),
|
|
304
|
+
permitsInUse: BigInt(permitsInUse),
|
|
305
|
+
peakPermitsInUse: BigInt(this.permitCounts[2 /* QueuePermitCount.Peak */]),
|
|
211
306
|
capacityWaiters: BigInt(this.waiters.length),
|
|
212
307
|
capacityWaitCount: this.capacityWaitCount,
|
|
213
308
|
capacityWaitDurationSeconds: this.capacityWaitDurationSeconds,
|
|
@@ -221,7 +316,7 @@ class ApplicationJobQueue {
|
|
|
221
316
|
}
|
|
222
317
|
resetMetrics() {
|
|
223
318
|
this.metricsEpoch += 1n;
|
|
224
|
-
this.
|
|
319
|
+
this.permitCounts[2 /* QueuePermitCount.Peak */] = this.permitsInUse();
|
|
225
320
|
this.capacityWaitCount = 0n;
|
|
226
321
|
this.capacityWaitDurationSeconds = 0;
|
|
227
322
|
this.runningTransitionCount = 0n;
|
|
@@ -248,25 +343,37 @@ class ApplicationJobQueue {
|
|
|
248
343
|
this.flowStateConfigFailureCount += 1n;
|
|
249
344
|
}
|
|
250
345
|
markQueued() {
|
|
251
|
-
if (this.
|
|
346
|
+
if (this.permitCounts[0 /* QueuePermitCount.Reserved */] === 0) {
|
|
252
347
|
throw new Error('Application job queue has no reserved supply permit.');
|
|
253
348
|
}
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
349
|
+
this.permitCounts[0 /* QueuePermitCount.Reserved */] =
|
|
350
|
+
this.permitCounts[0 /* QueuePermitCount.Reserved */] - 1;
|
|
351
|
+
this.permitCounts[1 /* QueuePermitCount.Queued */] = this.permitCounts[1 /* QueuePermitCount.Queued */] + 1;
|
|
352
|
+
}
|
|
353
|
+
releasePermit(permit) {
|
|
354
|
+
const state = permit.takeReleaseState();
|
|
355
|
+
if (state !== undefined)
|
|
356
|
+
this.release(state);
|
|
357
|
+
}
|
|
358
|
+
releaseUnusedReceiveRotation(grants, consumed, granted) {
|
|
359
|
+
const count = granted - consumed;
|
|
360
|
+
if (count === 0)
|
|
361
|
+
return;
|
|
362
|
+
// Unconsumed grants still belong to this receive round; no record has acquired them.
|
|
363
|
+
for (let index = consumed; index < granted; index++) {
|
|
364
|
+
const permit = grants[index];
|
|
365
|
+
permit.takeReleaseState();
|
|
366
|
+
permit.releaseStorage();
|
|
263
367
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
368
|
+
this.release('reserved', count);
|
|
369
|
+
}
|
|
370
|
+
release(state, count = 1) {
|
|
371
|
+
const index = state === 'reserved' ? 0 /* QueuePermitCount.Reserved */ : 1 /* QueuePermitCount.Queued */;
|
|
372
|
+
const available = this.permitCounts[index];
|
|
373
|
+
if (available < count) {
|
|
374
|
+
throw new Error(`Application job queue ${state} permit accounting underflow.`);
|
|
269
375
|
}
|
|
376
|
+
this.permitCounts[index] = available - count;
|
|
270
377
|
this.drainWaiters();
|
|
271
378
|
this.evaluatePressure();
|
|
272
379
|
}
|
|
@@ -274,19 +381,21 @@ class ApplicationJobQueue {
|
|
|
274
381
|
return this.configuration.effectiveMaxQueuedApplicationJobs;
|
|
275
382
|
}
|
|
276
383
|
permitsInUse() {
|
|
277
|
-
return this.
|
|
384
|
+
return (this.permitCounts[0 /* QueuePermitCount.Reserved */] + this.permitCounts[1 /* QueuePermitCount.Queued */]);
|
|
278
385
|
}
|
|
279
|
-
|
|
280
|
-
this.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.peakPermitsInUse = current;
|
|
386
|
+
reserveSupply(count, evaluatePressure = true) {
|
|
387
|
+
this.permitCounts[0 /* QueuePermitCount.Reserved */] =
|
|
388
|
+
this.permitCounts[0 /* QueuePermitCount.Reserved */] + count;
|
|
389
|
+
this.permitCounts[2 /* QueuePermitCount.Peak */] = Math.max(this.permitCounts[2 /* QueuePermitCount.Peak */], this.permitsInUse());
|
|
284
390
|
if (evaluatePressure)
|
|
285
391
|
this.evaluatePressure();
|
|
392
|
+
}
|
|
393
|
+
reserve(origin, evaluatePressure = true) {
|
|
394
|
+
this.reserveSupply(1, evaluatePressure);
|
|
286
395
|
return new ApplicationJobQueuePermit(this, origin);
|
|
287
396
|
}
|
|
288
397
|
drainWaiters() {
|
|
289
|
-
while (this.waiters.length > 0 && this.permitsInUse() < this.
|
|
398
|
+
while (this.waiters.length > 0 && this.permitsInUse() < this.limitCount) {
|
|
290
399
|
const waiter = this.waiters.shift();
|
|
291
400
|
if (!waiter.active)
|
|
292
401
|
continue;
|
|
@@ -348,12 +457,11 @@ class ApplicationJobQueue {
|
|
|
348
457
|
}
|
|
349
458
|
}
|
|
350
459
|
evaluatePressure() {
|
|
351
|
-
const permitsInUse = this.permitsInUse();
|
|
352
460
|
const next = this.pressureStateValue === 'running'
|
|
353
|
-
? permitsInUse >= this.
|
|
461
|
+
? this.permitsInUse() >= this.pauseCount
|
|
354
462
|
? 'paused'
|
|
355
463
|
: 'running'
|
|
356
|
-
: permitsInUse <= this.
|
|
464
|
+
: this.permitsInUse() <= this.resumeCount
|
|
357
465
|
? 'running'
|
|
358
466
|
: 'paused';
|
|
359
467
|
if (next === this.pressureStateValue)
|
|
@@ -20,6 +20,7 @@ export declare class ZLinkEntryActorRuntimeService implements ZLinkEntryActorRun
|
|
|
20
20
|
private readonly binder;
|
|
21
21
|
constructor(options: ZLinkEntryActorRuntimeOptions);
|
|
22
22
|
resolveActor(actorId: string): ZLinkActor | undefined;
|
|
23
|
+
releaseMembers(meshName: string): Promise<void>;
|
|
23
24
|
commitActorTransaction(actor: ZLinkActor, onJoined: () => Promise<void>): Promise<void>;
|
|
24
25
|
destroyActor(node: ZLinkBackendSpotNode, entryNodeRid: ActorRef['nodeRid'], actor: ZLinkActor, signal?: AbortSignal): Promise<void>;
|
|
25
26
|
routePacket(actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef): Promise<{
|