@zlink-systems/framework 0.30.1 → 0.30.2
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/Common/ZLinkEncodedPayload.d.ts +6 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
- package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
- package/dist/contracts/Common/encoded-payload-storage.js +5 -2
- package/dist/contracts/Configuration/Builders.d.ts +1 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
- package/dist/contracts/Locations/Rows.d.ts +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +4 -0
- package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
- package/dist/runtime/abort.d.ts +5 -0
- package/dist/runtime/abort.js +10 -0
- package/dist/runtime/actors/actor-authority-publication.js +3 -2
- package/dist/runtime/actors/actor-client.d.ts +0 -1
- package/dist/runtime/actors/actor-client.js +38 -45
- package/dist/runtime/actors/actor-context.d.ts +2 -0
- package/dist/runtime/actors/actor-context.js +46 -9
- package/dist/runtime/actors/actor-handoff.d.ts +7 -3
- package/dist/runtime/actors/actor-handoff.js +212 -88
- package/dist/runtime/actors/actor-join-relocation.d.ts +2 -0
- package/dist/runtime/actors/actor-local-native-join.js +4 -0
- package/dist/runtime/actors/actor-mailbox.js +27 -1
- package/dist/runtime/actors/actor-remote-joiner.js +3 -1
- package/dist/runtime/actors/actor-reply.d.ts +4 -0
- package/dist/runtime/actors/actor-reply.js +29 -0
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
- package/dist/runtime/actors/actor-runtime-state.js +2 -20
- package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
- package/dist/runtime/actors/index.d.ts +6 -2
- package/dist/runtime/actors/index.js +37 -21
- package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
- package/dist/runtime/actors/session-disconnected-wire.js +48 -0
- package/dist/runtime/admission.d.ts +9 -1
- package/dist/runtime/admission.js +55 -32
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +13 -0
- package/dist/runtime/application-jobs/application-job-queue-scope.js +27 -1
- package/dist/runtime/application-jobs/contracts.d.ts +2 -0
- package/dist/runtime/backend/contracts/index.d.ts +19 -3
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
- package/dist/runtime/backend/mesh-completion-table.js +5 -0
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +26 -2
- package/dist/runtime/backend/mesh-dispatch-pump.js +193 -107
- package/dist/runtime/backend/node/node-raw-binding-port.js +90 -58
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +33 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +142 -143
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +5 -5
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +20 -5
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +22 -3
- package/dist/runtime/channels/channel-dispatch-pipeline.js +103 -57
- package/dist/runtime/channels/channel-dispatchers.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatchers.js +44 -37
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +74 -31
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
- package/dist/runtime/channels/channel-runtime-manager.d.ts +3 -2
- package/dist/runtime/channels/channel-runtime-manager.js +4 -4
- package/dist/runtime/channels/channel-transports.d.ts +0 -1
- package/dist/runtime/channels/channel-transports.js +35 -33
- package/dist/runtime/channels/client-server-location-runtime.js +5 -4
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/fanout-location-runtime.js +3 -3
- package/dist/runtime/diagnostics/flow-context.js +19 -7
- package/dist/runtime/diagnostics/index.js +4 -9
- package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
- package/dist/runtime/diagnostics/message-flow.js +35 -5
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
- package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
- package/dist/runtime/execution/index.d.ts +4 -2
- package/dist/runtime/execution/index.js +33 -10
- package/dist/runtime/execution/serial-execution-queue.d.ts +4 -0
- package/dist/runtime/execution/serial-execution-queue.js +21 -2
- package/dist/runtime/execution/state-lane.d.ts +2 -0
- package/dist/runtime/execution/state-lane.js +5 -0
- package/dist/runtime/foundation/operation-registry.d.ts +25 -1
- package/dist/runtime/foundation/operation-registry.js +86 -18
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +39 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +151 -55
- package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
- package/dist/runtime/foundation/service-liveness-registry.js +38 -0
- package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -3
- package/dist/runtime/foundation/service-relocation-object-owner.js +48 -35
- package/dist/runtime/foundation/service-relocation-runtime.js +7 -3
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +8 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
- package/dist/runtime/foundation/service-stateful-registry.js +24 -26
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +72 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +444 -117
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -1
- package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
- package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +10 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +166 -53
- package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
- package/dist/runtime/host/actor-packet-relay.js +59 -72
- package/dist/runtime/host/actor-placement-coordinator.js +25 -8
- package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
- package/dist/runtime/host/actor-transfer-runtime.js +85 -331
- package/dist/runtime/host/application-job-queue.d.ts +24 -3
- package/dist/runtime/host/application-job-queue.js +28 -41
- package/dist/runtime/host/index.d.ts +5 -1
- package/dist/runtime/host/index.js +171 -97
- package/dist/runtime/host/location-runtime-owner.js +2 -6
- package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
- package/dist/runtime/host/mesh-router-resolver.js +14 -6
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
- package/dist/runtime/host/remote-bound-session-relay.js +71 -190
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
- package/dist/runtime/host/route-mesh-runtime.js +5 -3
- package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
- package/dist/runtime/host/runtime-shutdown.js +3 -2
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +17 -7
- package/dist/runtime/host/service-relocation-host-runtime.js +550 -367
- package/dist/runtime/host/spot-runtime-options-factory.js +15 -7
- package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
- package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
- package/dist/runtime/locations/auto-connect-loop.js +22 -14
- package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
- package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
- package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
- package/dist/runtime/locations/descriptor-publication.js +11 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
- package/dist/runtime/locations/in-memory-authority-store.js +56 -19
- package/dist/runtime/locations/in-memory-location-store.js +1 -10
- package/dist/runtime/locations/index.d.ts +1 -0
- package/dist/runtime/locations/index.js +1 -0
- package/dist/runtime/locations/lease-tracker.js +1 -6
- package/dist/runtime/locations/location-store-repository.d.ts +51 -1
- package/dist/runtime/locations/location-store-repository.js +363 -139
- package/dist/runtime/locations/relocation-blob.d.ts +18 -1
- package/dist/runtime/locations/relocation-blob.js +52 -1
- package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
- package/dist/runtime/locations/request-source-resolver.js +80 -0
- package/dist/runtime/locations/resolvers.js +1 -1
- package/dist/runtime/locations/runtime.d.ts +6 -2
- package/dist/runtime/locations/runtime.js +37 -30
- package/dist/runtime/messaging/payload-codec.d.ts +7 -1
- package/dist/runtime/messaging/payload-codec.js +7 -6
- package/dist/runtime/messaging/request-result.js +29 -26
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +19 -1
- package/dist/runtime/protocol/service_wire_codec.generated.js +85 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +7 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +23 -7
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +3 -2
- package/dist/runtime/spots/index.d.ts +18 -11
- package/dist/runtime/spots/index.js +234 -176
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
- package/dist/runtime/spots/spot-activation-registry.js +21 -11
- package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
- package/dist/runtime/spots/spot-activation-state.js +7 -7
- package/dist/runtime/spots/spot-activation.d.ts +6 -3
- package/dist/runtime/spots/spot-activation.js +123 -44
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
- package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-membership.js +0 -8
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
- package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
- package/dist/runtime/spots/spot-entry-activation.js +14 -9
- package/dist/runtime/spots/spot-handler-registry.d.ts +4 -3
- package/dist/runtime/spots/spot-handler-registry.js +6 -2
- package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
- package/dist/runtime/spots/spot-manager-public.js +2 -2
- package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
- package/dist/runtime/spots/spot-node-autoconnect.js +18 -39
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
- package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
- package/dist/runtime/spots/spot-outbound.js +3 -3
- package/dist/runtime/spots/spot-remote-codec.js +5 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +0 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
- package/dist/runtime/spots/spot-serial-executor.js +61 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
- package/dist/runtime/spots/spot-subscription-dispatch.js +1 -1
- package/dist/runtime/spots/spot-timer.d.ts +57 -5
- package/dist/runtime/spots/spot-timer.js +287 -103
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
- package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
- package/dist/runtime/streams/bound-session-service.d.ts +1 -1
- package/dist/runtime/streams/bound-session-service.js +6 -11
- package/dist/runtime/streams/index.d.ts +3 -2
- package/dist/runtime/streams/index.js +6 -4
- package/dist/runtime/streams/managed-stream.js +3 -2
- package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
- package/dist/runtime/streams/session-actor-coordinator.js +15 -32
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
- package/dist/runtime/streams/stream-session-runtime.js +1 -4
- package/dist/runtime/workers/index.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
- package/src/contracts/Common/encoded-payload-storage.ts +6 -3
- package/src/contracts/Configuration/Builders.ts +4 -1
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
- package/src/contracts/Locations/Rows.ts +2 -0
- package/src/contracts/Spots/Contracts.ts +8 -0
- package/src/contracts/Spots/ZLinkSpot.ts +3 -3
- package/src/runtime/abort.ts +12 -0
- package/src/runtime/actors/actor-authority-publication.ts +3 -2
- package/src/runtime/actors/actor-client.ts +61 -70
- package/src/runtime/actors/actor-context.ts +49 -9
- package/src/runtime/actors/actor-handoff.ts +282 -106
- package/src/runtime/actors/actor-join-relocation.ts +2 -0
- package/src/runtime/actors/actor-local-native-join.ts +4 -0
- package/src/runtime/actors/actor-mailbox.ts +40 -2
- package/src/runtime/actors/actor-remote-joiner.ts +6 -1
- package/src/runtime/actors/actor-reply.ts +42 -0
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
- package/src/runtime/actors/actor-runtime-state.ts +2 -20
- package/src/runtime/actors/actor-source-transfer.ts +1 -34
- package/src/runtime/actors/index.ts +41 -27
- package/src/runtime/actors/session-disconnected-wire.ts +66 -0
- package/src/runtime/admission.ts +69 -34
- package/src/runtime/application-jobs/application-job-queue-scope.ts +33 -1
- package/src/runtime/application-jobs/contracts.ts +2 -0
- package/src/runtime/backend/contracts/index.ts +39 -4
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
- package/src/runtime/backend/mesh-completion-table.ts +4 -0
- package/src/runtime/backend/mesh-dispatch-pump.ts +223 -124
- package/src/runtime/backend/node/node-raw-binding-port.ts +106 -70
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +221 -170
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -5
- package/src/runtime/channels/channel-clients.ts +49 -24
- package/src/runtime/channels/channel-dispatch-pipeline.ts +173 -124
- package/src/runtime/channels/channel-dispatchers.ts +116 -72
- package/src/runtime/channels/channel-envelope.ts +105 -36
- package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
- package/src/runtime/channels/channel-runtime-manager.ts +12 -5
- package/src/runtime/channels/channel-transports.ts +49 -58
- package/src/runtime/channels/client-server-location-runtime.ts +11 -10
- package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
- package/src/runtime/channels/fanout-location-runtime.ts +17 -9
- package/src/runtime/diagnostics/flow-context.ts +20 -7
- package/src/runtime/diagnostics/index.ts +1 -7
- package/src/runtime/diagnostics/message-flow.ts +47 -9
- package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
- package/src/runtime/execution/index.ts +40 -14
- package/src/runtime/execution/serial-execution-queue.ts +31 -4
- package/src/runtime/execution/state-lane.ts +7 -0
- package/src/runtime/foundation/operation-registry.ts +98 -20
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +244 -67
- package/src/runtime/foundation/service-liveness-registry.ts +39 -0
- package/src/runtime/foundation/service-mailbox.ts +8 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
- package/src/runtime/foundation/service-relocation-object-owner.ts +54 -37
- package/src/runtime/foundation/service-relocation-runtime.ts +7 -3
- package/src/runtime/foundation/service-runtime-contracts.ts +12 -1
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +38 -35
- package/src/runtime/foundation/service-stateful-runtime.ts +667 -152
- package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -11
- package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +187 -51
- package/src/runtime/host/actor-packet-relay.ts +113 -94
- package/src/runtime/host/actor-placement-coordinator.ts +31 -8
- package/src/runtime/host/actor-transfer-runtime.ts +104 -430
- package/src/runtime/host/application-job-queue.ts +29 -44
- package/src/runtime/host/index.ts +286 -129
- package/src/runtime/host/location-runtime-owner.ts +2 -6
- package/src/runtime/host/mesh-router-resolver.ts +13 -5
- package/src/runtime/host/remote-bound-session-relay.ts +86 -248
- package/src/runtime/host/route-mesh-runtime.ts +11 -5
- package/src/runtime/host/runtime-shutdown.ts +15 -4
- package/src/runtime/host/service-relocation-host-runtime.ts +784 -475
- package/src/runtime/host/spot-runtime-options-factory.ts +18 -7
- package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
- package/src/runtime/locations/auto-connect-loop.ts +22 -14
- package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
- package/src/runtime/locations/auto-connect-types.ts +0 -1
- package/src/runtime/locations/descriptor-publication.ts +7 -0
- package/src/runtime/locations/domain-store-contract.ts +5 -0
- package/src/runtime/locations/in-memory-authority-store.ts +85 -23
- package/src/runtime/locations/in-memory-location-store.ts +1 -12
- package/src/runtime/locations/index.ts +1 -0
- package/src/runtime/locations/lease-tracker.ts +2 -9
- package/src/runtime/locations/location-store-repository.ts +628 -152
- package/src/runtime/locations/relocation-blob.ts +75 -1
- package/src/runtime/locations/request-source-resolver.ts +138 -0
- package/src/runtime/locations/resolvers.ts +2 -2
- package/src/runtime/locations/runtime.ts +70 -40
- package/src/runtime/messaging/payload-codec.ts +8 -11
- package/src/runtime/messaging/request-result.ts +33 -29
- package/src/runtime/protocol/service_wire_codec.generated.ts +87 -4
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +13 -10
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +3 -2
- package/src/runtime/spots/index.ts +375 -281
- package/src/runtime/spots/spot-activation-registry.ts +25 -13
- package/src/runtime/spots/spot-activation-state.ts +12 -19
- package/src/runtime/spots/spot-activation.ts +170 -86
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
- package/src/runtime/spots/spot-actor-membership.ts +0 -15
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
- package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
- package/src/runtime/spots/spot-entry-activation.ts +24 -19
- package/src/runtime/spots/spot-handler-registry.ts +15 -4
- package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
- package/src/runtime/spots/spot-manager-public.ts +2 -2
- package/src/runtime/spots/spot-node-autoconnect.ts +22 -45
- package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
- package/src/runtime/spots/spot-outbound.ts +3 -3
- package/src/runtime/spots/spot-remote-codec.ts +9 -2
- package/src/runtime/spots/spot-runtime-ports.ts +0 -1
- package/src/runtime/spots/spot-serial-executor.ts +97 -25
- package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
- package/src/runtime/spots/spot-subscription-dispatch.ts +1 -1
- package/src/runtime/spots/spot-timer.ts +413 -157
- package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
- package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
- package/src/runtime/streams/bound-session-service.ts +7 -10
- package/src/runtime/streams/index.ts +12 -6
- package/src/runtime/streams/managed-stream.ts +4 -2
- package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
- package/src/runtime/streams/session-actor-coordinator.ts +39 -88
- package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
- package/src/runtime/streams/stream-session-runtime.ts +1 -5
- package/src/runtime/workers/index.ts +1 -1
|
@@ -27,6 +27,12 @@ export interface ZLinkTimerRelocationState {
|
|
|
27
27
|
readonly nextDueAtUnixMs: number;
|
|
28
28
|
readonly pendingTicks: readonly ZLinkTimerRelocationPendingTick[];
|
|
29
29
|
}
|
|
30
|
+
export interface ZLinkManagedTimerStart {
|
|
31
|
+
/** Created paused; the owner starts it with `resume()`. */
|
|
32
|
+
readonly paused?: boolean;
|
|
33
|
+
/** Relocated logical schedule the timer continues from. */
|
|
34
|
+
readonly cursor?: ZLinkTimerRelocationState;
|
|
35
|
+
}
|
|
30
36
|
export interface ZLinkTimerRelocationPendingTick {
|
|
31
37
|
readonly deliveryIndex: bigint;
|
|
32
38
|
readonly scheduledIndex: bigint;
|
|
@@ -44,23 +50,58 @@ export declare class ZLinkSpotTimerRegistry {
|
|
|
44
50
|
private readonly timers;
|
|
45
51
|
private readonly generations;
|
|
46
52
|
private executionBarrier;
|
|
53
|
+
/** Frozen from the source capture or the target restore until abort or Ready. */
|
|
54
|
+
private frozen;
|
|
55
|
+
/**
|
|
56
|
+
* The lifecycle owner opens this window around the target's Configure and
|
|
57
|
+
* pre-Ready OnInitialize only (Spot timer §1). A registration captures it at
|
|
58
|
+
* the call, so a registration started inside the window reattaches a
|
|
59
|
+
* restored key even when its asynchronous part finishes after the window.
|
|
60
|
+
*/
|
|
61
|
+
private initializing;
|
|
62
|
+
/**
|
|
63
|
+
* Handler constructors the target Spot announced with `addTimer(...)` during
|
|
64
|
+
* Configure. Together with `handlers.addTimerHandler(...)` they form the
|
|
65
|
+
* table that resolves a restored timer's handler by name.
|
|
66
|
+
*/
|
|
67
|
+
private readonly configureTimerHandlers;
|
|
68
|
+
private relocationHandlersResolved;
|
|
47
69
|
constructor(_metrics?: import('../diagnostics').ZLinkRuntimeMetrics, flowCreationEnabled?: () => boolean, executionSerialForTimer?: ((name: string, fallback: ZLinkSpotSerialTurnExecutor) => ZLinkSpotSerialTurnExecutor) | undefined, executionAllowed?: () => boolean, executeTimer?: (<T>(name: string, operation: () => Promise<T> | T) => Promise<T>) | undefined, isTimerExecuting?: ((name: string) => boolean) | undefined, clock?: ZLinkTimerClock | undefined);
|
|
48
70
|
setExecutionBarrier(barrier: ZLinkExecutionBarrier): void;
|
|
49
71
|
get hasActiveTimers(): boolean;
|
|
50
72
|
add<TSpot extends ZLinkTimerOwnerSpot, THandler extends ZLinkSpotTimerHandler<TSpot>>(name: string, periodMs: number, options: ZLinkTimerOptions | undefined, handlerType: Type<THandler>, serial: ZLinkSpotSerialTurnExecutor, spot: TSpot, providerResolver?: ZLinkProviderResolver, signal?: AbortSignal, reportFailure?: ZLinkTimerFailureReporter): Promise<ZLinkTimer>;
|
|
73
|
+
/**
|
|
74
|
+
* Stages the source payload on a fresh relocation target before Configure.
|
|
75
|
+
* The restored registrations keep their schedule and stay frozen until Ready.
|
|
76
|
+
*/
|
|
77
|
+
stageRelocation(states: readonly ZLinkTimerRelocationState[]): void;
|
|
78
|
+
/** Runs one relocation-target initialization callback inside the reattach window. */
|
|
79
|
+
runRelocationInitialization<T>(operation: () => Promise<T> | T): Promise<T>;
|
|
80
|
+
/**
|
|
81
|
+
* After Configure, resolves every restored timer's handler constructor by
|
|
82
|
+
* name among the constructors the Spot announced in Configure: `addTimer(...)`
|
|
83
|
+
* there or `handlers.addTimerHandler(...)`. A restored key that Configure did
|
|
84
|
+
* not reattach is registered with the resolved constructor so it survives
|
|
85
|
+
* Ready without re-registration. No match or more than one match fails the
|
|
86
|
+
* target restore.
|
|
87
|
+
*/
|
|
88
|
+
resolveRelocationHandlers(declared: readonly Type[], register: (name: string, periodMs: number, handlerType: Type) => Promise<unknown>): Promise<void>;
|
|
89
|
+
/** Ready: starts the restored and newly registered timers. */
|
|
90
|
+
publishRelocation(): Promise<void>;
|
|
51
91
|
dispose(): Promise<void>;
|
|
52
92
|
captureRelocation(): Promise<readonly ZLinkTimerRelocationState[]>;
|
|
53
|
-
|
|
54
|
-
abortRelocation(
|
|
93
|
+
/** Source abort: the captured timers continue from their own unchanged cursor. */
|
|
94
|
+
abortRelocation(): void;
|
|
55
95
|
commitRelocation(): Promise<void>;
|
|
56
96
|
cancel(name: string, generation: bigint, timer: ZLinkManagedTimer, signal?: AbortSignal): Promise<void>;
|
|
97
|
+
private createTimer;
|
|
57
98
|
private prepareAddCore;
|
|
58
99
|
private completeAddCore;
|
|
59
100
|
private cancelCore;
|
|
60
101
|
}
|
|
61
102
|
export declare class ZLinkManagedTimer implements ZLinkTimer {
|
|
62
103
|
private readonly name;
|
|
63
|
-
|
|
104
|
+
readonly periodMs: number;
|
|
64
105
|
private readonly options;
|
|
65
106
|
private readonly onTick;
|
|
66
107
|
private readonly onFailure?;
|
|
@@ -71,24 +112,35 @@ export declare class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
71
112
|
private pausedForRelocation;
|
|
72
113
|
private startedAtMs;
|
|
73
114
|
private startedAtUnixMs;
|
|
115
|
+
/** DeliveryIndex and ScheduledIndex of the last completed tick. */
|
|
74
116
|
private deliveryIndex;
|
|
75
117
|
private lastScheduledIndex;
|
|
118
|
+
/**
|
|
119
|
+
* The selected tick whose callback has not completed (Spot timer §1). It is
|
|
120
|
+
* the only pending tick a relocation captures, and a restored timer delivers
|
|
121
|
+
* it before it selects another tick.
|
|
122
|
+
*/
|
|
123
|
+
private pendingScheduledIndex;
|
|
76
124
|
private timeout;
|
|
125
|
+
/** The dispatch in flight, from its timer callback until `completeFireCore`. */
|
|
77
126
|
private running;
|
|
78
127
|
private dispatchFailure;
|
|
79
128
|
private finalization;
|
|
80
|
-
constructor(name: string, periodMs: number, options: Required<ZLinkTimerOptions>, onTick: (tick: ZLinkTimerTick) => Promise<void>, onFailure?: ZLinkTimerFailureReporter | undefined, shouldWaitForRunningOnCancel?: () => boolean, clock?: ZLinkTimerClock);
|
|
129
|
+
constructor(name: string, periodMs: number, options: Required<ZLinkTimerOptions>, onTick: (tick: ZLinkTimerTick) => Promise<void>, onFailure?: ZLinkTimerFailureReporter | undefined, shouldWaitForRunningOnCancel?: () => boolean, clock?: ZLinkTimerClock, start?: ZLinkManagedTimerStart);
|
|
81
130
|
get isDisposed(): boolean;
|
|
82
131
|
cancel(_signal?: AbortSignal): Promise<void>;
|
|
83
132
|
dispose(): Promise<void>;
|
|
84
133
|
captureRelocation(handlerType?: string): Promise<ZLinkTimerRelocationState>;
|
|
85
|
-
|
|
134
|
+
/** Starts a timer created paused, or continues one paused by a relocation capture. */
|
|
135
|
+
resume(): void;
|
|
86
136
|
private scheduleNext;
|
|
87
137
|
private fire;
|
|
88
138
|
private cancelCore;
|
|
89
139
|
private completeFinalization;
|
|
90
140
|
private prepareCaptureCore;
|
|
91
141
|
private prepareFireCore;
|
|
142
|
+
/** The tick info of the pending tick at `scheduledIndex` after the completed cursor. */
|
|
143
|
+
private pendingTick;
|
|
92
144
|
private completeFireCore;
|
|
93
145
|
private selectScheduledIndex;
|
|
94
146
|
private elapsedMs;
|
|
@@ -8,11 +8,10 @@ const internal_event_contracts_1 = require("../diagnostics/internal-event-contra
|
|
|
8
8
|
const contracts_1 = require("../../contracts");
|
|
9
9
|
const TimerRegistrationValidator_1 = require("../../contracts/Configuration/TimerRegistrationValidator");
|
|
10
10
|
const abort_1 = require("../abort");
|
|
11
|
+
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
11
12
|
const handler_instance_scope_1 = require("../handlers/handler-instance-scope");
|
|
12
13
|
const flow_context_1 = require("../diagnostics/flow-context");
|
|
13
14
|
const state_lane_1 = require("../execution/state-lane");
|
|
14
|
-
const node_async_hooks_1 = require("node:async_hooks");
|
|
15
|
-
const detachedTimerStateLaneResource = new node_async_hooks_1.AsyncResource('zlink:spot-timer');
|
|
16
15
|
const systemTimerClock = {
|
|
17
16
|
now: () => performance.now(),
|
|
18
17
|
utcNow: () => Date.now(),
|
|
@@ -30,6 +29,22 @@ class ZLinkSpotTimerRegistry {
|
|
|
30
29
|
timers = new Map();
|
|
31
30
|
generations = new Map();
|
|
32
31
|
executionBarrier;
|
|
32
|
+
/** Frozen from the source capture or the target restore until abort or Ready. */
|
|
33
|
+
frozen = false;
|
|
34
|
+
/**
|
|
35
|
+
* The lifecycle owner opens this window around the target's Configure and
|
|
36
|
+
* pre-Ready OnInitialize only (Spot timer §1). A registration captures it at
|
|
37
|
+
* the call, so a registration started inside the window reattaches a
|
|
38
|
+
* restored key even when its asynchronous part finishes after the window.
|
|
39
|
+
*/
|
|
40
|
+
initializing = false;
|
|
41
|
+
/**
|
|
42
|
+
* Handler constructors the target Spot announced with `addTimer(...)` during
|
|
43
|
+
* Configure. Together with `handlers.addTimerHandler(...)` they form the
|
|
44
|
+
* table that resolves a restored timer's handler by name.
|
|
45
|
+
*/
|
|
46
|
+
configureTimerHandlers = new Set();
|
|
47
|
+
relocationHandlersResolved = false;
|
|
33
48
|
constructor(_metrics, flowCreationEnabled = () => true, executionSerialForTimer, executionAllowed = () => true, executeTimer, isTimerExecuting, clock) {
|
|
34
49
|
this.flowCreationEnabled = flowCreationEnabled;
|
|
35
50
|
this.executionSerialForTimer = executionSerialForTimer;
|
|
@@ -49,44 +64,135 @@ class ZLinkSpotTimerRegistry {
|
|
|
49
64
|
}
|
|
50
65
|
async add(name, periodMs, options, handlerType, serial, spot, providerResolver, signal, reportFailure) {
|
|
51
66
|
(0, TimerRegistrationValidator_1.validateTimerRegistration)(name, periodMs, options);
|
|
67
|
+
const initializing = this.initializing;
|
|
68
|
+
if (initializing && !this.relocationHandlersResolved) {
|
|
69
|
+
this.configureTimerHandlers.add(handlerType);
|
|
70
|
+
}
|
|
52
71
|
(0, abort_1.throwIfAborted)(signal);
|
|
53
72
|
(0, handler_instance_scope_1.prepareHandlerInstance)(providerResolver, handlerType);
|
|
54
73
|
const handler = await (0, handler_instance_scope_1.resolveLifecycleHandler)(spot, handlerType, providerResolver);
|
|
55
|
-
const prepared = await this.lane.run(() => this.prepareAddCore(name));
|
|
56
|
-
if (prepared.previous !== undefined)
|
|
57
|
-
await prepared.previous.timer.cancel(signal);
|
|
58
74
|
const executionSerial = this.executeTimer === undefined
|
|
59
75
|
? (this.executionSerialForTimer?.(name, serial) ?? serial)
|
|
60
76
|
: undefined;
|
|
61
77
|
if (this.executionBarrier !== undefined)
|
|
62
78
|
executionSerial?.setExecutionBarrier(this.executionBarrier);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const binding = {
|
|
80
|
+
handler: handler,
|
|
81
|
+
spot,
|
|
82
|
+
executionSerial,
|
|
83
|
+
reportFailure
|
|
84
|
+
};
|
|
85
|
+
const prepared = await this.lane.run(() => this.prepareAddCore(name, handlerType.name, initializing, binding));
|
|
86
|
+
if (prepared.kind === 'reattached')
|
|
87
|
+
return prepared.handle;
|
|
88
|
+
if (prepared.previous !== undefined)
|
|
89
|
+
await prepared.previous.timer.cancel(signal);
|
|
90
|
+
const slot = { binding };
|
|
91
|
+
const timer = this.createTimer(name, prepared.generation, periodMs, options, slot);
|
|
92
|
+
const handle = new ZLinkRegisteredTimer(this, name, prepared.generation, timer);
|
|
93
|
+
const registered = await this.lane.run(() => this.completeAddCore(name, {
|
|
94
|
+
generation: prepared.generation,
|
|
95
|
+
handlerType: handlerType.name,
|
|
96
|
+
timer,
|
|
97
|
+
handle,
|
|
98
|
+
restored: false,
|
|
99
|
+
slot
|
|
100
|
+
}));
|
|
101
|
+
if (!registered)
|
|
102
|
+
await timer.cancel(signal);
|
|
103
|
+
return handle;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stages the source payload on a fresh relocation target before Configure.
|
|
107
|
+
* The restored registrations keep their schedule and stay frozen until Ready.
|
|
108
|
+
*/
|
|
109
|
+
stageRelocation(states) {
|
|
110
|
+
if (this.frozen || this.timers.size !== 0) {
|
|
111
|
+
throw new Error('Timer relocation can only be restored into a fresh registry.');
|
|
112
|
+
}
|
|
113
|
+
const restored = states.map((state) => {
|
|
114
|
+
if (states.some((other) => other !== state && other.name === state.name)) {
|
|
115
|
+
throw new Error(`Timer '${state.name}' appears twice in relocation state.`);
|
|
116
|
+
}
|
|
117
|
+
const options = {
|
|
118
|
+
overrunPolicy: state.overrunPolicy,
|
|
119
|
+
maxCatchUpTicks: state.maxCatchUpTicks,
|
|
120
|
+
stopOnUnhandledException: state.stopOnUnhandledException
|
|
78
121
|
};
|
|
79
|
-
|
|
80
|
-
|
|
122
|
+
(0, TimerRegistrationValidator_1.validateTimerRegistration)(state.name, state.periodMs, options);
|
|
123
|
+
const slot = { binding: undefined };
|
|
124
|
+
const timer = this.createTimer(state.name, 1n, state.periodMs, options, slot, state);
|
|
125
|
+
return [
|
|
126
|
+
state.name,
|
|
127
|
+
{
|
|
128
|
+
generation: 1n,
|
|
129
|
+
handlerType: state.handlerType,
|
|
130
|
+
timer,
|
|
131
|
+
handle: new ZLinkRegisteredTimer(this, state.name, 1n, timer),
|
|
132
|
+
restored: true,
|
|
133
|
+
slot
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
});
|
|
137
|
+
this.frozen = true;
|
|
138
|
+
for (const [name, entry] of restored) {
|
|
139
|
+
this.generations.set(name, entry.generation);
|
|
140
|
+
this.timers.set(name, entry);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Runs one relocation-target initialization callback inside the reattach window. */
|
|
144
|
+
async runRelocationInitialization(operation) {
|
|
145
|
+
if (!this.frozen || this.initializing) {
|
|
146
|
+
throw new Error('Timer relocation initialization is not active.');
|
|
147
|
+
}
|
|
148
|
+
this.initializing = true;
|
|
149
|
+
try {
|
|
150
|
+
return await operation();
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
this.initializing = false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* After Configure, resolves every restored timer's handler constructor by
|
|
158
|
+
* name among the constructors the Spot announced in Configure: `addTimer(...)`
|
|
159
|
+
* there or `handlers.addTimerHandler(...)`. A restored key that Configure did
|
|
160
|
+
* not reattach is registered with the resolved constructor so it survives
|
|
161
|
+
* Ready without re-registration. No match or more than one match fails the
|
|
162
|
+
* target restore.
|
|
163
|
+
*/
|
|
164
|
+
async resolveRelocationHandlers(declared, register) {
|
|
165
|
+
if (!this.frozen || !this.initializing || this.relocationHandlersResolved) {
|
|
166
|
+
throw new Error('Timer relocation handler resolution is not active.');
|
|
167
|
+
}
|
|
168
|
+
this.relocationHandlersResolved = true;
|
|
169
|
+
const constructors = [...new Set([...declared, ...this.configureTimerHandlers])];
|
|
170
|
+
const restored = await this.lane.run(() => [...this.timers.entries()].filter(([, entry]) => entry.restored));
|
|
171
|
+
for (const [name, entry] of restored) {
|
|
172
|
+
const matches = constructors.filter((type) => type.name === entry.handlerType);
|
|
173
|
+
if (matches.length !== 1) {
|
|
174
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RelocationFailed, matches.length === 0
|
|
175
|
+
? `Timer '${name}' handler '${entry.handlerType}' is not declared. Register its timer with context.addTimer(...) in configure(), or declare it with context.handlers.addTimerHandler(Handler) in configure().`
|
|
176
|
+
: `Timer '${name}' handler '${entry.handlerType}' is ambiguous: ${matches.length} declared constructors share the name.`);
|
|
81
177
|
}
|
|
82
|
-
|
|
83
|
-
await
|
|
178
|
+
if (entry.slot.binding === undefined) {
|
|
179
|
+
await register(name, entry.timer.periodMs, matches[0]);
|
|
84
180
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** Ready: starts the restored and newly registered timers. */
|
|
184
|
+
async publishRelocation() {
|
|
185
|
+
await this.lane.run(() => {
|
|
186
|
+
for (const [name, entry] of this.timers) {
|
|
187
|
+
if (entry.slot.binding === undefined) {
|
|
188
|
+
throw new Error(`Restored timer '${name}' has no resolved handler at Ready.`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
this.frozen = false;
|
|
192
|
+
for (const entry of this.timers.values()) {
|
|
193
|
+
(0, state_lane_1.startOutsideStateLane)(() => entry.timer.resume());
|
|
194
|
+
}
|
|
195
|
+
});
|
|
90
196
|
}
|
|
91
197
|
async dispose() {
|
|
92
198
|
const timers = await this.lane.run(() => {
|
|
@@ -102,7 +208,10 @@ class ZLinkSpotTimerRegistry {
|
|
|
102
208
|
await Promise.all(finalizations.filter((_, index) => timers[index].wait));
|
|
103
209
|
}
|
|
104
210
|
async captureRelocation() {
|
|
105
|
-
const timers = await this.lane.run(() =>
|
|
211
|
+
const timers = await this.lane.run(() => {
|
|
212
|
+
this.frozen = true;
|
|
213
|
+
return [...this.timers.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
214
|
+
});
|
|
106
215
|
const states = [];
|
|
107
216
|
for (const [name, entry] of timers) {
|
|
108
217
|
const state = await entry.timer.captureRelocation(entry.handlerType);
|
|
@@ -112,21 +221,12 @@ class ZLinkSpotTimerRegistry {
|
|
|
112
221
|
}
|
|
113
222
|
return states;
|
|
114
223
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
224
|
+
/** Source abort: the captured timers continue from their own unchanged cursor. */
|
|
225
|
+
abortRelocation() {
|
|
226
|
+
this.frozen = false;
|
|
227
|
+
for (const entry of this.timers.values()) {
|
|
228
|
+
(0, state_lane_1.startOutsideStateLane)(() => entry.timer.resume());
|
|
119
229
|
}
|
|
120
|
-
for (const [name, entry] of this.timers) {
|
|
121
|
-
const state = byName.get(name);
|
|
122
|
-
if (state === undefined) {
|
|
123
|
-
throw new Error(`Timer '${name}' is missing from relocation state.`);
|
|
124
|
-
}
|
|
125
|
-
entry.timer.restoreRelocation(state, entry.handlerType);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
abortRelocation(states) {
|
|
129
|
-
this.restoreRelocation(states);
|
|
130
230
|
}
|
|
131
231
|
async commitRelocation() {
|
|
132
232
|
await this.dispose();
|
|
@@ -136,17 +236,58 @@ class ZLinkSpotTimerRegistry {
|
|
|
136
236
|
await this.lane.run(() => this.cancelCore(name, generation, timer));
|
|
137
237
|
await timer.cancel(signal);
|
|
138
238
|
}
|
|
139
|
-
|
|
239
|
+
createTimer(name, generation, periodMs, options, slot, cursor) {
|
|
240
|
+
let callbackStarted = false;
|
|
241
|
+
const timer = (0, state_lane_1.startOutsideStateLane)(() => new ZLinkManagedTimer(name, periodMs, normalizeTimerOptions(options), async (tick) => {
|
|
242
|
+
callbackStarted = false;
|
|
243
|
+
const binding = slot.binding;
|
|
244
|
+
if (binding === undefined)
|
|
245
|
+
return;
|
|
246
|
+
const timerFlow = (0, flow_context_1.createInboundFlow)(undefined, 'Timer', this.flowCreationEnabled(), undefined);
|
|
247
|
+
const operation = () => {
|
|
248
|
+
const current = this.timers.get(name);
|
|
249
|
+
if (current === undefined ||
|
|
250
|
+
current.generation !== generation ||
|
|
251
|
+
current.timer !== timer) {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
if (!this.executionAllowed())
|
|
255
|
+
return undefined;
|
|
256
|
+
callbackStarted = true;
|
|
257
|
+
return (0, flow_context_1.runWithFlow)(timerFlow, () => binding.handler.handle(binding.spot, tick));
|
|
258
|
+
};
|
|
259
|
+
if (this.executeTimer !== undefined) {
|
|
260
|
+
await this.executeTimer(name, operation);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
await binding.executionSerial.execute(operation);
|
|
264
|
+
}
|
|
265
|
+
}, (tick, cause, event) => slot.binding?.reportFailure?.(tick, cause, event), () => callbackStarted, this.clock, { paused: true, cursor }));
|
|
266
|
+
return timer;
|
|
267
|
+
}
|
|
268
|
+
prepareAddCore(name, handlerType, initializing, binding) {
|
|
269
|
+
if (this.frozen && !initializing) {
|
|
270
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, `Timer '${name}' registration is sealed for relocation.`);
|
|
271
|
+
}
|
|
140
272
|
const previous = this.timers.get(name);
|
|
273
|
+
if (initializing && previous?.restored === true) {
|
|
274
|
+
if (previous.handlerType !== handlerType) {
|
|
275
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, `Timer '${name}' was restored with handler '${previous.handlerType}', not '${handlerType}'.`);
|
|
276
|
+
}
|
|
277
|
+
previous.slot.binding = binding;
|
|
278
|
+
return { kind: 'reattached', handle: previous.handle };
|
|
279
|
+
}
|
|
141
280
|
this.timers.delete(name);
|
|
142
281
|
const generation = (this.generations.get(name) ?? 0n) + 1n;
|
|
143
282
|
this.generations.set(name, generation);
|
|
144
|
-
return { previous, generation };
|
|
283
|
+
return { kind: 'registered', previous, generation };
|
|
145
284
|
}
|
|
146
|
-
completeAddCore(name,
|
|
147
|
-
if (this.generations.get(name) !== generation)
|
|
285
|
+
completeAddCore(name, entry) {
|
|
286
|
+
if (this.generations.get(name) !== entry.generation)
|
|
148
287
|
return false;
|
|
149
|
-
this.timers.set(name,
|
|
288
|
+
this.timers.set(name, entry);
|
|
289
|
+
if (!this.frozen)
|
|
290
|
+
(0, state_lane_1.startOutsideStateLane)(() => entry.timer.resume());
|
|
150
291
|
return true;
|
|
151
292
|
}
|
|
152
293
|
cancelCore(name, generation, timer) {
|
|
@@ -201,13 +342,21 @@ class ZLinkManagedTimer {
|
|
|
201
342
|
pausedForRelocation = false;
|
|
202
343
|
startedAtMs;
|
|
203
344
|
startedAtUnixMs;
|
|
345
|
+
/** DeliveryIndex and ScheduledIndex of the last completed tick. */
|
|
204
346
|
deliveryIndex = 0n;
|
|
205
347
|
lastScheduledIndex = 0n;
|
|
348
|
+
/**
|
|
349
|
+
* The selected tick whose callback has not completed (Spot timer §1). It is
|
|
350
|
+
* the only pending tick a relocation captures, and a restored timer delivers
|
|
351
|
+
* it before it selects another tick.
|
|
352
|
+
*/
|
|
353
|
+
pendingScheduledIndex;
|
|
206
354
|
timeout;
|
|
207
|
-
|
|
355
|
+
/** The dispatch in flight, from its timer callback until `completeFireCore`. */
|
|
356
|
+
running;
|
|
208
357
|
dispatchFailure;
|
|
209
358
|
finalization;
|
|
210
|
-
constructor(name, periodMs, options, onTick, onFailure, shouldWaitForRunningOnCancel = () => true, clock = systemTimerClock) {
|
|
359
|
+
constructor(name, periodMs, options, onTick, onFailure, shouldWaitForRunningOnCancel = () => true, clock = systemTimerClock, start = {}) {
|
|
211
360
|
this.name = name;
|
|
212
361
|
this.periodMs = periodMs;
|
|
213
362
|
this.options = options;
|
|
@@ -215,8 +364,20 @@ class ZLinkManagedTimer {
|
|
|
215
364
|
this.onFailure = onFailure;
|
|
216
365
|
this.shouldWaitForRunningOnCancel = shouldWaitForRunningOnCancel;
|
|
217
366
|
this.clock = clock;
|
|
218
|
-
|
|
219
|
-
|
|
367
|
+
const cursor = start.cursor;
|
|
368
|
+
if (cursor === undefined) {
|
|
369
|
+
this.startedAtMs = clock.now();
|
|
370
|
+
this.startedAtUnixMs = clock.utcNow();
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
validateRelocationCursor(name, periodMs, cursor);
|
|
374
|
+
this.startedAtUnixMs = cursor.startedAtUnixMs;
|
|
375
|
+
this.startedAtMs = clock.now() - Math.max(0, clock.utcNow() - cursor.startedAtUnixMs);
|
|
376
|
+
this.deliveryIndex = cursor.deliveryIndex;
|
|
377
|
+
this.lastScheduledIndex = cursor.lastScheduledIndex;
|
|
378
|
+
this.pendingScheduledIndex = cursor.pendingTicks[0]?.scheduledIndex;
|
|
379
|
+
}
|
|
380
|
+
this.pausedForRelocation = start.paused === true;
|
|
220
381
|
this.scheduleNext();
|
|
221
382
|
}
|
|
222
383
|
get isDisposed() {
|
|
@@ -261,51 +422,34 @@ class ZLinkManagedTimer {
|
|
|
261
422
|
deliveryIndex: this.deliveryIndex,
|
|
262
423
|
lastScheduledIndex: this.lastScheduledIndex,
|
|
263
424
|
nextDueAtUnixMs: this.startedAtUnixMs + Number(this.lastScheduledIndex + 1n) * this.periodMs,
|
|
264
|
-
pendingTicks:
|
|
425
|
+
pendingTicks: this.pendingScheduledIndex === undefined
|
|
426
|
+
? []
|
|
427
|
+
: [this.pendingTick(this.pendingScheduledIndex)]
|
|
265
428
|
}));
|
|
266
429
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
state.handlerType !== handlerType ||
|
|
272
|
-
state.periodMs !== this.periodMs ||
|
|
273
|
-
state.overrunPolicy !== this.options.overrunPolicy ||
|
|
274
|
-
state.maxCatchUpTicks !== this.options.maxCatchUpTicks ||
|
|
275
|
-
state.stopOnUnhandledException !== this.options.stopOnUnhandledException ||
|
|
276
|
-
!Number.isSafeInteger(state.startedAtUnixMs) ||
|
|
277
|
-
state.deliveryIndex < 0n ||
|
|
278
|
-
state.lastScheduledIndex < 0n ||
|
|
279
|
-
!Number.isSafeInteger(state.nextDueAtUnixMs) ||
|
|
280
|
-
state.nextDueAtUnixMs !==
|
|
281
|
-
state.startedAtUnixMs + Number(state.lastScheduledIndex + 1n) * state.periodMs ||
|
|
282
|
-
state.pendingTicks.length !== 0) {
|
|
283
|
-
throw new Error(`Timer '${this.name}' relocation contract does not match its registration.`);
|
|
284
|
-
}
|
|
285
|
-
if (this.timeout !== undefined)
|
|
286
|
-
this.clock.clearTimeout(this.timeout);
|
|
287
|
-
this.timeout = undefined;
|
|
288
|
-
this.startedAtUnixMs = state.startedAtUnixMs;
|
|
289
|
-
this.startedAtMs = this.clock.now() - Math.max(0, this.clock.utcNow() - state.startedAtUnixMs);
|
|
290
|
-
this.deliveryIndex = state.deliveryIndex;
|
|
291
|
-
this.lastScheduledIndex = state.lastScheduledIndex;
|
|
430
|
+
/** Starts a timer created paused, or continues one paused by a relocation capture. */
|
|
431
|
+
resume() {
|
|
432
|
+
if (this.disposed || !this.pausedForRelocation)
|
|
433
|
+
return;
|
|
292
434
|
this.pausedForRelocation = false;
|
|
293
435
|
this.scheduleNext();
|
|
294
436
|
}
|
|
295
437
|
scheduleNext() {
|
|
296
|
-
|
|
438
|
+
// The dispatch in flight schedules the next tick when it completes.
|
|
439
|
+
if (this.disposed || this.pausedForRelocation || this.running !== undefined) {
|
|
297
440
|
return;
|
|
298
441
|
}
|
|
299
|
-
const delayMs = this.
|
|
300
|
-
?
|
|
301
|
-
:
|
|
302
|
-
|
|
442
|
+
const delayMs = this.pendingScheduledIndex !== undefined
|
|
443
|
+
? 0
|
|
444
|
+
: this.options.overrunPolicy === contracts_1.ZLinkTimerOverrunPolicy.DelayNextTick
|
|
445
|
+
? this.periodMs
|
|
446
|
+
: Math.max(0, Number(this.lastScheduledIndex + 1n) * this.periodMs - this.elapsedMs());
|
|
447
|
+
this.timeout = (0, state_lane_1.startOutsideStateLane)(() => this.clock.setTimeout(() => {
|
|
303
448
|
this.timeout = undefined;
|
|
304
|
-
|
|
305
|
-
this.running = execution.then(() => undefined, (cause) => this.lane.run(() => {
|
|
449
|
+
this.running = this.fire().then(() => undefined, (cause) => this.lane.run(() => {
|
|
306
450
|
this.dispatchFailure ??= { cause };
|
|
307
451
|
}));
|
|
308
|
-
}, delayMs);
|
|
452
|
+
}, delayMs));
|
|
309
453
|
}
|
|
310
454
|
async fire() {
|
|
311
455
|
const prepared = await this.lane.run(() => this.prepareFireCore());
|
|
@@ -316,12 +460,18 @@ class ZLinkManagedTimer {
|
|
|
316
460
|
await this.onTick(prepared.tick);
|
|
317
461
|
}
|
|
318
462
|
catch (cause) {
|
|
463
|
+
// A tick whose callback had not started when a relocation captured it
|
|
464
|
+
// belongs to the capture: the target delivers it, so the source neither
|
|
465
|
+
// reports nor completes it.
|
|
466
|
+
const started = this.shouldWaitForRunningOnCancel();
|
|
467
|
+
if (!started && (await this.lane.run(() => this.pausedForRelocation)))
|
|
468
|
+
return;
|
|
319
469
|
shouldContinue = !this.options.stopOnUnhandledException;
|
|
320
470
|
await this.onFailure?.(prepared.tick, cause, shouldContinue
|
|
321
471
|
? internal_event_contracts_1.ZLinkSpotEventKind.TimerHandlerFailed
|
|
322
472
|
: internal_event_contracts_1.ZLinkSpotEventKind.TimerStoppedAfterUnhandledException);
|
|
323
473
|
}
|
|
324
|
-
await this.lane.run(() => this.completeFireCore(
|
|
474
|
+
await this.lane.run(() => this.completeFireCore(shouldContinue));
|
|
325
475
|
}
|
|
326
476
|
cancelCore() {
|
|
327
477
|
this.disposed = true;
|
|
@@ -329,7 +479,7 @@ class ZLinkManagedTimer {
|
|
|
329
479
|
this.timeout = undefined;
|
|
330
480
|
return {
|
|
331
481
|
timeout,
|
|
332
|
-
running: this.shouldWaitForRunningOnCancel() ? this.running :
|
|
482
|
+
running: this.shouldWaitForRunningOnCancel() ? this.running : undefined
|
|
333
483
|
};
|
|
334
484
|
}
|
|
335
485
|
async completeFinalization(start, finalization) {
|
|
@@ -369,34 +519,39 @@ class ZLinkManagedTimer {
|
|
|
369
519
|
this.clock.clearTimeout(this.timeout);
|
|
370
520
|
this.timeout = undefined;
|
|
371
521
|
}
|
|
372
|
-
return { running: this.shouldWaitForRunningOnCancel() ? this.running :
|
|
522
|
+
return { running: this.shouldWaitForRunningOnCancel() ? this.running : undefined };
|
|
373
523
|
}
|
|
374
524
|
prepareFireCore() {
|
|
375
525
|
if (this.disposed)
|
|
376
526
|
return undefined;
|
|
377
|
-
|
|
378
|
-
const
|
|
527
|
+
this.pendingScheduledIndex ??= this.selectScheduledIndex();
|
|
528
|
+
const pending = this.pendingTick(this.pendingScheduledIndex);
|
|
379
529
|
const startedElapsedMs = this.elapsedMs();
|
|
380
|
-
const scheduledElapsedMs = Number(scheduledIndex) * this.periodMs;
|
|
381
|
-
this.deliveryIndex += 1n;
|
|
530
|
+
const scheduledElapsedMs = Number(pending.scheduledIndex) * this.periodMs;
|
|
382
531
|
return {
|
|
383
|
-
scheduledIndex,
|
|
384
532
|
tick: {
|
|
385
533
|
name: this.name,
|
|
386
|
-
deliveryIndex:
|
|
387
|
-
scheduledIndex,
|
|
534
|
+
deliveryIndex: pending.deliveryIndex,
|
|
535
|
+
scheduledIndex: pending.scheduledIndex,
|
|
388
536
|
periodMs: this.periodMs,
|
|
389
|
-
scheduledAt: new Date(
|
|
537
|
+
scheduledAt: new Date(pending.scheduledAtUnixMs),
|
|
390
538
|
startedAt: new Date(this.clock.utcNow()),
|
|
391
539
|
scheduledElapsedMs,
|
|
392
540
|
startedElapsedMs,
|
|
393
541
|
delayMs: startedElapsedMs - scheduledElapsedMs,
|
|
394
|
-
skippedTicks
|
|
542
|
+
skippedTicks: pending.skippedTicks
|
|
395
543
|
}
|
|
396
544
|
};
|
|
397
545
|
}
|
|
398
|
-
|
|
399
|
-
|
|
546
|
+
/** The tick info of the pending tick at `scheduledIndex` after the completed cursor. */
|
|
547
|
+
pendingTick(scheduledIndex) {
|
|
548
|
+
return relocationPendingTick(this.startedAtUnixMs, this.periodMs, this.deliveryIndex, this.lastScheduledIndex, scheduledIndex);
|
|
549
|
+
}
|
|
550
|
+
completeFireCore(shouldContinue) {
|
|
551
|
+
this.deliveryIndex += 1n;
|
|
552
|
+
this.lastScheduledIndex = this.pendingScheduledIndex;
|
|
553
|
+
this.pendingScheduledIndex = undefined;
|
|
554
|
+
this.running = undefined;
|
|
400
555
|
if (!shouldContinue) {
|
|
401
556
|
this.disposed = true;
|
|
402
557
|
return;
|
|
@@ -428,8 +583,37 @@ class ZLinkManagedTimer {
|
|
|
428
583
|
}
|
|
429
584
|
}
|
|
430
585
|
exports.ZLinkManagedTimer = ZLinkManagedTimer;
|
|
431
|
-
function
|
|
432
|
-
|
|
586
|
+
function validateRelocationCursor(name, periodMs, state) {
|
|
587
|
+
if (state.name !== name ||
|
|
588
|
+
state.periodMs !== periodMs ||
|
|
589
|
+
!Number.isSafeInteger(state.startedAtUnixMs) ||
|
|
590
|
+
state.deliveryIndex < 0n ||
|
|
591
|
+
state.lastScheduledIndex < 0n ||
|
|
592
|
+
!Number.isSafeInteger(state.nextDueAtUnixMs) ||
|
|
593
|
+
state.nextDueAtUnixMs !==
|
|
594
|
+
state.startedAtUnixMs + Number(state.lastScheduledIndex + 1n) * state.periodMs ||
|
|
595
|
+
state.pendingTicks.length > 1 ||
|
|
596
|
+
state.pendingTicks.some((pending) => {
|
|
597
|
+
const expected = relocationPendingTick(state.startedAtUnixMs, state.periodMs, state.deliveryIndex, state.lastScheduledIndex, pending.scheduledIndex);
|
|
598
|
+
return (pending.scheduledIndex <= state.lastScheduledIndex ||
|
|
599
|
+
pending.deliveryIndex !== expected.deliveryIndex ||
|
|
600
|
+
pending.scheduledAtUnixMs !== expected.scheduledAtUnixMs ||
|
|
601
|
+
pending.skippedTicks !== expected.skippedTicks);
|
|
602
|
+
})) {
|
|
603
|
+
throw new Error(`Timer '${name}' relocation state is invalid.`);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Spot timer §1: the tick info that follows the completed cursor. A timer holds
|
|
608
|
+
* at most one pending tick, so its DeliveryIndex is the next one.
|
|
609
|
+
*/
|
|
610
|
+
function relocationPendingTick(startedAtUnixMs, periodMs, deliveryIndex, lastScheduledIndex, scheduledIndex) {
|
|
611
|
+
return {
|
|
612
|
+
deliveryIndex: deliveryIndex + 1n,
|
|
613
|
+
scheduledIndex,
|
|
614
|
+
scheduledAtUnixMs: startedAtUnixMs + Number(scheduledIndex) * periodMs,
|
|
615
|
+
skippedTicks: scheduledIndex - lastScheduledIndex - 1n
|
|
616
|
+
};
|
|
433
617
|
}
|
|
434
618
|
function createTimerDiagnostics(sourceName, spotId, isEntrySpot, timerName, handlerType, publisher) {
|
|
435
619
|
if (publisher === undefined) {
|