@zlink-systems/framework 0.29.0 → 0.30.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/Builders.d.ts +1 -2
- package/dist/contracts/Configuration/Configs.d.ts +0 -5
- package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
- package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
- package/dist/contracts/Configuration/index.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +3 -1
- package/dist/runtime/actors/actor-handoff.d.ts +3 -2
- package/dist/runtime/actors/actor-handoff.js +9 -4
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +1 -0
- package/dist/runtime/actors/index.d.ts +2 -0
- package/dist/runtime/actors/index.js +21 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +3 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +6 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +3 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +5 -0
- package/dist/runtime/application-jobs/contracts.d.ts +5 -1
- package/dist/runtime/backend/contracts/index.d.ts +10 -19
- package/dist/runtime/backend/mesh-completion-table.d.ts +6 -4
- package/dist/runtime/backend/mesh-completion-table.js +28 -18
- package/dist/runtime/backend/mesh-dispatch-pump.js +21 -25
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +24 -29
- package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +11 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +10 -12
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +64 -98
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +10 -5
- package/dist/runtime/backend/raw-binding-port.d.ts +9 -2
- package/dist/runtime/channels/channel-receive-loops.js +3 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
- package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
- package/dist/runtime/channels/channel-socket-registry.js +59 -82
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
- package/dist/runtime/diagnostics/message-flow.js +3 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +15 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +193 -64
- package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
- package/dist/runtime/foundation/service-liveness-registry.js +57 -44
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
- package/dist/runtime/foundation/service-mailbox.js +2 -1
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +7 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +60 -41
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -2
- package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -3
- package/dist/runtime/foundation/service-topology-registry.js +9 -4
- package/dist/runtime/handlers/handler-instance-scope.js +1 -1
- package/dist/runtime/host/actor-packet-relay.js +7 -7
- package/dist/runtime/host/actor-placement-coordinator.d.ts +2 -1
- package/dist/runtime/host/actor-placement-coordinator.js +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -1
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -1
- package/dist/runtime/host/application-job-queue.d.ts +11 -4
- package/dist/runtime/host/application-job-queue.js +66 -10
- package/dist/runtime/host/entry-actor-runtime.js +1 -1
- package/dist/runtime/host/index.d.ts +1 -1
- package/dist/runtime/host/index.js +18 -13
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
- package/dist/runtime/host/instance-activation-authority.js +89 -25
- package/dist/runtime/host/service-relocation-host-runtime.js +2 -2
- package/dist/runtime/host/spot-address-transport.d.ts +1 -0
- package/dist/runtime/host/spot-address-transport.js +25 -12
- package/dist/runtime/host/spot-runtime-options-factory.js +2 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +3 -2
- package/dist/runtime/locations/in-memory-authority-store.d.ts +5 -2
- package/dist/runtime/locations/in-memory-authority-store.js +107 -14
- package/dist/runtime/locations/in-memory-location-store.d.ts +3 -3
- package/dist/runtime/locations/in-memory-location-store.js +31 -13
- package/dist/runtime/locations/internal-location-contracts.d.ts +8 -0
- package/dist/runtime/locations/location-store-repository.d.ts +4 -2
- package/dist/runtime/locations/location-store-repository.js +209 -33
- package/dist/runtime/locations/resolvers.d.ts +2 -1
- package/dist/runtime/locations/resolvers.js +10 -1
- package/dist/runtime/messaging/submission-result.d.ts +1 -1
- package/dist/runtime/messaging/submission-result.js +2 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +2 -0
- package/dist/runtime/spots/index.d.ts +4 -3
- package/dist/runtime/spots/index.js +14 -14
- package/dist/runtime/spots/spot-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-activation.js +4 -4
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
- package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
- package/dist/runtime/spots/spot-entry-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-entry-activation.js +6 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +3 -1
- package/dist/runtime/spots/spot-node-runtime-manager.js +10 -11
- package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
- package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +1 -0
- package/dist/runtime/spots/spot-serial-executor.js +10 -1
- package/dist/runtime/streams/stream-session-runtime.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Configuration/Builders.ts +1 -2
- package/src/contracts/Configuration/Configs.ts +0 -6
- package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
- package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
- package/src/contracts/Configuration/index.ts +1 -6
- package/src/internal.ts +1 -0
- package/src/runtime/actors/actor-handoff.ts +13 -4
- package/src/runtime/actors/actor-runtime-contracts.ts +4 -0
- package/src/runtime/actors/index.ts +77 -42
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +12 -2
- package/src/runtime/application-jobs/application-job-queue-scope.ts +6 -1
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +10 -18
- package/src/runtime/backend/mesh-completion-table.ts +36 -19
- package/src/runtime/backend/mesh-dispatch-pump.ts +19 -22
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
- package/src/runtime/backend/node/node-backend-adapter-support.ts +31 -29
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
- package/src/runtime/backend/node/node-raw-binding-port.ts +19 -10
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +81 -111
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +12 -8
- package/src/runtime/backend/raw-binding-port.ts +12 -2
- package/src/runtime/channels/channel-receive-loops.ts +3 -3
- package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
- package/src/runtime/channels/channel-socket-registry.ts +84 -130
- package/src/runtime/diagnostics/message-flow.ts +1 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +268 -70
- package/src/runtime/foundation/service-liveness-registry.ts +68 -59
- package/src/runtime/foundation/service-mailbox.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +109 -77
- package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -79
- package/src/runtime/foundation/service-topology-registry.ts +13 -7
- package/src/runtime/handlers/handler-instance-scope.ts +2 -1
- package/src/runtime/host/actor-packet-relay.ts +7 -0
- package/src/runtime/host/actor-placement-coordinator.ts +8 -2
- package/src/runtime/host/actor-runtime-options-factory.ts +7 -0
- package/src/runtime/host/application-job-queue.ts +77 -10
- package/src/runtime/host/entry-actor-runtime.ts +1 -0
- package/src/runtime/host/index.ts +30 -7
- package/src/runtime/host/instance-activation-authority.ts +132 -27
- package/src/runtime/host/service-relocation-host-runtime.ts +2 -0
- package/src/runtime/host/spot-address-transport.ts +45 -22
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
- package/src/runtime/locations/domain-store-contract.ts +6 -2
- package/src/runtime/locations/in-memory-authority-store.ts +153 -12
- package/src/runtime/locations/in-memory-location-store.ts +39 -13
- package/src/runtime/locations/internal-location-contracts.ts +10 -0
- package/src/runtime/locations/location-store-repository.ts +295 -36
- package/src/runtime/locations/resolvers.ts +25 -2
- package/src/runtime/messaging/submission-result.ts +2 -2
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +2 -0
- package/src/runtime/spots/index.ts +16 -0
- package/src/runtime/spots/spot-activation.ts +5 -0
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
- package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
- package/src/runtime/spots/spot-entry-activation.ts +7 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +14 -12
- package/src/runtime/spots/spot-routing-internal.ts +14 -0
- package/src/runtime/spots/spot-runtime-ports.ts +2 -0
- package/src/runtime/spots/spot-serial-executor.ts +10 -4
- package/src/runtime/streams/stream-session-runtime.ts +1 -1
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
encodeInstanceRouteV1,
|
|
15
15
|
encodeSpotRequestCommand,
|
|
16
16
|
encodeSpotSendCommand,
|
|
17
|
+
type InstanceRouteV1,
|
|
17
18
|
type ServiceWireDecoderContext
|
|
18
19
|
} from '../protocol/service_wire_codec.generated';
|
|
19
20
|
import {
|
|
@@ -82,8 +83,6 @@ import {
|
|
|
82
83
|
import { APPLICATION_PAYLOAD_VERSION, ServiceWireProtocolError } from './service-wire-m6a-codec';
|
|
83
84
|
const MESSAGE_FOLLOW_MAX_BODY_BYTES = 16 * 1024 * 1024;
|
|
84
85
|
const MESSAGE_FOLLOW_VERSION = 1;
|
|
85
|
-
const INSTANCE_ROUTE_VERSION = 1;
|
|
86
|
-
const INSTANCE_ACTIVATION_VERSION = 2;
|
|
87
86
|
|
|
88
87
|
const PREFIX_SIZE = SERVICE_WIRE_PREFIX_SIZE;
|
|
89
88
|
const MAGIC_0 = SERVICE_WIRE_MAGIC[0];
|
|
@@ -946,6 +945,10 @@ export interface ServiceInstanceActivationTarget {
|
|
|
946
945
|
readonly descriptorVersion: string;
|
|
947
946
|
}
|
|
948
947
|
|
|
948
|
+
export interface ServiceInstanceColdActivationTarget extends ServiceInstanceActivationTarget {
|
|
949
|
+
readonly targetMeshName: string;
|
|
950
|
+
}
|
|
951
|
+
|
|
949
952
|
export interface ServiceUserSpotReservationFence {
|
|
950
953
|
readonly reservationId: string;
|
|
951
954
|
readonly expectedStoreVersion: string;
|
|
@@ -1105,7 +1108,7 @@ export type ServiceStatefulWireRecord =
|
|
|
1105
1108
|
| {
|
|
1106
1109
|
readonly kind: 'instanceSpot';
|
|
1107
1110
|
readonly activation: 'missing';
|
|
1108
|
-
readonly target:
|
|
1111
|
+
readonly target: ServiceInstanceColdActivationTarget;
|
|
1109
1112
|
readonly sourceNodeGeneration: bigint;
|
|
1110
1113
|
readonly sourceNodeRid: string;
|
|
1111
1114
|
readonly sourceSpotId?: string;
|
|
@@ -1435,7 +1438,7 @@ export function encodeInstanceSpotHeader(
|
|
|
1435
1438
|
}
|
|
1436
1439
|
|
|
1437
1440
|
export function encodeInstanceSpotActivationHeader(
|
|
1438
|
-
target:
|
|
1441
|
+
target: ServiceInstanceColdActivationTarget,
|
|
1439
1442
|
sourceNodeGeneration: bigint,
|
|
1440
1443
|
sourceNodeRid: string,
|
|
1441
1444
|
sourceSpotId: string | undefined,
|
|
@@ -1454,25 +1457,28 @@ export function encodeInstanceSpotActivationHeader(
|
|
|
1454
1457
|
if (operationKind === 'send' && replyRouteId !== undefined) {
|
|
1455
1458
|
throw new RangeError('Instance Spot send must not carry a reply route.');
|
|
1456
1459
|
}
|
|
1457
|
-
const
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1460
|
+
const encodedRoute = encodeInstanceRouteV1(
|
|
1461
|
+
{
|
|
1462
|
+
routeKind: 'coldActivation',
|
|
1463
|
+
targetNodeRid: toGeneratedRoutingId(target.targetNodeRid, 'targetNodeRid'),
|
|
1464
|
+
targetNodeGeneration: target.targetNodeGeneration,
|
|
1465
|
+
targetSpotId: target.targetSpotId,
|
|
1466
|
+
targetMeshName: target.targetMeshName,
|
|
1467
|
+
stableType: target.stableType,
|
|
1468
|
+
targetDescriptorVersion: target.descriptorVersion,
|
|
1469
|
+
deadlineUnixMs
|
|
1470
|
+
},
|
|
1471
|
+
STATEFUL_MESSAGE_CONTEXT
|
|
1463
1472
|
);
|
|
1464
1473
|
return concat(
|
|
1465
1474
|
prefix(M6bServiceWireCommand.instanceSpot, hasMetadata ? M6bServiceWireFlag.metadata : 0),
|
|
1466
|
-
|
|
1467
|
-
u16(targetBody.byteLength),
|
|
1468
|
-
targetBody,
|
|
1475
|
+
encodedRoute,
|
|
1469
1476
|
u64Any(sourceNodeGeneration),
|
|
1470
1477
|
rid(sourceNodeRid, 'sourceNodeRid'),
|
|
1471
1478
|
optionalRid(sourceSpotId),
|
|
1472
1479
|
Buffer.of(operationKind === 'send' ? 1 : 2),
|
|
1473
1480
|
u64Any(operation.high),
|
|
1474
1481
|
u64Any(operation.low),
|
|
1475
|
-
u64(deadlineUnixMs),
|
|
1476
1482
|
...(operationKind === 'request' ? [u64(requirePositive(replyRouteId, 'replyRouteId'))] : [])
|
|
1477
1483
|
);
|
|
1478
1484
|
}
|
|
@@ -1741,53 +1747,31 @@ export function decodeStatefulHeader(
|
|
|
1741
1747
|
fail(`Invalid command flags '${command.flags}'.`);
|
|
1742
1748
|
}
|
|
1743
1749
|
const routeStart = reader.offset;
|
|
1744
|
-
|
|
1745
|
-
if (version !== INSTANCE_ROUTE_VERSION && version !== INSTANCE_ACTIVATION_VERSION)
|
|
1746
|
-
fail('Unsupported Instance route version.');
|
|
1750
|
+
reader.u8('instanceRoute.kind');
|
|
1747
1751
|
const routeLength = reader.u16('instanceRoute.length');
|
|
1748
1752
|
const routeEnd = reader.offset + routeLength;
|
|
1749
|
-
const
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
generatedReadyRoute?.routeKind === 'ready'
|
|
1761
|
-
? {
|
|
1762
|
-
targetNodeRid: fromGeneratedRoutingId(
|
|
1763
|
-
generatedReadyRoute.targetNodeRid,
|
|
1764
|
-
'targetNodeRid'
|
|
1765
|
-
),
|
|
1766
|
-
targetNodeGeneration: generatedReadyRoute.targetNodeGeneration,
|
|
1767
|
-
targetSpotId: generatedReadyRoute.targetSpotId
|
|
1768
|
-
}
|
|
1769
|
-
: {
|
|
1770
|
-
targetNodeRid: reader.rid('targetNodeRid'),
|
|
1771
|
-
targetNodeGeneration: reader.nonZeroU64('targetNodeGeneration'),
|
|
1772
|
-
targetSpotId: reader.rid('targetSpotId')
|
|
1773
|
-
};
|
|
1774
|
-
const route: ServiceInstanceRouteFence | undefined =
|
|
1775
|
-
generatedReadyRoute?.routeKind === 'ready'
|
|
1776
|
-
? {
|
|
1777
|
-
...commonTarget,
|
|
1778
|
-
...generatedReadyRoute.authority
|
|
1779
|
-
}
|
|
1753
|
+
const generatedRoute = decodeCanonicalInstanceRoute(
|
|
1754
|
+
reader.bytes.subarray(routeStart, routeEnd)
|
|
1755
|
+
);
|
|
1756
|
+
const commonTarget = {
|
|
1757
|
+
targetNodeRid: fromGeneratedRoutingId(generatedRoute.targetNodeRid, 'targetNodeRid'),
|
|
1758
|
+
targetNodeGeneration: generatedRoute.targetNodeGeneration,
|
|
1759
|
+
targetSpotId: generatedRoute.targetSpotId
|
|
1760
|
+
};
|
|
1761
|
+
const route =
|
|
1762
|
+
generatedRoute.routeKind === 'ready'
|
|
1763
|
+
? { ...commonTarget, ...generatedRoute.authority }
|
|
1780
1764
|
: undefined;
|
|
1781
|
-
const target
|
|
1782
|
-
|
|
1765
|
+
const target =
|
|
1766
|
+
generatedRoute.routeKind === 'coldActivation'
|
|
1783
1767
|
? {
|
|
1784
1768
|
...commonTarget,
|
|
1785
|
-
|
|
1786
|
-
|
|
1769
|
+
targetMeshName: generatedRoute.targetMeshName,
|
|
1770
|
+
stableType: generatedRoute.stableType,
|
|
1771
|
+
descriptorVersion: generatedRoute.targetDescriptorVersion
|
|
1787
1772
|
}
|
|
1788
1773
|
: undefined;
|
|
1789
|
-
|
|
1790
|
-
if (reader.offset !== routeEnd) fail('Invalid Instance route body length.');
|
|
1774
|
+
reader.offset = routeEnd;
|
|
1791
1775
|
const sourceNodeGeneration = reader.nonZeroU64('sourceNodeGeneration');
|
|
1792
1776
|
const sourceNodeRid = reader.rid('sourceNodeRid');
|
|
1793
1777
|
const sourceSpotId = reader.optionalRid('sourceSpotId');
|
|
@@ -1799,21 +1783,21 @@ export function decodeStatefulHeader(
|
|
|
1799
1783
|
};
|
|
1800
1784
|
const operationKind = operationValue === 1 ? ('send' as const) : ('request' as const);
|
|
1801
1785
|
if (
|
|
1802
|
-
|
|
1786
|
+
generatedRoute.routeKind === 'ready' &&
|
|
1803
1787
|
((operationKind === 'send' && (operation.high !== 0n || operation.low !== 0n)) ||
|
|
1804
1788
|
(operationKind === 'request' && operation.high === 0n && operation.low === 0n))
|
|
1805
1789
|
) {
|
|
1806
1790
|
fail('Invalid Instance operation identity.');
|
|
1807
1791
|
}
|
|
1808
1792
|
if (
|
|
1809
|
-
|
|
1793
|
+
generatedRoute.routeKind === 'coldActivation' &&
|
|
1810
1794
|
operation.high === 0n &&
|
|
1811
1795
|
operation.low === 0n
|
|
1812
1796
|
) {
|
|
1813
1797
|
fail('Instance activation requires a non-zero operation identity.');
|
|
1814
1798
|
}
|
|
1815
1799
|
const deadlineUnixMs =
|
|
1816
|
-
|
|
1800
|
+
generatedRoute.routeKind === 'coldActivation' ? generatedRoute.deadlineUnixMs : undefined;
|
|
1817
1801
|
const replyRouteId =
|
|
1818
1802
|
operationKind === 'request' ? reader.nonZeroU64('replyRouteId') : undefined;
|
|
1819
1803
|
reader.end();
|
|
@@ -1826,12 +1810,12 @@ export function decodeStatefulHeader(
|
|
|
1826
1810
|
operation,
|
|
1827
1811
|
...(replyRouteId === undefined ? {} : { replyRouteId })
|
|
1828
1812
|
};
|
|
1829
|
-
return
|
|
1813
|
+
return generatedRoute.routeKind === 'ready'
|
|
1830
1814
|
? {
|
|
1831
1815
|
...common,
|
|
1832
1816
|
activation: 'ready',
|
|
1833
1817
|
route: route!,
|
|
1834
|
-
instanceIntent:
|
|
1818
|
+
instanceIntent: generatedRoute.instanceIntent === 'true'
|
|
1835
1819
|
}
|
|
1836
1820
|
: {
|
|
1837
1821
|
...common,
|
|
@@ -2387,11 +2371,6 @@ function text8(value: string, name: string): Buffer {
|
|
|
2387
2371
|
return sized8(value, name);
|
|
2388
2372
|
}
|
|
2389
2373
|
|
|
2390
|
-
function text16(value: string, name: string): Buffer {
|
|
2391
|
-
const bytes = encodeCanonicalServiceWireText(value, name, 0xffff, outOfRange);
|
|
2392
|
-
return concat(u16(bytes.byteLength), bytes);
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
2374
|
function optionalRid(value: string | undefined): Buffer {
|
|
2396
2375
|
return value === undefined ? Buffer.of(0) : rid(value, 'sourceSpotId');
|
|
2397
2376
|
}
|
|
@@ -2448,6 +2427,15 @@ function concat(...parts: readonly Uint8Array[]): Buffer {
|
|
|
2448
2427
|
return Buffer.concat(parts.map((part) => Buffer.from(part)));
|
|
2449
2428
|
}
|
|
2450
2429
|
|
|
2430
|
+
function decodeCanonicalInstanceRoute(bytes: Uint8Array): InstanceRouteV1 {
|
|
2431
|
+
try {
|
|
2432
|
+
return decodeInstanceRouteV1(bytes, STATEFUL_MESSAGE_CONTEXT);
|
|
2433
|
+
} catch (error) {
|
|
2434
|
+
if (error instanceof RangeError) throw new ServiceWireProtocolError(error.message);
|
|
2435
|
+
throw error;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2451
2439
|
function fail(message: string): never {
|
|
2452
2440
|
throw new ServiceWireProtocolError(message);
|
|
2453
2441
|
}
|
|
@@ -3093,21 +3081,9 @@ class FrozenReader {
|
|
|
3093
3081
|
|
|
3094
3082
|
private instanceRoute(): void {
|
|
3095
3083
|
const start = this.offset;
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
if (kind === INSTANCE_ROUTE_VERSION) {
|
|
3100
|
-
decodeInstanceRouteV1(this.bytes.subarray(start, this.offset), STATEFUL_MESSAGE_CONTEXT);
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
body.rid8('targetNodeRid');
|
|
3104
|
-
body.nonZeroU64('targetNodeGeneration');
|
|
3105
|
-
body.text8('targetSpotId');
|
|
3106
|
-
body.text8('targetMeshName');
|
|
3107
|
-
body.text8('stableType');
|
|
3108
|
-
body.text8('targetDescriptorVersion');
|
|
3109
|
-
body.nonZeroU64('deadlineUnixMs');
|
|
3110
|
-
body.end('Instance route');
|
|
3084
|
+
this.u8('instanceRouteKind');
|
|
3085
|
+
this.body16('Instance route');
|
|
3086
|
+
decodeCanonicalInstanceRoute(this.bytes.subarray(start, this.offset));
|
|
3111
3087
|
}
|
|
3112
3088
|
|
|
3113
3089
|
private relocationObject(): void {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ZLINK_MAX_IDENTITY_TEXT_BYTES } from '../../contracts/Common/CoreTypes';
|
|
2
|
+
import type { ServiceLivenessConnection } from './service-liveness-registry';
|
|
2
3
|
import {
|
|
3
4
|
ZLINK_MAX_PUBLIC_WEIGHT,
|
|
4
5
|
isValidCapacity,
|
|
@@ -43,7 +44,8 @@ export interface AdmittedServicePeer {
|
|
|
43
44
|
readonly descriptor: ServiceNodeDescriptor;
|
|
44
45
|
// The Core selected-route generation this admission belongs to (Core ROUTER
|
|
45
46
|
// §10.1), as an opaque token compared only for equality.
|
|
46
|
-
readonly connectionId: string;
|
|
47
|
+
readonly connectionId: string | bigint;
|
|
48
|
+
readonly liveness?: ServiceLivenessConnection;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export interface ServicePeerAdmissionExpectation {
|
|
@@ -103,12 +105,14 @@ export class ServiceTopologyRegistry {
|
|
|
103
105
|
|
|
104
106
|
admit(
|
|
105
107
|
descriptor: ServiceNodeDescriptor,
|
|
106
|
-
connectionId: string,
|
|
107
|
-
expected?: ServicePeerAdmissionExpectation
|
|
108
|
+
connectionId: string | bigint,
|
|
109
|
+
expected?: ServicePeerAdmissionExpectation,
|
|
110
|
+
admitLiveness?: () => ServiceLivenessConnection
|
|
108
111
|
): PeerAdmissionResult {
|
|
109
112
|
try {
|
|
110
113
|
validateDescriptor(descriptor);
|
|
111
|
-
requireText(connectionId, 'connectionId');
|
|
114
|
+
if (typeof connectionId === 'string') requireText(connectionId, 'connectionId');
|
|
115
|
+
else if (connectionId === 0n) throw new TypeError('connectionId must be nonzero.');
|
|
112
116
|
} catch (error) {
|
|
113
117
|
return 'invalidDescriptor';
|
|
114
118
|
}
|
|
@@ -154,14 +158,15 @@ export class ServiceTopologyRegistry {
|
|
|
154
158
|
// that route replaces the admission of a route it replaced.
|
|
155
159
|
this.peersByRid.set(descriptor.nodeRoutingId, {
|
|
156
160
|
descriptor: cloneDescriptor(descriptor),
|
|
157
|
-
connectionId
|
|
161
|
+
connectionId,
|
|
162
|
+
liveness: admitLiveness?.() ?? current?.liveness
|
|
158
163
|
});
|
|
159
164
|
this.remember(descriptor);
|
|
160
165
|
this.rebuildSelections();
|
|
161
166
|
return 'admitted';
|
|
162
167
|
}
|
|
163
168
|
|
|
164
|
-
disconnect(nodeRoutingId: string, connectionId: string): boolean {
|
|
169
|
+
disconnect(nodeRoutingId: string, connectionId: string | bigint): boolean {
|
|
165
170
|
const current = this.peersByRid.get(nodeRoutingId);
|
|
166
171
|
if (current === undefined || current.connectionId !== connectionId) return false;
|
|
167
172
|
this.peersByRid.delete(nodeRoutingId);
|
|
@@ -525,7 +530,8 @@ function cloneDescriptor(descriptor: ServiceNodeDescriptor): ServiceNodeDescript
|
|
|
525
530
|
function clonePeer(peer: AdmittedServicePeer): AdmittedServicePeer {
|
|
526
531
|
return {
|
|
527
532
|
descriptor: cloneDescriptor(peer.descriptor),
|
|
528
|
-
connectionId: peer.connectionId
|
|
533
|
+
connectionId: peer.connectionId,
|
|
534
|
+
liveness: peer.liveness
|
|
529
535
|
};
|
|
530
536
|
}
|
|
531
537
|
|
|
@@ -212,7 +212,8 @@ class LifecycleHandlerInstanceScope {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
async dispose(detachedTaskRunner: ZLinkDetachedTaskRunner): Promise<void> {
|
|
215
|
-
const disposeFromActiveInvocation =
|
|
215
|
+
const disposeFromActiveInvocation =
|
|
216
|
+
this.activeInvocations > 0 && activeLifecycleScope.getStore() === this;
|
|
216
217
|
const disposal = this.beginDisposeCore();
|
|
217
218
|
if (disposal.deferred !== undefined) {
|
|
218
219
|
startOutsideLifecycleInvocation(() => {
|
|
@@ -303,6 +303,7 @@ export class ZLinkActorPacketRelay {
|
|
|
303
303
|
const dispatch =
|
|
304
304
|
state?.spotId === undefined
|
|
305
305
|
? this.requireSpotNodeRuntime().dispatchEntryActorPacket(
|
|
306
|
+
'remote',
|
|
306
307
|
relay.actorId,
|
|
307
308
|
[header, body],
|
|
308
309
|
false,
|
|
@@ -310,6 +311,7 @@ export class ZLinkActorPacketRelay {
|
|
|
310
311
|
fallbackActorRef
|
|
311
312
|
)
|
|
312
313
|
: this.requireSpotManager().dispatchRoutedActorPacket(
|
|
314
|
+
'remote',
|
|
313
315
|
state.spotId,
|
|
314
316
|
relay.actorId,
|
|
315
317
|
[header, body],
|
|
@@ -356,6 +358,7 @@ export class ZLinkActorPacketRelay {
|
|
|
356
358
|
const dispatch =
|
|
357
359
|
state?.spotId === undefined
|
|
358
360
|
? this.requireSpotNodeRuntime().dispatchEntryActorPacket(
|
|
361
|
+
'remote',
|
|
359
362
|
relay.actorId,
|
|
360
363
|
[header, body],
|
|
361
364
|
false,
|
|
@@ -363,6 +366,7 @@ export class ZLinkActorPacketRelay {
|
|
|
363
366
|
fallbackActorRef
|
|
364
367
|
)
|
|
365
368
|
: this.requireSpotManager().dispatchRoutedActorPacket(
|
|
369
|
+
'remote',
|
|
366
370
|
state.spotId,
|
|
367
371
|
relay.actorId,
|
|
368
372
|
[header, body],
|
|
@@ -423,6 +427,7 @@ export class ZLinkActorPacketRelay {
|
|
|
423
427
|
const response =
|
|
424
428
|
state?.spotId === undefined
|
|
425
429
|
? await this.requireSpotNodeRuntime().dispatchEntryActorPacket(
|
|
430
|
+
'remote',
|
|
426
431
|
relay.actorId,
|
|
427
432
|
[header, body],
|
|
428
433
|
relay.returnResponse === true,
|
|
@@ -430,6 +435,7 @@ export class ZLinkActorPacketRelay {
|
|
|
430
435
|
fallbackActorRef
|
|
431
436
|
)
|
|
432
437
|
: await this.requireSpotManager().dispatchRoutedActorPacket(
|
|
438
|
+
'remote',
|
|
433
439
|
state.spotId,
|
|
434
440
|
relay.actorId,
|
|
435
441
|
[header, body],
|
|
@@ -892,6 +898,7 @@ export class ZLinkActorPacketRelay {
|
|
|
892
898
|
this.options.detachedTaskRunner.runDetached('local actor packet relay', async () => {
|
|
893
899
|
try {
|
|
894
900
|
const response = await this.requireSpotManager().dispatchRoutedActorPacket(
|
|
901
|
+
'local',
|
|
895
902
|
spotId,
|
|
896
903
|
actor.actorId,
|
|
897
904
|
[header, body],
|
|
@@ -11,7 +11,8 @@ import type {
|
|
|
11
11
|
ZLinkAuthoritySnapshot,
|
|
12
12
|
ZLinkCreationOperationIdentity,
|
|
13
13
|
ZLinkLocationOwnerToken,
|
|
14
|
-
ZLinkObjectReserveResult
|
|
14
|
+
ZLinkObjectReserveResult,
|
|
15
|
+
ZLinkObjectReserveRequest
|
|
15
16
|
} from '../locations/internal-location-contracts';
|
|
16
17
|
import type {
|
|
17
18
|
ZLinkAuthorityStore,
|
|
@@ -57,6 +58,10 @@ export interface ZLinkActorPlacementTarget {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
export interface ZLinkActorPlacementCoordinatorOptions {
|
|
61
|
+
readonly actorRelocationPolicy?: (
|
|
62
|
+
meshName: string,
|
|
63
|
+
stableType: string
|
|
64
|
+
) => ZLinkObjectReserveRequest['actorRelocationPolicy'];
|
|
60
65
|
readonly store: ZLinkObjectCreationStore & ZLinkAuthorityStore;
|
|
61
66
|
readonly target: (
|
|
62
67
|
meshName: string | undefined,
|
|
@@ -130,7 +135,8 @@ export class ZLinkActorPlacementCoordinator {
|
|
|
130
135
|
},
|
|
131
136
|
target: reservationTarget(target),
|
|
132
137
|
creatingPayload,
|
|
133
|
-
capacity: { actors: 1, spots: 0 }
|
|
138
|
+
capacity: { actors: 1, spots: 0 },
|
|
139
|
+
actorRelocationPolicy: this.options.actorRelocationPolicy?.(target.meshName, stableType)
|
|
134
140
|
},
|
|
135
141
|
deadline.signal,
|
|
136
142
|
BigInt(deadlineUnixMs)
|
|
@@ -34,6 +34,10 @@ import type { ZLinkRemoteActorPacketTarget } from '../actors';
|
|
|
34
34
|
import type { ZLinkActorJoinRelocation } from '../actors/actor-join-relocation';
|
|
35
35
|
|
|
36
36
|
export interface ZLinkActorRuntimeOptionsFactoryOptions {
|
|
37
|
+
readonly terminateActorActivation: (
|
|
38
|
+
actor: ZLinkActor,
|
|
39
|
+
terminal: () => Promise<void>
|
|
40
|
+
) => Promise<void>;
|
|
37
41
|
readonly registration: ZLinkFrameworkRegistration;
|
|
38
42
|
/** Message flow tracer, so a failed deferred Join records its cause on the flow. */
|
|
39
43
|
readonly messageFlow?: () =>
|
|
@@ -101,6 +105,7 @@ export class ZLinkActorRuntimeOptionsFactory {
|
|
|
101
105
|
| 'actorRefResolver'
|
|
102
106
|
| 'actorCreatedNotifier'
|
|
103
107
|
| 'actorDestroyedCleanup'
|
|
108
|
+
| 'terminateActorActivation'
|
|
104
109
|
| 'publishActorAuthority'
|
|
105
110
|
| 'locationLifecycle'
|
|
106
111
|
| 'boundSessionFactory'
|
|
@@ -111,6 +116,7 @@ export class ZLinkActorRuntimeOptionsFactory {
|
|
|
111
116
|
> {
|
|
112
117
|
const actorTransferRegistry = this.options.actorTransferRegistry;
|
|
113
118
|
return {
|
|
119
|
+
terminateActorActivation: this.options.terminateActorActivation,
|
|
114
120
|
actorMeshNameProvider: this.options.actorMeshName,
|
|
115
121
|
actorLeaveSpot: (meshName, spotId, actor, signal) => {
|
|
116
122
|
const spotManager = this.options.spotManager();
|
|
@@ -274,6 +280,7 @@ export class ZLinkActorRuntimeOptionsFactory {
|
|
|
274
280
|
this.actorBelongsToMesh(meshName, actorId) &&
|
|
275
281
|
!this.options.actorHandoff.isProvisional(actorId)
|
|
276
282
|
? this.options.actorHandoff.capture(
|
|
283
|
+
'local',
|
|
277
284
|
actorId,
|
|
278
285
|
parts,
|
|
279
286
|
returnResponse,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { SeverityNumber } from '@opentelemetry/api-logs';
|
|
2
|
+
import { telemetryLogger } from '../diagnostics/message-flow';
|
|
1
3
|
import { MILLISECONDS_PER_SECOND } from '../diagnostics/runtime-metrics';
|
|
2
4
|
import { ZLinkApplicationJobQueueProfile } from '../../contracts/Dispatch';
|
|
3
5
|
import {
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
import { readFileSync } from 'node:fs';
|
|
12
14
|
import { availableParallelism } from 'node:os';
|
|
13
15
|
import type {
|
|
16
|
+
ApplicationJobOrigin,
|
|
14
17
|
ApplicationJobPermitPort,
|
|
15
18
|
ApplicationJobQueuePort
|
|
16
19
|
} from '../application-jobs/contracts';
|
|
@@ -122,7 +125,10 @@ export function resolveApplicationJobQueueConfiguration(
|
|
|
122
125
|
export class ApplicationJobQueuePermit implements ApplicationJobPermitPort {
|
|
123
126
|
private state: 'reserved' | 'queued' | 'released' = 'reserved';
|
|
124
127
|
|
|
125
|
-
constructor(
|
|
128
|
+
constructor(
|
|
129
|
+
private readonly owner: ApplicationJobQueue,
|
|
130
|
+
readonly origin: ApplicationJobOrigin
|
|
131
|
+
) {}
|
|
126
132
|
|
|
127
133
|
markApplicationQueued(): void {
|
|
128
134
|
if (this.state !== 'reserved') {
|
|
@@ -149,6 +155,7 @@ export class ApplicationJobQueuePermit implements ApplicationJobPermitPort {
|
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
interface CapacityWaiter {
|
|
158
|
+
readonly origin: ApplicationJobOrigin;
|
|
152
159
|
readonly resolve: (permit: ApplicationJobQueuePermit) => void;
|
|
153
160
|
readonly reject: (reason: unknown) => void;
|
|
154
161
|
readonly signal?: AbortSignal;
|
|
@@ -164,6 +171,8 @@ interface CapacityWaiter {
|
|
|
164
171
|
* directly to the oldest live waiter without allocating the configured limit.
|
|
165
172
|
*/
|
|
166
173
|
export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
174
|
+
private localWaiters = 0;
|
|
175
|
+
private localBacklogLogged = false;
|
|
167
176
|
private reservedSupplyPermits = 0n;
|
|
168
177
|
private queuedApplicationJobs = 0n;
|
|
169
178
|
private peakPermitsInUse = 0n;
|
|
@@ -191,7 +200,8 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
191
200
|
constructor(
|
|
192
201
|
private readonly configuration: ApplicationJobQueueConfiguration,
|
|
193
202
|
private readonly nowMs: () => number = () => performance.now(),
|
|
194
|
-
private readonly handlerStartGate?: () => boolean
|
|
203
|
+
private readonly handlerStartGate?: () => boolean,
|
|
204
|
+
private readonly loggerFailureReporter?: (error: unknown) => void
|
|
195
205
|
) {
|
|
196
206
|
this.receiveFlowController = new ApplicationJobReceiveFlowController(this, (state) => state);
|
|
197
207
|
}
|
|
@@ -242,16 +252,33 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
242
252
|
this.receiveFlowController.unregister(target);
|
|
243
253
|
}
|
|
244
254
|
|
|
245
|
-
acquire(
|
|
255
|
+
acquire(
|
|
256
|
+
signal: AbortSignal | undefined,
|
|
257
|
+
origin: ApplicationJobOrigin
|
|
258
|
+
): Promise<ApplicationJobQueuePermit> {
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
const permit = this.acquireOrResume(resolve, reject, signal, origin);
|
|
261
|
+
if (permit !== undefined) resolve(permit);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
acquireOrResume(
|
|
266
|
+
resume: (permit: ApplicationJobQueuePermit) => void,
|
|
267
|
+
reject: (reason: unknown) => void,
|
|
268
|
+
signal: AbortSignal | undefined,
|
|
269
|
+
origin: ApplicationJobOrigin
|
|
270
|
+
): ApplicationJobQueuePermit | undefined {
|
|
246
271
|
if (signal?.aborted === true) {
|
|
247
|
-
|
|
272
|
+
reject(abortReason(signal));
|
|
273
|
+
return undefined;
|
|
248
274
|
}
|
|
249
275
|
if (this.waiters.length === 0 && this.permitsInUse() < this.limit()) {
|
|
250
|
-
return
|
|
276
|
+
return this.reserve(origin);
|
|
251
277
|
}
|
|
252
278
|
|
|
253
|
-
|
|
279
|
+
new Promise<ApplicationJobQueuePermit>((resolve, reject) => {
|
|
254
280
|
const waiter: CapacityWaiter = {
|
|
281
|
+
origin,
|
|
255
282
|
resolve,
|
|
256
283
|
reject,
|
|
257
284
|
signal,
|
|
@@ -262,9 +289,14 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
262
289
|
};
|
|
263
290
|
this.waiters.push(waiter);
|
|
264
291
|
this.capacityWaitCount += 1n;
|
|
292
|
+
const warningCount = this.updateLocalWaiters(origin, 1);
|
|
265
293
|
signal?.addEventListener('abort', waiter.abort, { once: true });
|
|
266
294
|
this.drainWaiters();
|
|
267
|
-
|
|
295
|
+
if (warningCount !== undefined) this.logLocalBacklog(warningCount);
|
|
296
|
+
})
|
|
297
|
+
.then(resume)
|
|
298
|
+
.catch(reject);
|
|
299
|
+
return undefined;
|
|
268
300
|
}
|
|
269
301
|
|
|
270
302
|
snapshot(): ApplicationJobQueueSnapshot {
|
|
@@ -356,12 +388,15 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
356
388
|
return this.reservedSupplyPermits + this.queuedApplicationJobs;
|
|
357
389
|
}
|
|
358
390
|
|
|
359
|
-
private reserve(
|
|
391
|
+
private reserve(
|
|
392
|
+
origin: ApplicationJobOrigin,
|
|
393
|
+
evaluatePressure = true
|
|
394
|
+
): ApplicationJobQueuePermit {
|
|
360
395
|
this.reservedSupplyPermits += 1n;
|
|
361
396
|
const current = this.permitsInUse();
|
|
362
397
|
if (current > this.peakPermitsInUse) this.peakPermitsInUse = current;
|
|
363
398
|
if (evaluatePressure) this.evaluatePressure();
|
|
364
|
-
return new ApplicationJobQueuePermit(this);
|
|
399
|
+
return new ApplicationJobQueuePermit(this, origin);
|
|
365
400
|
}
|
|
366
401
|
|
|
367
402
|
private drainWaiters(): void {
|
|
@@ -371,7 +406,7 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
371
406
|
waiter.active = false;
|
|
372
407
|
waiter.signal?.removeEventListener('abort', waiter.abort);
|
|
373
408
|
this.recordCompletedWait(waiter);
|
|
374
|
-
waiter.resolve(this.reserve(false));
|
|
409
|
+
waiter.resolve(this.reserve(waiter.origin, false));
|
|
375
410
|
}
|
|
376
411
|
}
|
|
377
412
|
|
|
@@ -387,11 +422,43 @@ export class ApplicationJobQueue implements ApplicationJobQueuePort {
|
|
|
387
422
|
}
|
|
388
423
|
|
|
389
424
|
private recordCompletedWait(waiter: CapacityWaiter): void {
|
|
425
|
+
this.updateLocalWaiters(waiter.origin, -1);
|
|
390
426
|
if (waiter.metricsEpoch !== this.metricsEpoch) return;
|
|
391
427
|
const durationMs = Math.max(0, this.nowMs() - waiter.startedAtMs);
|
|
392
428
|
this.capacityWaitDurationSeconds += durationMs / MILLISECONDS_PER_SECOND;
|
|
393
429
|
}
|
|
394
430
|
|
|
431
|
+
private updateLocalWaiters(origin: ApplicationJobOrigin, delta: number): number | undefined {
|
|
432
|
+
if (origin !== 'local') return undefined;
|
|
433
|
+
this.localWaiters += delta;
|
|
434
|
+
if (this.localWaiters === 0) this.localBacklogLogged = false;
|
|
435
|
+
if (!this.localBacklogLogged && this.localWaiters > Number(this.limit())) {
|
|
436
|
+
this.localBacklogLogged = true;
|
|
437
|
+
return this.localWaiters;
|
|
438
|
+
}
|
|
439
|
+
return undefined;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private logLocalBacklog(localWaiters: number): void {
|
|
443
|
+
try {
|
|
444
|
+
telemetryLogger.emit({
|
|
445
|
+
eventName: 'zlink.runtime.host.local_job_backlog_exceeded',
|
|
446
|
+
timestamp: new Date(),
|
|
447
|
+
severityNumber: SeverityNumber.WARN,
|
|
448
|
+
severityText: 'WARN',
|
|
449
|
+
body: 'Same-host jobs waiting for a host permit exceeded the application job queue maximum.',
|
|
450
|
+
attributes: {
|
|
451
|
+
source_kind: 'host',
|
|
452
|
+
source_name: 'zlink.runtime.host',
|
|
453
|
+
local_waiters: localWaiters,
|
|
454
|
+
effective_maximum: Number(this.limit())
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
} catch (error) {
|
|
458
|
+
this.loggerFailureReporter?.(error);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
395
462
|
private evaluatePressure(): void {
|
|
396
463
|
const permitsInUse = this.permitsInUse();
|
|
397
464
|
const next =
|