@zlink-systems/framework 0.11.0 → 0.13.0
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/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Configuration/EndpointNotation.d.ts +5 -4
- package/dist/contracts/Configuration/EndpointNotation.js +5 -4
- package/dist/contracts/Configuration/InternalDefaults.d.ts +0 -1
- package/dist/contracts/Configuration/InternalDefaults.js +1 -2
- package/dist/contracts/Configuration/RegistrationNormalizers.js +1 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +2 -5
- package/dist/contracts/Configuration/RegistrationValidators.js +0 -1
- package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +6 -7
- package/dist/contracts/Errors/ZLinkFrameworkException.js +6 -7
- package/dist/runtime/actors/actor-client.js +1 -1
- package/dist/runtime/actors/actor-mailbox.js +1 -5
- package/dist/runtime/backend/contracts/index.d.ts +2 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +1 -3
- package/dist/runtime/backend/mesh-completion-table.js +11 -15
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +11 -4
- package/dist/runtime/backend/mesh-dispatch-pump.js +201 -134
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +3 -4
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +51 -37
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +2 -2
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +2 -2
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +16 -0
- package/dist/runtime/backend/node/node-event-loop-poller.js +49 -0
- package/dist/runtime/backend/node/node-raw-binding-port.js +24 -41
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +8 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +100 -107
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +3 -2
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +18 -67
- package/dist/runtime/backend/raw-binding-port.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.d.ts +5 -1
- package/dist/runtime/channels/channel-dispatchers.js +2 -2
- package/dist/runtime/channels/channel-envelope.js +324 -121
- package/dist/runtime/channels/channel-multipart.d.ts +8 -1
- package/dist/runtime/channels/channel-outbound-operations.js +0 -2
- package/dist/runtime/channels/channel-receive-loops.d.ts +1 -3
- package/dist/runtime/channels/channel-receive-loops.js +25 -65
- package/dist/runtime/channels/channel-socket-registry.js +3 -1
- package/dist/runtime/channels/channel-transports.d.ts +2 -1
- package/dist/runtime/channels/channel-transports.js +12 -10
- package/dist/runtime/execution/serial-execution-queue.d.ts +5 -18
- package/dist/runtime/execution/serial-execution-queue.js +16 -80
- package/dist/runtime/foundation/event-loop-resources.d.ts +0 -3
- package/dist/runtime/foundation/event-loop-resources.js +2 -11
- package/dist/runtime/foundation/operation-registry.d.ts +2 -8
- package/dist/runtime/foundation/operation-registry.js +3 -21
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +19 -7
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +56 -10
- package/dist/runtime/foundation/service-mailbox.d.ts +1 -7
- package/dist/runtime/foundation/service-mailbox.js +3 -2
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +1 -1
- package/dist/runtime/foundation/service-stateful-registry.js +2 -2
- package/dist/runtime/foundation/service-stateful-runtime.js +14 -14
- package/dist/runtime/framework-errors-internal.d.ts +4 -4
- package/dist/runtime/framework-errors-internal.js +8 -10
- package/dist/runtime/host/actor-placement-coordinator.js +1 -1
- package/dist/runtime/host/index.js +1 -1
- package/dist/runtime/host/service-relocation-host-runtime.js +0 -4
- package/dist/runtime/host/spot-address-transport.js +1 -1
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +0 -12
- package/dist/runtime/spots/spot-node-runtime-manager.js +6 -166
- package/dist/runtime/spots/spot-serial-turn-executor.js +1 -4
- package/dist/runtime/spots/spot-timer.d.ts +3 -0
- package/dist/runtime/spots/spot-timer.js +87 -18
- package/dist/runtime/streams/session-serial-executor.js +1 -3
- package/dist/runtime/streams/stream-session-runtime.d.ts +2 -2
- package/dist/runtime/streams/stream-session-runtime.js +13 -19
- package/dist/runtime/workers/index.d.ts +0 -1
- package/dist/runtime/workers/index.js +1 -9
- package/package.json +3 -3
- package/src/contracts/Configuration/EndpointNotation.ts +5 -4
- package/src/contracts/Configuration/InternalDefaults.ts +0 -1
- package/src/contracts/Configuration/RegistrationNormalizers.ts +2 -4
- package/src/contracts/Configuration/RegistrationTypes.ts +2 -5
- package/src/contracts/Configuration/RegistrationValidators.ts +0 -1
- package/src/contracts/Errors/ZLinkFrameworkException.ts +6 -7
- package/src/runtime/actors/actor-client.ts +1 -1
- package/src/runtime/actors/actor-mailbox.ts +1 -12
- package/src/runtime/backend/contracts/index.ts +2 -0
- package/src/runtime/backend/mesh-completion-table.ts +12 -23
- package/src/runtime/backend/mesh-dispatch-pump.ts +206 -138
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +66 -35
- package/src/runtime/backend/node/node-backend-adapter-support.ts +4 -4
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +2 -2
- package/src/runtime/backend/node/node-event-loop-poller.ts +55 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +30 -45
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +97 -110
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +23 -69
- package/src/runtime/backend/raw-binding-port.ts +1 -0
- package/src/runtime/backend/runtime-values.ts +7 -1
- package/src/runtime/channels/channel-dispatchers.ts +2 -2
- package/src/runtime/channels/channel-envelope.ts +379 -109
- package/src/runtime/channels/channel-multipart.ts +9 -1
- package/src/runtime/channels/channel-outbound-operations.ts +0 -1
- package/src/runtime/channels/channel-receive-loops.ts +24 -75
- package/src/runtime/channels/channel-socket-registry.ts +4 -1
- package/src/runtime/channels/channel-transports.ts +20 -10
- package/src/runtime/execution/serial-execution-queue.ts +16 -108
- package/src/runtime/foundation/event-loop-resources.ts +2 -11
- package/src/runtime/foundation/operation-registry.ts +2 -22
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +74 -19
- package/src/runtime/foundation/service-mailbox.ts +3 -13
- package/src/runtime/foundation/service-runtime-contracts.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +2 -2
- package/src/runtime/foundation/service-stateful-runtime.ts +14 -14
- package/src/runtime/framework-errors-internal.ts +8 -10
- package/src/runtime/host/actor-placement-coordinator.ts +1 -1
- package/src/runtime/host/index.ts +2 -1
- package/src/runtime/host/service-relocation-host-runtime.ts +0 -4
- package/src/runtime/host/spot-address-transport.ts +1 -1
- package/src/runtime/host/user-spot-creation-coordinator.ts +1 -1
- package/src/runtime/spots/spot-node-runtime-manager.ts +13 -233
- package/src/runtime/spots/spot-serial-turn-executor.ts +1 -8
- package/src/runtime/spots/spot-timer.ts +109 -18
- package/src/runtime/streams/session-serial-executor.ts +1 -7
- package/src/runtime/streams/stream-session-runtime.ts +13 -17
- package/src/runtime/workers/index.ts +2 -17
|
@@ -40,22 +40,7 @@ function encodeChannelEnvelopeParts(kind, channelName, packetName, payload, time
|
|
|
40
40
|
const encoded = encodePayload(payload, (0, channel_framework_packets_1.codecsForFrameworkPacket)(messageName, codecs), messageName, 'payload');
|
|
41
41
|
const flow = createFlow ? (0, flow_context_1.currentOrCreateFlow)('Application') : undefined;
|
|
42
42
|
const envelopeCorrelationId = correlationIdForOutboundKind(kind, correlationId);
|
|
43
|
-
|
|
44
|
-
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
45
|
-
kind,
|
|
46
|
-
channelName,
|
|
47
|
-
messageName,
|
|
48
|
-
contentType: encoded.contentType,
|
|
49
|
-
correlationId: envelopeCorrelationId,
|
|
50
|
-
deadline: timeoutMs === undefined ? null : new Date(Date.now() + timeoutMs).toISOString(),
|
|
51
|
-
topic: topic ?? null,
|
|
52
|
-
errorCode: null,
|
|
53
|
-
errorMessage: null,
|
|
54
|
-
metadata: applicationMetadataRecord(metadata),
|
|
55
|
-
flowId: flow?.flowId,
|
|
56
|
-
flowOrigin: flow?.flowOrigin
|
|
57
|
-
};
|
|
58
|
-
return [encodeChannelHeader(header), encoded.message];
|
|
43
|
+
return [encodeChannelHeader(kind, channelName, messageName, encoded.contentType, envelopeCorrelationId, timeoutMs === undefined ? null : new Date(Date.now() + timeoutMs).toISOString(), topic ?? null, null, null, undefined, applicationMetadataRecord(metadata), flow?.flowId, flow?.flowOrigin), encoded.message];
|
|
59
44
|
}
|
|
60
45
|
/**
|
|
61
46
|
* Encodes an outbound channel envelope with a deadline that was established
|
|
@@ -71,60 +56,17 @@ function encodeChannelEnvelopePartsAtDeadline(kind, channelName, packetName, pay
|
|
|
71
56
|
const encoded = encodePayload(payload, (0, channel_framework_packets_1.codecsForFrameworkPacket)(messageName, codecs), messageName, 'payload');
|
|
72
57
|
const flow = createFlow ? (0, flow_context_1.currentOrCreateFlow)('Application') : undefined;
|
|
73
58
|
const envelopeCorrelationId = correlationIdForOutboundKind(kind, correlationId);
|
|
74
|
-
|
|
75
|
-
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
76
|
-
kind,
|
|
77
|
-
channelName,
|
|
78
|
-
messageName,
|
|
79
|
-
contentType: encoded.contentType,
|
|
80
|
-
correlationId: envelopeCorrelationId,
|
|
81
|
-
deadline: new Date(deadlineUnixMs).toISOString(),
|
|
82
|
-
topic: topic ?? null,
|
|
83
|
-
errorCode: null,
|
|
84
|
-
errorMessage: null,
|
|
85
|
-
metadata: applicationMetadataRecord(metadata),
|
|
86
|
-
flowId: flow?.flowId,
|
|
87
|
-
flowOrigin: flow?.flowOrigin
|
|
88
|
-
};
|
|
89
|
-
return [encodeChannelHeader(header), encoded.message];
|
|
59
|
+
return [encodeChannelHeader(kind, channelName, messageName, encoded.contentType, envelopeCorrelationId, new Date(deadlineUnixMs).toISOString(), topic ?? null, null, null, undefined, applicationMetadataRecord(metadata), flow?.flowId, flow?.flowOrigin), encoded.message];
|
|
90
60
|
}
|
|
91
61
|
function encodeChannelPublishEnvelopeParts(channelName, topic, packetName, payload, codecs, createFlow = true, metadata = EMPTY_OUTBOUND_METADATA) {
|
|
92
62
|
const messageName = (0, packet_name_1.resolveFrameworkPacketName)(payload, packetName, 'Channel');
|
|
93
63
|
const encoded = encodePayload(payload, (0, channel_framework_packets_1.codecsForFrameworkPacket)(messageName, codecs), messageName, 'payload');
|
|
94
64
|
const flow = createFlow ? (0, flow_context_1.currentOrCreateFlow)('Application') : undefined;
|
|
95
|
-
|
|
96
|
-
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
97
|
-
kind: 4 /* ZLinkChannelMessageKind.Publish */,
|
|
98
|
-
channelName,
|
|
99
|
-
messageName,
|
|
100
|
-
contentType: encoded.contentType,
|
|
101
|
-
correlationId: null,
|
|
102
|
-
deadline: null,
|
|
103
|
-
topic,
|
|
104
|
-
errorCode: null,
|
|
105
|
-
errorMessage: null,
|
|
106
|
-
metadata: applicationMetadataRecord(metadata),
|
|
107
|
-
flowId: flow?.flowId,
|
|
108
|
-
flowOrigin: flow?.flowOrigin
|
|
109
|
-
};
|
|
110
|
-
return [encodeChannelHeader(header), encoded.message];
|
|
65
|
+
return [encodeChannelHeader(4 /* ZLinkChannelMessageKind.Publish */, channelName, messageName, encoded.contentType, null, null, topic, null, null, undefined, applicationMetadataRecord(metadata), flow?.flowId, flow?.flowOrigin), encoded.message];
|
|
111
66
|
}
|
|
112
67
|
function encodeChannelReplyParts(request, payload, codecs) {
|
|
113
68
|
const encoded = encodePayload(payload ?? Buffer.alloc(0), (0, channel_framework_packets_1.codecsForFrameworkPacket)(request.messageName, codecs), request.messageName, 'reply');
|
|
114
|
-
|
|
115
|
-
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
116
|
-
kind: 2 /* ZLinkChannelMessageKind.Response */,
|
|
117
|
-
channelName: request.channelName,
|
|
118
|
-
messageName: request.messageName,
|
|
119
|
-
contentType: encoded.contentType,
|
|
120
|
-
correlationId: request.correlationId,
|
|
121
|
-
deadline: null,
|
|
122
|
-
topic: null,
|
|
123
|
-
metadata: {},
|
|
124
|
-
flowId: request.flowId,
|
|
125
|
-
flowOrigin: request.flowOrigin
|
|
126
|
-
};
|
|
127
|
-
return [encodeChannelHeader(header), encoded.message];
|
|
69
|
+
return [encodeChannelHeader(2 /* ZLinkChannelMessageKind.Response */, request.channelName, request.messageName, encoded.contentType, request.correlationId, null, null, undefined, undefined, undefined, EMPTY_APPLICATION_METADATA, request.flowId, request.flowOrigin), encoded.message];
|
|
128
70
|
}
|
|
129
71
|
/**
|
|
130
72
|
* Reply metadata marker for errors the framework generated itself (never for
|
|
@@ -147,13 +89,12 @@ const ERROR_KIND_WIRE_NAMES = [
|
|
|
147
89
|
'not_configured', // 3
|
|
148
90
|
'rejected', // 4
|
|
149
91
|
'unavailable', // 5
|
|
150
|
-
'
|
|
151
|
-
'
|
|
152
|
-
'
|
|
153
|
-
'
|
|
154
|
-
'
|
|
155
|
-
'
|
|
156
|
-
'internal_failure' // 12
|
|
92
|
+
'deadline_exceeded', // 6
|
|
93
|
+
'shutting_down', // 7
|
|
94
|
+
'protocol_error', // 8
|
|
95
|
+
'invalid_operation', // 9
|
|
96
|
+
'data_lost', // 10
|
|
97
|
+
'internal_failure' // 11
|
|
157
98
|
];
|
|
158
99
|
const ERROR_KIND_BY_WIRE_NAME = new Map(ERROR_KIND_WIRE_NAMES.map((name, kind) => [name, kind]));
|
|
159
100
|
function channelErrorCodeName(kind) {
|
|
@@ -164,22 +105,7 @@ function encodeChannelErrorReplyParts(request, error, metadata = {}) {
|
|
|
164
105
|
? error.kind
|
|
165
106
|
: contracts_1.ZLinkFrameworkErrorKind.InternalFailure);
|
|
166
107
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
167
|
-
|
|
168
|
-
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
169
|
-
kind: 5 /* ZLinkChannelMessageKind.Error */,
|
|
170
|
-
channelName: request.channelName,
|
|
171
|
-
messageName: request.messageName,
|
|
172
|
-
contentType: exports.JSON_CONTENT_TYPE,
|
|
173
|
-
correlationId: request.correlationId,
|
|
174
|
-
deadline: null,
|
|
175
|
-
topic: null,
|
|
176
|
-
errorCode,
|
|
177
|
-
errorMessage,
|
|
178
|
-
metadata,
|
|
179
|
-
flowId: request.flowId,
|
|
180
|
-
flowOrigin: request.flowOrigin
|
|
181
|
-
};
|
|
182
|
-
return [encodeChannelHeader(header), encodeJsonBytes(null)];
|
|
108
|
+
return [encodeChannelHeader(5 /* ZLinkChannelMessageKind.Error */, request.channelName, request.messageName, exports.JSON_CONTENT_TYPE, request.correlationId, null, null, errorCode, errorMessage, undefined, metadata, request.flowId, request.flowOrigin), encodeJsonBytes(null)];
|
|
183
109
|
}
|
|
184
110
|
function decodeChannelReply(parts, codecs) {
|
|
185
111
|
const header = decodeChannelHeader(parts);
|
|
@@ -335,25 +261,145 @@ function isMessage(value) {
|
|
|
335
261
|
function encodeJsonBytes(value, schema) {
|
|
336
262
|
return Buffer.from((0, framework_json_v1_1.stringifyFrameworkJsonV1)(value, schema));
|
|
337
263
|
}
|
|
338
|
-
function encodeChannelHeader(
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
264
|
+
function encodeChannelHeader(kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin) {
|
|
265
|
+
// The wire has a fixed field order. Measure escaped UTF-8 first, then write
|
|
266
|
+
// each field once into the only header Buffer: no header object, whole JSON
|
|
267
|
+
// string, or post-encode byte copy exists on the outbound path.
|
|
268
|
+
const measure = new ChannelHeaderWriter();
|
|
269
|
+
writeChannelHeader(measure, kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin);
|
|
270
|
+
const result = Buffer.alloc(measure.byteLength);
|
|
271
|
+
const writer = new ChannelHeaderWriter(result);
|
|
272
|
+
writeChannelHeader(writer, kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin);
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
function writeChannelHeader(writer, kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin) {
|
|
276
|
+
writer.append('{"formatMarker":');
|
|
277
|
+
writer.append(String(exports.ZLINK_CHANNEL_FORMAT_MARKER));
|
|
278
|
+
writer.append(',"kind":');
|
|
279
|
+
writer.append(String(kind));
|
|
280
|
+
writer.append(',"channelName":');
|
|
281
|
+
writer.string(channelName);
|
|
282
|
+
writer.append(',"messageName":');
|
|
283
|
+
writer.string(messageName);
|
|
284
|
+
writer.append(',"contentType":');
|
|
285
|
+
writer.string(contentType);
|
|
286
|
+
writer.append(',"correlationId":');
|
|
287
|
+
writer.nullableString(correlationId);
|
|
288
|
+
writer.append(',"deadline":');
|
|
289
|
+
writer.nullableString(deadline);
|
|
290
|
+
writer.append(',"topic":');
|
|
291
|
+
writer.nullableString(topic);
|
|
292
|
+
if (errorCode !== undefined) {
|
|
293
|
+
writer.append(',"errorCode":');
|
|
294
|
+
writer.nullableString(errorCode);
|
|
295
|
+
}
|
|
296
|
+
if (errorMessage !== undefined) {
|
|
297
|
+
writer.append(',"errorMessage":');
|
|
298
|
+
writer.nullableString(errorMessage);
|
|
299
|
+
}
|
|
300
|
+
if (source !== undefined) {
|
|
301
|
+
writer.append(',"source":');
|
|
302
|
+
writer.nullableString(source);
|
|
303
|
+
}
|
|
304
|
+
writer.append(',"metadata":{');
|
|
305
|
+
let first = true;
|
|
306
|
+
for (const name in metadata) {
|
|
307
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, name))
|
|
308
|
+
continue;
|
|
309
|
+
if (!first)
|
|
310
|
+
writer.append(',');
|
|
311
|
+
first = false;
|
|
312
|
+
writer.string(name);
|
|
313
|
+
writer.append(':');
|
|
314
|
+
writer.string(metadata[name]);
|
|
315
|
+
}
|
|
316
|
+
writer.append('}');
|
|
317
|
+
if (flowId !== undefined) {
|
|
318
|
+
writer.append(',"flowId":');
|
|
319
|
+
writer.string(flowId);
|
|
320
|
+
}
|
|
321
|
+
if (flowOrigin !== undefined) {
|
|
322
|
+
writer.append(',"flowOrigin":');
|
|
323
|
+
writer.append(String(encodeFlowOrigin(flowOrigin)));
|
|
324
|
+
}
|
|
325
|
+
writer.append('}');
|
|
326
|
+
}
|
|
327
|
+
class ChannelHeaderWriter {
|
|
328
|
+
output;
|
|
329
|
+
offset = 0;
|
|
330
|
+
constructor(output) {
|
|
331
|
+
this.output = output;
|
|
332
|
+
}
|
|
333
|
+
get byteLength() {
|
|
334
|
+
return this.offset;
|
|
335
|
+
}
|
|
336
|
+
append(value) {
|
|
337
|
+
if (this.output === undefined) {
|
|
338
|
+
this.offset += Buffer.byteLength(value);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
this.offset += this.output.write(value, this.offset, 'utf8');
|
|
342
|
+
}
|
|
343
|
+
nullableString(value) {
|
|
344
|
+
if (value === null)
|
|
345
|
+
this.append('null');
|
|
346
|
+
else
|
|
347
|
+
this.string(value);
|
|
348
|
+
}
|
|
349
|
+
string(value) {
|
|
350
|
+
this.append('"');
|
|
351
|
+
let start = 0;
|
|
352
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
353
|
+
const code = value.charCodeAt(index);
|
|
354
|
+
let escaped;
|
|
355
|
+
switch (code) {
|
|
356
|
+
case 0x08:
|
|
357
|
+
escaped = '\\b';
|
|
358
|
+
break;
|
|
359
|
+
case 0x09:
|
|
360
|
+
escaped = '\\t';
|
|
361
|
+
break;
|
|
362
|
+
case 0x0a:
|
|
363
|
+
escaped = '\\n';
|
|
364
|
+
break;
|
|
365
|
+
case 0x0c:
|
|
366
|
+
escaped = '\\f';
|
|
367
|
+
break;
|
|
368
|
+
case 0x0d:
|
|
369
|
+
escaped = '\\r';
|
|
370
|
+
break;
|
|
371
|
+
case 0x22:
|
|
372
|
+
escaped = '\\"';
|
|
373
|
+
break;
|
|
374
|
+
case 0x5c:
|
|
375
|
+
escaped = '\\\\';
|
|
376
|
+
break;
|
|
377
|
+
default:
|
|
378
|
+
if (code < 0x20) {
|
|
379
|
+
escaped = `\\u00${code.toString(16).padStart(2, '0')}`;
|
|
380
|
+
}
|
|
381
|
+
else if (code >= 0xd800 && code <= 0xdbff) {
|
|
382
|
+
const next = value.charCodeAt(index + 1);
|
|
383
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
384
|
+
index += 1;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
escaped = `\\u${code.toString(16)}`;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
391
|
+
escaped = `\\u${code.toString(16)}`;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (escaped === undefined)
|
|
395
|
+
continue;
|
|
396
|
+
this.append(value.slice(start, index));
|
|
397
|
+
this.append(escaped);
|
|
398
|
+
start = index + 1;
|
|
399
|
+
}
|
|
400
|
+
this.append(value.slice(start));
|
|
401
|
+
this.append('"');
|
|
402
|
+
}
|
|
357
403
|
}
|
|
358
404
|
function encodeFlowOrigin(origin) {
|
|
359
405
|
switch (origin) {
|
|
@@ -367,13 +413,173 @@ function decodeChannelHeader(parts, flowEnabled = true) {
|
|
|
367
413
|
if (parts.length === 0) {
|
|
368
414
|
throw new configuration_1.ZLinkConfigurationException('Channel envelope header part is missing.');
|
|
369
415
|
}
|
|
370
|
-
return validateChannelHeader(
|
|
416
|
+
return validateChannelHeader(parseChannelHeaderBytes(parts[0].data()), flowEnabled);
|
|
371
417
|
}
|
|
372
418
|
function parseWireJson(payload, schema) {
|
|
373
419
|
return (0, framework_json_v1_1.parseFrameworkJsonV1)(payload, {
|
|
374
420
|
rejectPropertyName: isPrototypeKey
|
|
375
421
|
}, schema);
|
|
376
422
|
}
|
|
423
|
+
function parseChannelHeaderBytes(payload) {
|
|
424
|
+
return tryParseCanonicalChannelHeader(payload) ?? parseWireJson(payload.toString());
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Accept the byte layout emitted by writeChannelHeader without materializing
|
|
428
|
+
* the enclosing JSON text. Any variation falls through to the established
|
|
429
|
+
* framework-json-v1 parser, which remains the sole authority for JSON
|
|
430
|
+
* failures, unknown properties, and prototype-key rejection.
|
|
431
|
+
*/
|
|
432
|
+
function tryParseCanonicalChannelHeader(payload) {
|
|
433
|
+
const reader = new CanonicalChannelHeaderReader(payload);
|
|
434
|
+
if (!reader.consume('{"formatMarker":242,"kind":'))
|
|
435
|
+
return undefined;
|
|
436
|
+
const kind = reader.readSingleDigit();
|
|
437
|
+
if (kind === undefined || !reader.consume(',"channelName":'))
|
|
438
|
+
return undefined;
|
|
439
|
+
const channelName = reader.readString();
|
|
440
|
+
if (channelName === undefined || !reader.consume(',"messageName":'))
|
|
441
|
+
return undefined;
|
|
442
|
+
const messageName = reader.readString();
|
|
443
|
+
if (messageName === undefined || !reader.consume(',"contentType":'))
|
|
444
|
+
return undefined;
|
|
445
|
+
const contentType = reader.readString();
|
|
446
|
+
if (contentType === undefined || !reader.consume(',"correlationId":'))
|
|
447
|
+
return undefined;
|
|
448
|
+
const correlationId = reader.readNullableString();
|
|
449
|
+
if (correlationId === undefined || !reader.consume(',"deadline":'))
|
|
450
|
+
return undefined;
|
|
451
|
+
const deadline = reader.readNullableString();
|
|
452
|
+
if (deadline === undefined || !reader.consume(',"topic":'))
|
|
453
|
+
return undefined;
|
|
454
|
+
const topic = reader.readNullableString();
|
|
455
|
+
if (topic === undefined)
|
|
456
|
+
return undefined;
|
|
457
|
+
const header = {
|
|
458
|
+
formatMarker: exports.ZLINK_CHANNEL_FORMAT_MARKER,
|
|
459
|
+
kind,
|
|
460
|
+
channelName,
|
|
461
|
+
messageName,
|
|
462
|
+
contentType,
|
|
463
|
+
correlationId: correlationId === NULL_JSON_STRING ? null : correlationId,
|
|
464
|
+
deadline: deadline === NULL_JSON_STRING ? null : deadline,
|
|
465
|
+
topic: topic === NULL_JSON_STRING ? null : topic
|
|
466
|
+
};
|
|
467
|
+
if (!reader.readOptionalNullableString('errorCode', header))
|
|
468
|
+
return undefined;
|
|
469
|
+
if (!reader.readOptionalNullableString('errorMessage', header))
|
|
470
|
+
return undefined;
|
|
471
|
+
if (!reader.readOptionalNullableString('source', header))
|
|
472
|
+
return undefined;
|
|
473
|
+
if (!reader.consume(',"metadata":{}'))
|
|
474
|
+
return undefined;
|
|
475
|
+
header.metadata = {};
|
|
476
|
+
if (!reader.readOptionalString('flowId', header))
|
|
477
|
+
return undefined;
|
|
478
|
+
if (!reader.readOptionalSingleDigit('flowOrigin', header))
|
|
479
|
+
return undefined;
|
|
480
|
+
return reader.consume('}') && reader.atEnd() ? header : undefined;
|
|
481
|
+
}
|
|
482
|
+
const NULL_JSON_STRING = Symbol('null JSON string');
|
|
483
|
+
class CanonicalChannelHeaderReader {
|
|
484
|
+
bytes;
|
|
485
|
+
index = 0;
|
|
486
|
+
constructor(bytes) {
|
|
487
|
+
this.bytes = bytes;
|
|
488
|
+
}
|
|
489
|
+
atEnd() {
|
|
490
|
+
return this.index === this.bytes.length;
|
|
491
|
+
}
|
|
492
|
+
consume(value) {
|
|
493
|
+
if (this.index + value.length > this.bytes.length)
|
|
494
|
+
return false;
|
|
495
|
+
for (let offset = 0; offset < value.length; offset += 1) {
|
|
496
|
+
if (this.bytes[this.index + offset] !== value.charCodeAt(offset))
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
this.index += value.length;
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
readSingleDigit() {
|
|
503
|
+
if (this.index === this.bytes.length)
|
|
504
|
+
return undefined;
|
|
505
|
+
const value = this.bytes[this.index];
|
|
506
|
+
if (value < 0x30 || value > 0x39)
|
|
507
|
+
return undefined;
|
|
508
|
+
this.index += 1;
|
|
509
|
+
return value - 0x30;
|
|
510
|
+
}
|
|
511
|
+
readString() {
|
|
512
|
+
if (this.bytes[this.index] !== 0x22)
|
|
513
|
+
return undefined;
|
|
514
|
+
const start = this.index;
|
|
515
|
+
this.index += 1;
|
|
516
|
+
while (this.index < this.bytes.length) {
|
|
517
|
+
const value = this.bytes[this.index++];
|
|
518
|
+
if (value === 0x22) {
|
|
519
|
+
return JSON.parse(this.bytes.toString('utf8', start, this.index));
|
|
520
|
+
}
|
|
521
|
+
if (value < 0x20)
|
|
522
|
+
return undefined;
|
|
523
|
+
if (value !== 0x5c)
|
|
524
|
+
continue;
|
|
525
|
+
if (this.index === this.bytes.length)
|
|
526
|
+
return undefined;
|
|
527
|
+
const escaped = this.bytes[this.index++];
|
|
528
|
+
if (escaped === 0x75) {
|
|
529
|
+
for (let count = 0; count < 4; count += 1) {
|
|
530
|
+
if (this.index === this.bytes.length)
|
|
531
|
+
return undefined;
|
|
532
|
+
const digit = this.bytes[this.index++];
|
|
533
|
+
if (!isHexDigit(digit))
|
|
534
|
+
return undefined;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
else if (escaped !== 0x22 && escaped !== 0x5c && escaped !== 0x2f
|
|
538
|
+
&& escaped !== 0x62 && escaped !== 0x66 && escaped !== 0x6e
|
|
539
|
+
&& escaped !== 0x72 && escaped !== 0x74) {
|
|
540
|
+
return undefined;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
readNullableString() {
|
|
546
|
+
if (this.consume('null'))
|
|
547
|
+
return NULL_JSON_STRING;
|
|
548
|
+
return this.readString();
|
|
549
|
+
}
|
|
550
|
+
readOptionalNullableString(name, target) {
|
|
551
|
+
if (!this.consume(`,\"${name}\":`))
|
|
552
|
+
return true;
|
|
553
|
+
const value = this.readNullableString();
|
|
554
|
+
if (value === undefined)
|
|
555
|
+
return false;
|
|
556
|
+
target[name] = value === NULL_JSON_STRING ? null : value;
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
readOptionalString(name, target) {
|
|
560
|
+
if (!this.consume(`,\"${name}\":`))
|
|
561
|
+
return true;
|
|
562
|
+
const value = this.readString();
|
|
563
|
+
if (value === undefined)
|
|
564
|
+
return false;
|
|
565
|
+
target[name] = value;
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
readOptionalSingleDigit(name, target) {
|
|
569
|
+
if (!this.consume(`,\"${name}\":`))
|
|
570
|
+
return true;
|
|
571
|
+
const value = this.readSingleDigit();
|
|
572
|
+
if (value === undefined)
|
|
573
|
+
return false;
|
|
574
|
+
target[name] = value;
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
function isHexDigit(value) {
|
|
579
|
+
return (value >= 0x30 && value <= 0x39)
|
|
580
|
+
|| (value >= 0x41 && value <= 0x46)
|
|
581
|
+
|| (value >= 0x61 && value <= 0x66);
|
|
582
|
+
}
|
|
377
583
|
function schemaForInboundChannelEnvelope(header) {
|
|
378
584
|
const contract = (0, Attributes_1.readZLinkPacketJsonContract)(header.messageName);
|
|
379
585
|
return header.kind === 2 /* ZLinkChannelMessageKind.Response */ ? contract?.reply : contract?.payload;
|
|
@@ -401,22 +607,19 @@ function validateChannelHeader(value, flowEnabled = true) {
|
|
|
401
607
|
}
|
|
402
608
|
const correlationId = requireNullableString(header.correlationId, 'correlationId');
|
|
403
609
|
validateCorrelationForKind(kind, correlationId);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
flowId,
|
|
418
|
-
flowOrigin
|
|
419
|
-
};
|
|
610
|
+
requireString(header.channelName, 'channelName');
|
|
611
|
+
requireString(header.messageName, 'messageName');
|
|
612
|
+
requireNullableString(header.deadline, 'deadline');
|
|
613
|
+
requireNullableString(header.topic, 'topic');
|
|
614
|
+
// Parsing already gives this receive operation an owned object. Validate
|
|
615
|
+
// and normalize it here instead of allocating a second header per record.
|
|
616
|
+
header.errorCode = header.errorCode === undefined ? null : requireNullableString(header.errorCode, 'errorCode');
|
|
617
|
+
header.errorMessage = header.errorMessage === undefined ? null : requireNullableString(header.errorMessage, 'errorMessage');
|
|
618
|
+
header.source = header.source === undefined ? undefined : requireNullableString(header.source, 'source');
|
|
619
|
+
header.metadata = requireApplicationMetadata(header.metadata);
|
|
620
|
+
header.flowId = flowId;
|
|
621
|
+
header.flowOrigin = flowOrigin;
|
|
622
|
+
return header;
|
|
420
623
|
}
|
|
421
624
|
function correlationIdForOutboundKind(kind, correlationId) {
|
|
422
625
|
if (kind === 1 /* ZLinkChannelMessageKind.Request */) {
|
|
@@ -6,8 +6,15 @@ export interface ZLinkMultipartOperation<TNext> {
|
|
|
6
6
|
export interface ZLinkMultipartSubmitOperation extends ZLinkMultipartOperation<ZLinkMultipartSubmitOperation> {
|
|
7
7
|
submit(): unknown;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Binding submit()은 제출 스냅샷을 돌려준다. admission을 기다리려면 `.admitted`를
|
|
11
|
+
* await 한다. binding 타입과 구조적으로 호환되므로 import 하지 않는다.
|
|
12
|
+
*/
|
|
13
|
+
export interface ZLinkMultipartSubmission {
|
|
14
|
+
readonly admitted: Promise<void>;
|
|
15
|
+
}
|
|
9
16
|
export interface ZLinkMultipartAsyncSubmitOperation extends ZLinkMultipartOperation<ZLinkMultipartAsyncSubmitOperation> {
|
|
10
|
-
submit():
|
|
17
|
+
submit(): ZLinkMultipartSubmission;
|
|
11
18
|
}
|
|
12
19
|
export type ZLinkMultipartReplyOperation = ZLinkMultipartSubmitOperation;
|
|
13
20
|
export declare function appendParts<TNext extends ZLinkMultipartOperation<TNext>>(operation: ZLinkMultipartOperation<TNext>, parts: readonly MessageLike[]): TNext;
|
|
@@ -331,8 +331,6 @@ function requestTerminalResult(error, signal) {
|
|
|
331
331
|
if (error instanceof contracts_1.ZLinkFrameworkException) {
|
|
332
332
|
if (error.kind === contracts_1.ZLinkFrameworkErrorKind.ShuttingDown)
|
|
333
333
|
return 'shutdown';
|
|
334
|
-
if (error.kind === contracts_1.ZLinkFrameworkErrorKind.CapacityExceeded)
|
|
335
|
-
return 'backpressured';
|
|
336
334
|
}
|
|
337
335
|
return 'failed';
|
|
338
336
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Message } from '../../contracts/Common/Message';
|
|
2
2
|
import type { ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
|
|
3
3
|
import type { ZLinkBackendRouterSocket, ZLinkBackendSpotRouteBridge, ZLinkBackendSubscriberSocket, ZLinkBackendReadablePoller, ZLinkChannelBackendAdapter } from '../backend/contracts';
|
|
4
|
+
import type { ZLinkMultipartAsyncSubmitOperation } from './channel-multipart';
|
|
4
5
|
import type { ZLinkChannelEnvelopeHeader } from './channel-envelope';
|
|
5
6
|
import { type ZLinkReceiveTaskErrorReporter } from './channel-receive-task-tracker';
|
|
6
7
|
import { ApplicationJobQueue } from '../host/application-job-queue';
|
|
@@ -10,9 +11,6 @@ interface ZLinkMultipartOperation<TNext> {
|
|
|
10
11
|
interface ZLinkMultipartSubmitOperation extends ZLinkMultipartOperation<ZLinkMultipartSubmitOperation> {
|
|
11
12
|
submit(): unknown;
|
|
12
13
|
}
|
|
13
|
-
interface ZLinkMultipartAsyncSubmitOperation extends ZLinkMultipartOperation<ZLinkMultipartAsyncSubmitOperation> {
|
|
14
|
-
submit(): Promise<void>;
|
|
15
|
-
}
|
|
16
14
|
type ZLinkMultipartReplyOperation = ZLinkMultipartSubmitOperation;
|
|
17
15
|
interface ZLinkChannelRequestDispatchLoop {
|
|
18
16
|
/** Spec 27 §4: with tracing Off, inbound flow fields are neither validated nor carried forward. */
|