@workflow/core 5.0.0-beta.5 → 5.0.0-beta.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/attribute-changes.d.ts +5 -0
- package/dist/attribute-changes.d.ts.map +1 -0
- package/dist/attribute-changes.js +25 -0
- package/dist/capabilities.d.ts +35 -2
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +74 -5
- package/dist/capture-stack.d.ts +1 -1
- package/dist/capture-stack.js +2 -2
- package/dist/class-serialization.d.ts +32 -0
- package/dist/class-serialization.d.ts.map +1 -1
- package/dist/class-serialization.js +37 -1
- package/dist/classify-error.d.ts +19 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +98 -6
- package/dist/context-violation-error.d.ts +5 -5
- package/dist/context-violation-error.d.ts.map +1 -1
- package/dist/context-violation-error.js +8 -6
- package/dist/create-hook.d.ts +72 -7
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +1 -1
- package/dist/define-hook.js +2 -2
- package/dist/describe-error.d.ts +7 -7
- package/dist/describe-error.d.ts.map +1 -1
- package/dist/describe-error.js +97 -12
- package/dist/encryption.d.ts +38 -4
- package/dist/encryption.d.ts.map +1 -1
- package/dist/encryption.js +96 -14
- package/dist/events-consumer.d.ts +297 -0
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +673 -42
- package/dist/flushable-stream.d.ts +97 -1
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +291 -11
- package/dist/global.d.ts +36 -2
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +21 -6
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/log-format.d.ts +2 -2
- package/dist/log-format.js +19 -12
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +10 -6
- package/dist/private.d.ts +226 -9
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +626 -7
- package/dist/replay-divergence.d.ts +25 -0
- package/dist/replay-divergence.d.ts.map +1 -0
- package/dist/replay-divergence.js +61 -0
- package/dist/replay-payload-cache.d.ts +64 -0
- package/dist/replay-payload-cache.d.ts.map +1 -0
- package/dist/replay-payload-cache.js +158 -0
- package/dist/runtime/compute-instance.d.ts +13 -0
- package/dist/runtime/compute-instance.d.ts.map +1 -0
- package/dist/runtime/compute-instance.js +14 -0
- package/dist/runtime/constants.d.ts +315 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +502 -16
- package/dist/runtime/count-step-started-events.d.ts +52 -0
- package/dist/runtime/count-step-started-events.d.ts.map +1 -0
- package/dist/runtime/count-step-started-events.js +72 -0
- package/dist/runtime/deployment-guard.d.ts +99 -0
- package/dist/runtime/deployment-guard.d.ts.map +1 -0
- package/dist/runtime/deployment-guard.js +154 -0
- package/dist/runtime/get-port-lazy.d.ts +15 -0
- package/dist/runtime/get-port-lazy.d.ts.map +1 -1
- package/dist/runtime/get-port-lazy.js +75 -6
- package/dist/runtime/get-world-lazy.d.ts +5 -14
- package/dist/runtime/get-world-lazy.d.ts.map +1 -1
- package/dist/runtime/get-world-lazy.js +19 -29
- package/dist/runtime/helpers.d.ts +415 -29
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +686 -57
- package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
- package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
- package/dist/runtime/quickjs-assets.generated.js +30 -0
- package/dist/runtime/quickjs-entrypoint.d.ts +158 -0
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
- package/dist/runtime/quickjs-entrypoint.js +1863 -0
- package/dist/runtime/quickjs-log-view.d.ts +129 -0
- package/dist/runtime/quickjs-log-view.d.ts.map +1 -0
- package/dist/runtime/quickjs-log-view.js +229 -0
- package/dist/runtime/quickjs-runtime.d.ts +244 -0
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
- package/dist/runtime/quickjs-runtime.js +2427 -0
- package/dist/runtime/quickjs-serde.d.ts +107 -0
- package/dist/runtime/quickjs-serde.d.ts.map +1 -0
- package/dist/runtime/quickjs-serde.js +2159 -0
- package/dist/runtime/replay-budget.d.ts +97 -0
- package/dist/runtime/replay-budget.d.ts.map +1 -0
- package/dist/runtime/replay-budget.js +139 -0
- package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
- package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
- package/dist/runtime/replay-recovery-reporter.js +64 -0
- package/dist/runtime/resume-hook.d.ts +91 -8
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +512 -89
- package/dist/runtime/resume-latency.d.ts +150 -0
- package/dist/runtime/resume-latency.d.ts.map +1 -0
- package/dist/runtime/resume-latency.js +155 -0
- package/dist/runtime/run-id-time.d.ts +19 -0
- package/dist/runtime/run-id-time.d.ts.map +1 -0
- package/dist/runtime/run-id-time.js +42 -0
- package/dist/runtime/run.d.ts +72 -7
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +280 -53
- package/dist/runtime/runs.d.ts +54 -3
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +126 -16
- package/dist/runtime/start.d.ts +101 -2
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +352 -61
- package/dist/runtime/step-executor.d.ts +186 -5
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +768 -130
- package/dist/runtime/step-latency.d.ts +220 -0
- package/dist/runtime/step-latency.d.ts.map +1 -0
- package/dist/runtime/step-latency.js +215 -0
- package/dist/runtime/step-ownership.d.ts +72 -0
- package/dist/runtime/step-ownership.d.ts.map +1 -0
- package/dist/runtime/step-ownership.js +114 -0
- package/dist/runtime/step-single-flight.d.ts +12 -0
- package/dist/runtime/step-single-flight.d.ts.map +1 -0
- package/dist/runtime/step-single-flight.js +75 -0
- package/dist/runtime/suspension-handler.d.ts +247 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +1304 -125
- package/dist/runtime/unserializable-step.d.ts +34 -0
- package/dist/runtime/unserializable-step.d.ts.map +1 -0
- package/dist/runtime/unserializable-step.js +52 -0
- package/dist/runtime/vm-mode.d.ts +44 -0
- package/dist/runtime/vm-mode.d.ts.map +1 -0
- package/dist/runtime/vm-mode.js +62 -0
- package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
- package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
- package/dist/runtime/vm-serde-bundle.generated.js +16 -0
- package/dist/runtime/wait-continuation.d.ts +106 -0
- package/dist/runtime/wait-continuation.d.ts.map +1 -0
- package/dist/runtime/wait-continuation.js +136 -0
- package/dist/runtime/wait-until.d.ts +18 -0
- package/dist/runtime/wait-until.d.ts.map +1 -0
- package/dist/runtime/wait-until.js +42 -0
- package/dist/runtime/world-compatibility.d.ts +32 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -0
- package/dist/runtime/world-compatibility.js +44 -0
- package/dist/runtime/world-init.d.ts +17 -42
- package/dist/runtime/world-init.d.ts.map +1 -1
- package/dist/runtime/world-init.js +18 -43
- package/dist/runtime/world.d.ts +14 -2
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +75 -19
- package/dist/runtime.d.ts +10 -6
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +3911 -489
- package/dist/sealed-box.d.ts +167 -0
- package/dist/sealed-box.d.ts.map +1 -0
- package/dist/sealed-box.js +571 -0
- package/dist/serialization/client.d.ts +3 -3
- package/dist/serialization/client.d.ts.map +1 -1
- package/dist/serialization/client.js +8 -4
- package/dist/serialization/codec-devalue-vm.d.ts +16 -0
- package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
- package/dist/serialization/codec-devalue-vm.js +148 -0
- package/dist/serialization/codec-devalue.d.ts +1 -1
- package/dist/serialization/codec-devalue.d.ts.map +1 -1
- package/dist/serialization/codec-devalue.js +24 -6
- package/dist/serialization/codec.d.ts +37 -2
- package/dist/serialization/codec.d.ts.map +1 -1
- package/dist/serialization/codec.js +2 -2
- package/dist/serialization/compression.d.ts +105 -0
- package/dist/serialization/compression.d.ts.map +1 -0
- package/dist/serialization/compression.js +261 -0
- package/dist/serialization/encryption.d.ts +119 -17
- package/dist/serialization/encryption.d.ts.map +1 -1
- package/dist/serialization/encryption.js +152 -17
- package/dist/serialization/errors.d.ts +13 -0
- package/dist/serialization/errors.d.ts.map +1 -1
- package/dist/serialization/errors.js +20 -2
- package/dist/serialization/format.d.ts +6 -6
- package/dist/serialization/format.js +7 -7
- package/dist/serialization/hardened.d.ts +156 -0
- package/dist/serialization/hardened.d.ts.map +1 -0
- package/dist/serialization/hardened.js +538 -0
- package/dist/serialization/index.d.ts +10 -8
- package/dist/serialization/index.d.ts.map +1 -1
- package/dist/serialization/index.js +10 -8
- package/dist/serialization/reducers/class-vm.d.ts +20 -0
- package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/class-vm.js +77 -0
- package/dist/serialization/reducers/class.d.ts.map +1 -1
- package/dist/serialization/reducers/class.js +11 -6
- package/dist/serialization/reducers/common-vm.d.ts +15 -0
- package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/common-vm.js +616 -0
- package/dist/serialization/reducers/common.d.ts +1 -1
- package/dist/serialization/reducers/common.d.ts.map +1 -1
- package/dist/serialization/reducers/common.js +202 -62
- package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
- package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function-vm.js +97 -0
- package/dist/serialization/reducers/step-function.d.ts.map +1 -1
- package/dist/serialization/reducers/step-function.js +25 -9
- package/dist/serialization/step.d.ts +4 -4
- package/dist/serialization/step.d.ts.map +1 -1
- package/dist/serialization/step.js +9 -5
- package/dist/serialization/types.d.ts +80 -1
- package/dist/serialization/types.d.ts.map +1 -1
- package/dist/serialization/types.js +15 -1
- package/dist/serialization/workflow-vm.d.ts +29 -0
- package/dist/serialization/workflow-vm.d.ts.map +1 -0
- package/dist/serialization/workflow-vm.js +74 -0
- package/dist/serialization-format.d.ts +64 -8
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +225 -73
- package/dist/serialization.d.ts +262 -34
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +1885 -277
- package/dist/set-attributes.d.ts +13 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +60 -0
- package/dist/source-map.d.ts +25 -0
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +154 -10
- package/dist/step/context-storage.d.ts +63 -2
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +7 -5
- package/dist/step/writable-stream.d.ts +3 -3
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +80 -13
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +148 -27
- package/dist/symbols.d.ts +50 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +51 -1
- package/dist/telemetry/semantic-conventions.d.ts +433 -2
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +319 -3
- package/dist/telemetry.d.ts +91 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +244 -17
- package/dist/test-support/orchestrator-context.d.ts +25 -0
- package/dist/test-support/orchestrator-context.d.ts.map +1 -0
- package/dist/test-support/orchestrator-context.js +107 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -1
- package/dist/util.d.ts +0 -5
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +1 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +84 -14
- package/dist/vm/script-cache.d.ts +26 -0
- package/dist/vm/script-cache.d.ts.map +1 -0
- package/dist/vm/script-cache.js +131 -0
- package/dist/vm/uint8array-base64.js +1 -1
- package/dist/workflow/abort-controller.d.ts +2 -2
- package/dist/workflow/abort-controller.d.ts.map +1 -1
- package/dist/workflow/abort-controller.js +88 -21
- package/dist/workflow/attribute-dispatcher.d.ts +6 -0
- package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
- package/dist/workflow/attribute-dispatcher.js +45 -0
- package/dist/workflow/create-hook.d.ts.map +1 -1
- package/dist/workflow/create-hook.js +24 -3
- package/dist/workflow/get-workflow-metadata.js +2 -2
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +304 -47
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +2 -1
- package/dist/workflow/set-attributes.d.ts +68 -0
- package/dist/workflow/set-attributes.d.ts.map +1 -0
- package/dist/workflow/set-attributes.js +60 -0
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +58 -12
- package/dist/workflow/world-init-stub.d.ts +3 -3
- package/dist/workflow/world-init-stub.js +4 -4
- package/dist/workflow.d.ts +95 -3
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +900 -561
- package/docs/api-reference/create-hook.mdx +89 -10
- package/docs/api-reference/create-webhook.mdx +16 -15
- package/docs/api-reference/define-hook.mdx +35 -33
- package/docs/api-reference/fatal-error.mdx +30 -8
- package/docs/api-reference/fetch.mdx +14 -10
- package/docs/api-reference/get-step-metadata.mdx +2 -2
- package/docs/api-reference/get-workflow-metadata.mdx +3 -3
- package/docs/api-reference/get-writable.mdx +7 -7
- package/docs/api-reference/index.mdx +4 -1
- package/docs/api-reference/retryable-error.mdx +1 -1
- package/docs/api-reference/set-attributes.mdx +61 -0
- package/docs/api-reference/sleep.mdx +4 -4
- package/docs/foundations/cancellation.mdx +31 -32
- package/docs/foundations/errors-and-retries.mdx +42 -11
- package/docs/foundations/hooks.mdx +64 -35
- package/docs/foundations/idempotency.mdx +244 -12
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +2 -1
- package/docs/foundations/serialization.mdx +21 -22
- package/docs/foundations/starting-workflows.mdx +106 -30
- package/docs/foundations/streaming.mdx +108 -60
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/foundations/workflows-and-steps.mdx +9 -9
- package/docs/how-it-works/cancellation.mdx +63 -63
- package/docs/how-it-works/code-transform.mdx +83 -67
- package/docs/how-it-works/encryption.mdx +30 -26
- package/docs/how-it-works/event-sourcing.mdx +125 -34
- package/docs/how-it-works/framework-integrations.mdx +96 -337
- package/docs/how-it-works/understanding-directives.mdx +22 -22
- package/package.json +24 -15
- package/dist/runtime/step-handler.d.ts +0 -2
- package/dist/runtime/step-handler.d.ts.map +0 -1
- package/dist/runtime/step-handler.js +0 -776
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { Event } from '@workflow/world';
|
|
2
|
+
/**
|
|
3
|
+
* Client-side latency measurement (TTFS / STSO / RSFS) threaded from the
|
|
4
|
+
* orchestrator's inline execution path into `executeStep`.
|
|
5
|
+
*
|
|
6
|
+
* TTFS (time-to-first-step) measures run creation → the first step's body
|
|
7
|
+
* beginning to execute. STSO (step-to-step overhead) measures the previous
|
|
8
|
+
* step's terminal event → the next step's body beginning to execute. RSFS
|
|
9
|
+
* (run-started-to-first-step) measures the `run_started` response landing →
|
|
10
|
+
* the first step's start POST being issued, a sub-window of TTFS that
|
|
11
|
+
* isolates replay overhead from the run-creation queue hop; `finalSchedulingReplay`
|
|
12
|
+
* is the synchronous workflow-function-execution duration of only the FINAL
|
|
13
|
+
* replay pass within that window (the pass that reached and scheduled the
|
|
14
|
+
* first step); it is NOT accumulated across earlier pre-first-step passes
|
|
15
|
+
* (see {@link StepLatencyTracking.replayMs}), so it must not be read as "the
|
|
16
|
+
* replay portion of RSFS". All are attached to the step's terminal
|
|
17
|
+
* event so a backend can emit latency metrics from the event write alone,
|
|
18
|
+
* without extra event-log queries.
|
|
19
|
+
*
|
|
20
|
+
* Eligibility is decided by the orchestrator (which owns the event log) via
|
|
21
|
+
* {@link computeStepLatencyTracking}; the final values are computed by
|
|
22
|
+
* `executeStep` right before user code runs via
|
|
23
|
+
* {@link computeStepLatencyEventData}.
|
|
24
|
+
*/
|
|
25
|
+
export interface StepLatencyTracking {
|
|
26
|
+
/**
|
|
27
|
+
* Epoch ms of run creation (from the run-id ULID, falling back to the run
|
|
28
|
+
* snapshot's `createdAt`). Present only when the step qualifies for TTFS.
|
|
29
|
+
*/
|
|
30
|
+
ttfsAnchorMs?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Wall-clock ms this invocation spent committing `hook_created` events
|
|
33
|
+
* before the first step (fire-and-forget `createHook()` ahead of the first
|
|
34
|
+
* step commits in the same suspension batch). Subtracted from TTFS so the
|
|
35
|
+
* metric reflects runtime overhead rather than the user's hook writes.
|
|
36
|
+
*/
|
|
37
|
+
preStepBlockingMs?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Epoch ms the first pre-step `attr_set` write began (its client-stamped
|
|
40
|
+
* `occurredAt`, falling back to `createdAt`). When present, the TTFS
|
|
41
|
+
* measurement ENDS here instead of at the step's code start: a
|
|
42
|
+
* workflow-body `setAttributes` before the first step
|
|
43
|
+
* resolves through an extra replay (see the `hasAttributeEvents` branch in
|
|
44
|
+
* runtime.ts), so everything from this write until the step body runs is
|
|
45
|
+
* the duration of the setAttributes call, which is subtracted by ending
|
|
46
|
+
* the measurement at the point where the step would otherwise have been
|
|
47
|
+
* scheduled.
|
|
48
|
+
*/
|
|
49
|
+
preStepAttrStartMs?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Epoch ms the previous step's terminal event was recorded (its
|
|
52
|
+
* client-stamped `occurredAt`, falling back to `createdAt`). Present only
|
|
53
|
+
* when the step qualifies for STSO.
|
|
54
|
+
*/
|
|
55
|
+
prevStepEndMs?: number;
|
|
56
|
+
/** Number of unique terminal steps already in the event log. */
|
|
57
|
+
stepCount?: number;
|
|
58
|
+
/** Number of events already in the event log. */
|
|
59
|
+
eventCount?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Epoch ms the `run_started` response was received/parsed by the SDK.
|
|
62
|
+
* Present only when the step qualifies for RSFS: the same eligibility as
|
|
63
|
+
* TTFS (see {@link computeStepLatencyTracking}), plus a recoverable
|
|
64
|
+
* anchor. In turbo mode, `run_started` is backgrounded rather than
|
|
65
|
+
* awaited, so this is stamped at the point the runtime synthesizes the
|
|
66
|
+
* run locally and begins replay instead of at the real response; the
|
|
67
|
+
* first step's start POST is still chained on the real `run_started`
|
|
68
|
+
* promise (see step-executor.ts), so RSFS still ends up measuring the
|
|
69
|
+
* genuine run_started-to-first-step-POST stretch even though the two
|
|
70
|
+
* halves overlap under turbo.
|
|
71
|
+
*/
|
|
72
|
+
rsfsAnchorMs?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Wall-clock ms this invocation's synchronous workflow-function replay
|
|
75
|
+
* took: from calling `runWorkflow` to it throwing the suspension that
|
|
76
|
+
* scheduled this batch. Excludes awaited network I/O (the suspension's
|
|
77
|
+
* event commits, the step's own start POST). Reported for every batch that
|
|
78
|
+
* qualifies for TTFS or STSO, not just the first step.
|
|
79
|
+
*
|
|
80
|
+
* This is the FINAL pass only: the one that reached and scheduled this
|
|
81
|
+
* batch. Valid RSFS paths can replay more than once before the first step
|
|
82
|
+
* (e.g. a workflow-body `setAttributes()` detour replays twice), and a
|
|
83
|
+
* redelivery omits earlier invocations' replay work entirely; this value is
|
|
84
|
+
* not accumulated across those earlier passes. Do not read it as "the
|
|
85
|
+
* replay portion of RSFS": RSFS ({@link rsfsAnchorMs}) covers the whole
|
|
86
|
+
* run_started-to-first-step window, this covers only the last pass.
|
|
87
|
+
*
|
|
88
|
+
* On a retained resume this measures the resume, not a replay, which is
|
|
89
|
+
* why the distribution is bimodal and why {@link retained} is reported
|
|
90
|
+
* alongside it as the dimension that separates the two modes.
|
|
91
|
+
*/
|
|
92
|
+
replayMs?: number;
|
|
93
|
+
/** Whether turbo mode is active for this invocation. */
|
|
94
|
+
turbo: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Whether a retained VM session served this batch, as opposed to a full
|
|
97
|
+
* replay from the event log. Reported as a `retained` entry in
|
|
98
|
+
* {@link StepLatencyEventData.optimizations}, alongside `turbo`.
|
|
99
|
+
*/
|
|
100
|
+
retained: boolean;
|
|
101
|
+
}
|
|
102
|
+
/** Latency telemetry attached to a step's terminal event's `eventData`. */
|
|
103
|
+
export interface StepLatencyEventData {
|
|
104
|
+
ttfs?: number;
|
|
105
|
+
stso?: number;
|
|
106
|
+
stepCount?: number;
|
|
107
|
+
eventCount?: number;
|
|
108
|
+
/** Client-measured run_started → first step's start POST, ms. */
|
|
109
|
+
rsfs?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Client-measured wall-clock ms of the FINAL pass that scheduled this
|
|
112
|
+
* batch (see {@link StepLatencyTracking.replayMs}); not accumulated
|
|
113
|
+
* across earlier passes, so it must not be read as "the replay portion of
|
|
114
|
+
* `rsfs`". Present whenever `ttfs` or `stso` is.
|
|
115
|
+
*/
|
|
116
|
+
finalSchedulingReplay?: number;
|
|
117
|
+
/**
|
|
118
|
+
* Active runtime modes for this measurement: `turbo`, `lazyStepStart`,
|
|
119
|
+
* `optimisticStart`, and `retained` (a retained VM served the batch; its
|
|
120
|
+
* absence means a full replay). The server turns each known entry into a
|
|
121
|
+
* bounded boolean tag on every latency metric.
|
|
122
|
+
*/
|
|
123
|
+
optimizations?: string[];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Decide, from the orchestrator's view of the event log, whether the inline
|
|
127
|
+
* step batch about to execute qualifies for TTFS and/or STSO measurement.
|
|
128
|
+
* Returns undefined when neither applies. Called once per batch; the result
|
|
129
|
+
* is passed to the batch's first step only, so a parallel first batch emits a
|
|
130
|
+
* single sample rather than one per sibling.
|
|
131
|
+
*/
|
|
132
|
+
export declare function computeStepLatencyTracking(params: {
|
|
133
|
+
/** The orchestrator's current in-memory event log (ascending order). */
|
|
134
|
+
events: Event[];
|
|
135
|
+
/**
|
|
136
|
+
* Whether this invocation's initial event load contained nothing beyond
|
|
137
|
+
* run_created/run_started/attr_set. Pre-existing hook events were written
|
|
138
|
+
* by an earlier invocation, so the time they added (including the queue
|
|
139
|
+
* hop back to this invocation) is unmeasurable and disqualifies TTFS.
|
|
140
|
+
* attr_set is permitted: a redelivery can land after a committed pre-step
|
|
141
|
+
* attr_set, and the detour it marks is subtracted via `preStepAttrStartMs`
|
|
142
|
+
* regardless of which invocation wrote it.
|
|
143
|
+
*/
|
|
144
|
+
invocationStartedClean: boolean;
|
|
145
|
+
/** Epoch ms of run creation, if recoverable. Absent disqualifies TTFS. */
|
|
146
|
+
runCreatedAtMs: number | undefined;
|
|
147
|
+
/**
|
|
148
|
+
* Epoch ms the `run_started` response was received/parsed by the SDK (or,
|
|
149
|
+
* under turbo, the instant the run was synthesized locally; see
|
|
150
|
+
* {@link StepLatencyTracking.rsfsAnchorMs}). Absent disqualifies RSFS.
|
|
151
|
+
*/
|
|
152
|
+
runStartedReceivedAtMs: number | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* Wall-clock ms this suspension's `runWorkflow` call spent executing
|
|
155
|
+
* synchronously before throwing: the FINAL replay pass only, not
|
|
156
|
+
* accumulated across earlier passes. See
|
|
157
|
+
* {@link StepLatencyTracking.replayMs}.
|
|
158
|
+
*/
|
|
159
|
+
replayMs: number;
|
|
160
|
+
/** See {@link StepLatencyTracking.preStepBlockingMs}. */
|
|
161
|
+
preStepBlockingMs: number;
|
|
162
|
+
/**
|
|
163
|
+
* The accumulator's value as of the suspension that wrote the run's first
|
|
164
|
+
* attr_set (its hook phase runs before its attr writes). When the
|
|
165
|
+
* measurement ends at the attr write, only hook time from before that
|
|
166
|
+
* point may be subtracted; later hook writes fall outside the measured
|
|
167
|
+
* window. Undefined when no attr suspension happened in this invocation
|
|
168
|
+
* (e.g. the attr_set was loaded from a redelivery's snapshot, where no
|
|
169
|
+
* same-invocation hook time precedes it).
|
|
170
|
+
*/
|
|
171
|
+
preStepBlockingBeforeAttrMs: number | undefined;
|
|
172
|
+
/**
|
|
173
|
+
* Whether the suspension that scheduled this batch also created waits.
|
|
174
|
+
* Those `wait_created` writes are not in `events` yet (they were committed
|
|
175
|
+
* by this suspension pass), so they must be reported separately. A
|
|
176
|
+
* wait disqualifies both measurements.
|
|
177
|
+
*/
|
|
178
|
+
suspensionHasWaits: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Whether the suspension that scheduled this batch also created hooks
|
|
181
|
+
* (also not in `events` yet). Hooks keep TTFS eligible (their measured
|
|
182
|
+
* write time is subtracted via `preStepBlockingMs`) but disqualify STSO,
|
|
183
|
+
* which is only meaningful for a pure back-to-back step gap.
|
|
184
|
+
*/
|
|
185
|
+
suspensionCreatedHooks: boolean;
|
|
186
|
+
/** Whether turbo mode is active for this invocation. */
|
|
187
|
+
turbo: boolean;
|
|
188
|
+
/** See {@link StepLatencyTracking.retained}. */
|
|
189
|
+
retained: boolean;
|
|
190
|
+
}): StepLatencyTracking | undefined;
|
|
191
|
+
/**
|
|
192
|
+
* Compute the latency telemetry to attach to the step's terminal event.
|
|
193
|
+
* Called by `executeStep` with the wall-clock timestamp taken immediately
|
|
194
|
+
* before user step code runs. Returns undefined when there is nothing to
|
|
195
|
+
* report (no tracking, or a retry attempt; retries measure neither TTFS nor
|
|
196
|
+
* STSO).
|
|
197
|
+
*/
|
|
198
|
+
export declare function computeStepLatencyEventData(params: {
|
|
199
|
+
tracking: StepLatencyTracking | undefined;
|
|
200
|
+
/** `Date.now()` taken immediately before user step code began executing. */
|
|
201
|
+
stepCodeStartedAtMs: number;
|
|
202
|
+
/**
|
|
203
|
+
* `Date.now()` taken immediately before the first step's start POST
|
|
204
|
+
* (`step_started`) was issued. Present only for the lazy inline steps RSFS
|
|
205
|
+
* cares about; see the call sites in step-executor.ts.
|
|
206
|
+
*/
|
|
207
|
+
stepStartPostSentAtMs: number | undefined;
|
|
208
|
+
attempt: number;
|
|
209
|
+
/** Whether this step was started lazily (no separate step_created write). */
|
|
210
|
+
lazyStepStart: boolean;
|
|
211
|
+
/** Whether the body ran optimistically, without awaiting step_started. */
|
|
212
|
+
optimisticStart: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Whether the step's `step_created` + `step_started` pair was pre-claimed
|
|
215
|
+
* inside the suspension handler's batched fan-out write (no start POST of
|
|
216
|
+
* its own at all).
|
|
217
|
+
*/
|
|
218
|
+
preclaimedStart?: boolean;
|
|
219
|
+
}): StepLatencyEventData | undefined;
|
|
220
|
+
//# sourceMappingURL=step-latency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-latency.d.ts","sourceRoot":"","sources":["../../src/runtime/step-latency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,KAAK,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAYD,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAkCD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,wEAAwE;IACxE,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB;;;;;;;;OAQG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,0EAA0E;IAC1E,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;;;;OAQG;IACH,2BAA2B,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD;;;;;OAKG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,wDAAwD;IACxD,KAAK,EAAE,OAAO,CAAC;IACf,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,mBAAmB,GAAG,SAAS,CAwFlC;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC1C,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,aAAa,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,eAAe,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,oBAAoB,GAAG,SAAS,CAyFnC"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Most negative raw duration still attributed to cross-machine clock skew
|
|
3
|
+
* (and clamped to 0). Anything more negative means a corrupt anchor (e.g. a
|
|
4
|
+
* mis-decoded run-ID timestamp) and the sample is dropped instead: a
|
|
5
|
+
* systematically corrupt anchor would otherwise report an exact-zero latency
|
|
6
|
+
* on every sample, silently dragging entire percentile distributions to 0
|
|
7
|
+
* rather than surfacing as missing data.
|
|
8
|
+
*/
|
|
9
|
+
const MAX_CLOCK_SKEW_MS = 60_000;
|
|
10
|
+
/**
|
|
11
|
+
* Event types that disqualify TTFS when present in the event log at the time
|
|
12
|
+
* the run's first step batch is scheduled:
|
|
13
|
+
*
|
|
14
|
+
* - Any step event means this is not the run's first step execution.
|
|
15
|
+
* - `hook_received` / `wait_created` / `wait_completed` mean the run's path to
|
|
16
|
+
* the first step depended on user-driven timing (a webhook arriving, a
|
|
17
|
+
* sleep elapsing), so the measurement would not reflect runtime overhead.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately absent, with their cost subtracted instead:
|
|
20
|
+
*
|
|
21
|
+
* - `hook_created`: a fire-and-forget `createHook()` before the first step
|
|
22
|
+
* commits in the same invocation, whose measured duration is subtracted via
|
|
23
|
+
* {@link StepLatencyTracking.preStepBlockingMs}.
|
|
24
|
+
* - `attr_set` (workflow-body `setAttributes`): resolves through
|
|
25
|
+
* an extra replay before steps run. Subtracted by ending the measurement at
|
|
26
|
+
* the first attr write's timestamp instead; see
|
|
27
|
+
* {@link StepLatencyTracking.preStepAttrStartMs}.
|
|
28
|
+
*/
|
|
29
|
+
const TTFS_DISQUALIFYING_EVENT_TYPES = new Set([
|
|
30
|
+
'step_created',
|
|
31
|
+
'step_started',
|
|
32
|
+
'step_completed',
|
|
33
|
+
'step_failed',
|
|
34
|
+
'step_retrying',
|
|
35
|
+
'hook_received',
|
|
36
|
+
'wait_created',
|
|
37
|
+
'wait_completed',
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* Decide, from the orchestrator's view of the event log, whether the inline
|
|
41
|
+
* step batch about to execute qualifies for TTFS and/or STSO measurement.
|
|
42
|
+
* Returns undefined when neither applies. Called once per batch; the result
|
|
43
|
+
* is passed to the batch's first step only, so a parallel first batch emits a
|
|
44
|
+
* single sample rather than one per sibling.
|
|
45
|
+
*/
|
|
46
|
+
export function computeStepLatencyTracking(params) {
|
|
47
|
+
const { events } = params;
|
|
48
|
+
let ttfsEligible = params.invocationStartedClean &&
|
|
49
|
+
params.runCreatedAtMs !== undefined &&
|
|
50
|
+
!params.suspensionHasWaits;
|
|
51
|
+
let preStepAttrStartMs;
|
|
52
|
+
if (ttfsEligible) {
|
|
53
|
+
for (const event of events) {
|
|
54
|
+
if (TTFS_DISQUALIFYING_EVENT_TYPES.has(event.eventType)) {
|
|
55
|
+
ttfsEligible = false;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (event.eventType === 'attr_set') {
|
|
59
|
+
const attrStartMs = +(event.occurredAt ?? event.createdAt);
|
|
60
|
+
preStepAttrStartMs =
|
|
61
|
+
preStepAttrStartMs === undefined
|
|
62
|
+
? attrStartMs
|
|
63
|
+
: Math.min(preStepAttrStartMs, attrStartMs);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// STSO: the two steps ran back-to-back, so the newest known event is the
|
|
68
|
+
// previous step's terminal event, with nothing (hook_received, waits,
|
|
69
|
+
// attr_set, ...) in between and this suspension scheduling nothing but
|
|
70
|
+
// steps.
|
|
71
|
+
let prevStepEndMs;
|
|
72
|
+
let stepCount;
|
|
73
|
+
let eventCount;
|
|
74
|
+
const lastEvent = events[events.length - 1];
|
|
75
|
+
if (!params.suspensionHasWaits &&
|
|
76
|
+
!params.suspensionCreatedHooks &&
|
|
77
|
+
lastEvent &&
|
|
78
|
+
(lastEvent.eventType === 'step_completed' ||
|
|
79
|
+
lastEvent.eventType === 'step_failed')) {
|
|
80
|
+
prevStepEndMs = +(lastEvent.occurredAt ?? lastEvent.createdAt);
|
|
81
|
+
const terminalStepIds = new Set();
|
|
82
|
+
for (const event of events) {
|
|
83
|
+
if ((event.eventType === 'step_completed' ||
|
|
84
|
+
event.eventType === 'step_failed') &&
|
|
85
|
+
event.correlationId !== undefined) {
|
|
86
|
+
terminalStepIds.add(event.correlationId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
stepCount = terminalStepIds.size;
|
|
90
|
+
eventCount = events.length;
|
|
91
|
+
}
|
|
92
|
+
// RSFS shares TTFS's eligibility exactly (same event-log/wait checks),
|
|
93
|
+
// plus its own anchor being recoverable.
|
|
94
|
+
const rsfsEligible = ttfsEligible && params.runStartedReceivedAtMs !== undefined;
|
|
95
|
+
if (!ttfsEligible && prevStepEndMs === undefined) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
...(ttfsEligible
|
|
100
|
+
? {
|
|
101
|
+
ttfsAnchorMs: params.runCreatedAtMs,
|
|
102
|
+
// When the measurement ends at the first attr write, only hook
|
|
103
|
+
// time from before that point is inside the measured window.
|
|
104
|
+
preStepBlockingMs: preStepAttrStartMs !== undefined
|
|
105
|
+
? (params.preStepBlockingBeforeAttrMs ?? 0)
|
|
106
|
+
: params.preStepBlockingMs,
|
|
107
|
+
...(preStepAttrStartMs !== undefined ? { preStepAttrStartMs } : {}),
|
|
108
|
+
}
|
|
109
|
+
: {}),
|
|
110
|
+
...(rsfsEligible ? { rsfsAnchorMs: params.runStartedReceivedAtMs } : {}),
|
|
111
|
+
...(prevStepEndMs !== undefined
|
|
112
|
+
? { prevStepEndMs, stepCount, eventCount }
|
|
113
|
+
: {}),
|
|
114
|
+
// Not gated on rsfsEligible: replay cost is meaningful for every batch
|
|
115
|
+
// this function returns tracking for. Gating it on RSFS left the STSO
|
|
116
|
+
// population — ordinary step-to-step transitions, the bulk of step
|
|
117
|
+
// scheduling — with no replay-cost telemetry at all.
|
|
118
|
+
replayMs: params.replayMs,
|
|
119
|
+
turbo: params.turbo,
|
|
120
|
+
retained: params.retained,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Compute the latency telemetry to attach to the step's terminal event.
|
|
125
|
+
* Called by `executeStep` with the wall-clock timestamp taken immediately
|
|
126
|
+
* before user step code runs. Returns undefined when there is nothing to
|
|
127
|
+
* report (no tracking, or a retry attempt; retries measure neither TTFS nor
|
|
128
|
+
* STSO).
|
|
129
|
+
*/
|
|
130
|
+
export function computeStepLatencyEventData(params) {
|
|
131
|
+
const { tracking } = params;
|
|
132
|
+
if (!tracking || params.attempt !== 1) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
// Small negative durations clamp to 0: cross-invocation timestamps can
|
|
136
|
+
// come from another machine's clock, so bounded skew must not produce
|
|
137
|
+
// negative values. Durations more negative than MAX_CLOCK_SKEW_MS are not
|
|
138
|
+
// skew but a corrupt anchor, and the sample is dropped (see the constant's
|
|
139
|
+
// doc comment).
|
|
140
|
+
//
|
|
141
|
+
// A pre-step setAttributes detour ends the measurement at the first attr
|
|
142
|
+
// write instead of the step's code start: the remainder is the duration
|
|
143
|
+
// of the setAttributes call (resolved via an extra replay), which is
|
|
144
|
+
// subtracted rather than disqualifying the sample. In that case
|
|
145
|
+
// `tracking.preStepBlockingMs` already holds only the hook time from
|
|
146
|
+
// BEFORE the attr write; hook writes after the window closed are excluded
|
|
147
|
+
// by computeStepLatencyTracking (see preStepBlockingBeforeAttrMs).
|
|
148
|
+
const ttfsEndMs = tracking.preStepAttrStartMs ?? params.stepCodeStartedAtMs;
|
|
149
|
+
const rawTtfs = tracking.ttfsAnchorMs !== undefined
|
|
150
|
+
? ttfsEndMs - tracking.ttfsAnchorMs - (tracking.preStepBlockingMs ?? 0)
|
|
151
|
+
: undefined;
|
|
152
|
+
const ttfs = rawTtfs !== undefined && rawTtfs >= -MAX_CLOCK_SKEW_MS
|
|
153
|
+
? Math.max(0, rawTtfs)
|
|
154
|
+
: undefined;
|
|
155
|
+
const rawStso = tracking.prevStepEndMs !== undefined
|
|
156
|
+
? params.stepCodeStartedAtMs - tracking.prevStepEndMs
|
|
157
|
+
: undefined;
|
|
158
|
+
const stso = rawStso !== undefined && rawStso >= -MAX_CLOCK_SKEW_MS
|
|
159
|
+
? Math.max(0, rawStso)
|
|
160
|
+
: undefined;
|
|
161
|
+
// RSFS ends at the actual start-POST instant, not at ttfsEndMs: unlike
|
|
162
|
+
// TTFS it is not subject to the pre-step attr-write shortcut, so a
|
|
163
|
+
// pre-step setAttributes detour (rare) makes RSFS include the detour
|
|
164
|
+
// while TTFS excludes it. `finalSchedulingReplay` is a direct passthrough
|
|
165
|
+
// of `tracking.replayMs`, the FINAL replay pass only (see
|
|
166
|
+
// StepLatencyTracking.replayMs), so no further subtraction applies, but
|
|
167
|
+
// it also means it is NOT accumulated across any earlier pre-first-step
|
|
168
|
+
// passes (e.g. a setAttributes detour) and must not be read as "the
|
|
169
|
+
// replay portion of rsfs"; rsfs covers the whole window.
|
|
170
|
+
//
|
|
171
|
+
// finalSchedulingReplay duplicates what OTEL already captures on the
|
|
172
|
+
// run/invocation span, but is deliberately collected as client telemetry
|
|
173
|
+
// so the server can emit it as an UNSAMPLED, full-population metric:
|
|
174
|
+
// workflow-server's server spans are heavily sampled in production (~7%),
|
|
175
|
+
// so they cannot serve as the dashboard's exact TTFS decomposition.
|
|
176
|
+
const rsfs = tracking.rsfsAnchorMs !== undefined &&
|
|
177
|
+
params.stepStartPostSentAtMs !== undefined
|
|
178
|
+
? Math.max(0, params.stepStartPostSentAtMs - tracking.rsfsAnchorMs)
|
|
179
|
+
: undefined;
|
|
180
|
+
const finalSchedulingReplay = tracking.replayMs !== undefined
|
|
181
|
+
? Math.max(0, tracking.replayMs)
|
|
182
|
+
: undefined;
|
|
183
|
+
if (ttfs === undefined && stso === undefined) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
const optimizations = [];
|
|
187
|
+
if (tracking.turbo)
|
|
188
|
+
optimizations.push('turbo');
|
|
189
|
+
if (params.lazyStepStart)
|
|
190
|
+
optimizations.push('lazyStepStart');
|
|
191
|
+
if (params.optimisticStart)
|
|
192
|
+
optimizations.push('optimisticStart');
|
|
193
|
+
if (params.preclaimedStart)
|
|
194
|
+
optimizations.push('preclaimedStart');
|
|
195
|
+
// Rides the existing optimizations list rather than a dedicated wire
|
|
196
|
+
// field: the server already parses this array and turns each known entry
|
|
197
|
+
// into a bounded boolean tag on every latency metric, so `retained`
|
|
198
|
+
// dimensions ttfs/stso/rsfs/finalSchedulingReplay for free.
|
|
199
|
+
if (tracking.retained)
|
|
200
|
+
optimizations.push('retained');
|
|
201
|
+
return {
|
|
202
|
+
...(ttfs !== undefined ? { ttfs } : {}),
|
|
203
|
+
...(stso !== undefined ? { stso } : {}),
|
|
204
|
+
...(stso !== undefined && tracking.stepCount !== undefined
|
|
205
|
+
? { stepCount: tracking.stepCount }
|
|
206
|
+
: {}),
|
|
207
|
+
...(stso !== undefined && tracking.eventCount !== undefined
|
|
208
|
+
? { eventCount: tracking.eventCount }
|
|
209
|
+
: {}),
|
|
210
|
+
...(rsfs !== undefined ? { rsfs } : {}),
|
|
211
|
+
...(finalSchedulingReplay !== undefined ? { finalSchedulingReplay } : {}),
|
|
212
|
+
optimizations,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1sYXRlbmN5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1sYXRlbmN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXVHQTs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUM7QUEwQmpDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLDhCQUE4QixHQUFvQyxJQUFJLEdBQUcsQ0FDN0U7SUFDRSxjQUFjO0lBQ2QsY0FBYztJQUNkLGdCQUFnQjtJQUNoQixhQUFhO0lBQ2IsZUFBZTtJQUNmLGVBQWU7SUFDZixjQUFjO0lBQ2QsZ0JBQWdCO0NBQ2pCLENBQ0YsQ0FBQztBQUVGOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxNQTBEMUM7SUFDQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTFCLElBQUksWUFBWSxHQUNkLE1BQU0sQ0FBQyxzQkFBc0I7UUFDN0IsTUFBTSxDQUFDLGNBQWMsS0FBSyxTQUFTO1FBQ25DLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDO0lBQzdCLElBQUksa0JBQXNDLENBQUM7SUFDM0MsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNqQixLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzNCLElBQUksOEJBQThCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUN4RCxZQUFZLEdBQUcsS0FBSyxDQUFDO2dCQUNyQixNQUFNO1lBQ1IsQ0FBQztZQUNELElBQUksS0FBSyxDQUFDLFNBQVMsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUMzRCxrQkFBa0I7b0JBQ2hCLGtCQUFrQixLQUFLLFNBQVM7d0JB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b3cvd29ybGQnO1xuXG4vKipcbiAqIENsaWVudC1zaWRlIGxhdGVuY3kgbWVhc3VyZW1lbnQgKFRURlMgLyBTVFNPIC8gUlNGUykgdGhyZWFkZWQgZnJvbSB0aGVcbiAqIG9yY2hlc3RyYXRvcidzIGlubGluZSBleGVjdXRpb24gcGF0aCBpbnRvIGBleGVjdXRlU3RlcGAuXG4gKlxuICogVFRGUyAodGltZS10by1maXJzdC1zdGVwKSBtZWFzdXJlcyBydW4gY3JlYXRpb24g4oaSIHRoZSBmaXJzdCBzdGVwJ3MgYm9keVxuICogYmVnaW5uaW5nIHRvIGV4ZWN1dGUuIFNUU08gKHN0ZXAtdG8tc3RlcCBvdmVyaGVhZCkgbWVhc3VyZXMgdGhlIHByZXZpb3VzXG4gKiBzdGVwJ3MgdGVybWluYWwgZXZlbnQg4oaSIHRoZSBuZXh0IHN0ZXAncyBib2R5IGJlZ2lubmluZyB0byBleGVjdXRlLiBSU0ZTXG4gKiAocnVuLXN0YXJ0ZWQtdG8tZmlyc3Qtc3RlcCkgbWVhc3VyZXMgdGhlIGBydW5fc3RhcnRlZGAgcmVzcG9uc2UgbGFuZGluZyDihpJcbiAqIHRoZSBmaXJzdCBzdGVwJ3Mgc3RhcnQgUE9TVCBiZWluZyBpc3N1ZWQsIGEgc3ViLXdpbmRvdyBvZiBUVEZTIHRoYXRcbiAqIGlzb2xhdGVzIHJlcGxheSBvdmVyaGVhZCBmcm9tIHRoZSBydW4tY3JlYXRpb24gcXVldWUgaG9wOyBgZmluYWxTY2hlZHVsaW5nUmVwbGF5YFxuICogaXMgdGhlIHN5bmNocm9ub3VzIHdvcmtmbG93LWZ1bmN0aW9uLWV4ZWN1dGlvbiBkdXJhdGlvbiBvZiBvbmx5IHRoZSBGSU5BTFxuICogcmVwbGF5IHBhc3Mgd2l0aGluIHRoYXQgd2luZG93ICh0aGUgcGFzcyB0aGF0IHJlYWNoZWQgYW5kIHNjaGVkdWxlZCB0aGVcbiAqIGZpcnN0IHN0ZXApOyBpdCBpcyBOT1QgYWNjdW11bGF0ZWQgYWNyb3NzIGVhcmxpZXIgcHJlLWZpcnN0LXN0ZXAgcGFzc2VzXG4gKiAoc2VlIHtAbGluayBTdGVwTGF0ZW5jeVRyYWNraW5nLnJlcGxheU1zfSksIHNvIGl0IG11c3Qgbm90IGJlIHJlYWQgYXMgXCJ0aGVcbiAqIHJlcGxheSBwb3J0aW9uIG9mIFJTRlNcIi4gQWxsIGFyZSBhdHRhY2hlZCB0byB0aGUgc3RlcCdzIHRlcm1pbmFsXG4gKiBldmVudCBzbyBhIGJhY2tlbmQgY2FuIGVtaXQgbGF0ZW5jeSBtZXRyaWNzIGZyb20gdGhlIGV2ZW50IHdyaXRlIGFsb25lLFxuICogd2l0aG91dCBleHRyYSBldmVudC1sb2cgcXVlcmllcy5cbiAqXG4gKiBFbGlnaWJpbGl0eSBpcyBkZWNpZGVkIGJ5IHRoZSBvcmNoZXN0cmF0b3IgKHdoaWNoIG93bnMgdGhlIGV2ZW50IGxvZykgdmlhXG4gKiB7QGxpbmsgY29tcHV0ZVN0ZXBMYXRlbmN5VHJhY2tpbmd9OyB0aGUgZmluYWwgdmFsdWVzIGFyZSBjb21wdXRlZCBieVxuICogYGV4ZWN1dGVTdGVwYCByaWdodCBiZWZvcmUgdXNlciBjb2RlIHJ1bnMgdmlhXG4gKiB7QGxpbmsgY29tcHV0ZVN0ZXBMYXRlbmN5RXZlbnREYXRhfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGVwTGF0ZW5jeVRyYWNraW5nIHtcbiAgLyoqXG4gICAqIEVwb2NoIG1zIG9mIHJ1biBjcmVhdGlvbiAoZnJvbSB0aGUgcnVuLWlkIFVMSUQsIGZhbGxpbmcgYmFjayB0byB0aGUgcnVuXG4gICAqIHNuYXBzaG90J3MgYGNyZWF0ZWRBdGApLiBQcmVzZW50IG9ubHkgd2hlbiB0aGUgc3RlcCBxdWFsaWZpZXMgZm9yIFRURlMuXG4gICAqL1xuICB0dGZzQW5jaG9yTXM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBXYWxsLWNsb2NrIG1zIHRoaXMgaW52b2NhdGlvbiBzcGVudCBjb21taXR0aW5nIGBob29rX2NyZWF0ZWRgIGV2ZW50c1xuICAgKiBiZWZvcmUgdGhlIGZpcnN0IHN0ZXAgKGZpcmUtYW5kLWZvcmdldCBgY3JlYXRlSG9vaygpYCBhaGVhZCBvZiB0aGUgZmlyc3RcbiAgICogc3RlcCBjb21taXRzIGluIHRoZSBzYW1lIHN1c3BlbnNpb24gYmF0Y2gpLiBTdWJ0cmFjdGVkIGZyb20gVFRGUyBzbyB0aGVcbiAgICogbWV0cmljIHJlZmxlY3RzIHJ1bnRpbWUgb3ZlcmhlYWQgcmF0aGVyIHRoYW4gdGhlIHVzZXIncyBob29rIHdyaXRlcy5cbiAgICovXG4gIHByZVN0ZXBCbG9ja2luZ01zPzogbnVtYmVyO1xuICAvKipcbiAgICogRXBvY2ggbXMgdGhlIGZpcnN0IHByZS1zdGVwIGBhdHRyX3NldGAgd3JpdGUgYmVnYW4gKGl0cyBjbGllbnQtc3RhbXBlZFxuICAgKiBgb2NjdXJyZWRBdGAsIGZhbGxpbmcgYmFjayB0byBgY3JlYXRlZEF0YCkuIFdoZW4gcHJlc2VudCwgdGhlIFRURlNcbiAgICogbWVhc3VyZW1lbnQgRU5EUyBoZXJlIGluc3RlYWQgb2YgYXQgdGhlIHN0ZXAncyBjb2RlIHN0YXJ0OiBhXG4gICAqIHdvcmtmbG93LWJvZHkgYHNldEF0dHJpYnV0ZXNgIGJlZm9yZSB0aGUgZmlyc3Qgc3RlcFxuICAgKiByZXNvbHZlcyB0aHJvdWdoIGFuIGV4dHJhIHJlcGxheSAoc2VlIHRoZSBgaGFzQXR0cmlidXRlRXZlbnRzYCBicmFuY2ggaW5cbiAgICogcnVudGltZS50cyksIHNvIGV2ZXJ5dGhpbmcgZnJvbSB0aGlzIHdyaXRlIHVudGlsIHRoZSBzdGVwIGJvZHkgcnVucyBpc1xuICAgKiB0aGUgZHVyYXRpb24gb2YgdGhlIHNldEF0dHJpYnV0ZXMgY2FsbCwgd2hpY2ggaXMgc3VidHJhY3RlZCBieSBlbmRpbmdcbiAgICogdGhlIG1lYXN1cmVtZW50IGF0IHRoZSBwb2ludCB3aGVyZSB0aGUgc3RlcCB3b3VsZCBvdGhlcndpc2UgaGF2ZSBiZWVuXG4gICAqIHNjaGVkdWxlZC5cbiAgICovXG4gIHByZVN0ZXBBdHRyU3RhcnRNcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIEVwb2NoIG1zIHRoZSBwcmV2aW91cyBzdGVwJ3MgdGVybWluYWwgZXZlbnQgd2FzIHJlY29yZGVkIChpdHNcbiAgICogY2xpZW50LXN0YW1wZWQgYG9jY3VycmVkQXRgLCBmYWxsaW5nIGJhY2sgdG8gYGNyZWF0ZWRBdGApLiBQcmVzZW50IG9ubHlcbiAgICogd2hlbiB0aGUgc3RlcCBxdWFsaWZpZXMgZm9yIFNUU08uXG4gICAqL1xuICBwcmV2U3RlcEVuZE1zPzogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIHVuaXF1ZSB0ZXJtaW5hbCBzdGVwcyBhbHJlYWR5IGluIHRoZSBldmVudCBsb2cuICovXG4gIHN0ZXBDb3VudD86IG51bWJlcjtcbiAgLyoqIE51bWJlciBvZiBldmVudHMgYWxyZWFkeSBpbiB0aGUgZXZlbnQgbG9nLiAqL1xuICBldmVudENvdW50PzogbnVtYmVyO1xuICAvKipcbiAgICogRXBvY2ggbXMgdGhlIGBydW5fc3RhcnRlZGAgcmVzcG9uc2Ugd2FzIHJlY2VpdmVkL3BhcnNlZCBieSB0aGUgU0RLLlxuICAgKiBQcmVzZW50IG9ubHkgd2hlbiB0aGUgc3RlcCBxdWFsaWZpZXMgZm9yIFJTRlM6IHRoZSBzYW1lIGVsaWdpYmlsaXR5IGFzXG4gICAqIFRURlMgKHNlZSB7QGxpbmsgY29tcHV0ZVN0ZXBMYXRlbmN5VHJhY2tpbmd9KSwgcGx1cyBhIHJlY292ZXJhYmxlXG4gICAqIGFuY2hvci4gSW4gdHVyYm8gbW9kZSwgYHJ1bl9zdGFydGVkYCBpcyBiYWNrZ3JvdW5kZWQgcmF0aGVyIHRoYW5cbiAgICogYXdhaXRlZCwgc28gdGhpcyBpcyBzdGFtcGVkIGF0IHRoZSBwb2ludCB0aGUgcnVudGltZSBzeW50aGVzaXplcyB0aGVcbiAgICogcnVuIGxvY2FsbHkgYW5kIGJlZ2lucyByZXBsYXkgaW5zdGVhZCBvZiBhdCB0aGUgcmVhbCByZXNwb25zZTsgdGhlXG4gICAqIGZpcnN0IHN0ZXAncyBzdGFydCBQT1NUIGlzIHN0aWxsIGNoYWluZWQgb24gdGhlIHJlYWwgYHJ1bl9zdGFydGVkYFxuICAgKiBwcm9taXNlIChzZWUgc3RlcC1leGVjdXRvci50cyksIHNvIFJTRlMgc3RpbGwgZW5kcyB1cCBtZWFzdXJpbmcgdGhlXG4gICAqIGdlbnVpbmUgcnVuX3N0YXJ0ZWQtdG8tZmlyc3Qtc3RlcC1QT1NUIHN0cmV0Y2ggZXZlbiB0aG91Z2ggdGhlIHR3b1xuICAgKiBoYWx2ZXMgb3ZlcmxhcCB1bmRlciB0dXJiby5cbiAgICovXG4gIHJzZnNBbmNob3JNcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFdhbGwtY2xvY2sgbXMgdGhpcyBpbnZvY2F0aW9uJ3Mgc3luY2hyb25vdXMgd29ya2Zsb3ctZnVuY3Rpb24gcmVwbGF5XG4gICAqIHRvb2s6IGZyb20gY2FsbGluZyBgcnVuV29ya2Zsb3dgIHRvIGl0IHRocm93aW5nIHRoZSBzdXNwZW5zaW9uIHRoYXRcbiAgICogc2NoZWR1bGVkIHRoaXMgYmF0Y2guIEV4Y2x1ZGVzIGF3YWl0ZWQgbmV0d29yayBJL08gKHRoZSBzdXNwZW5zaW9uJ3NcbiAgICogZXZlbnQgY29tbWl0cywgdGhlIHN0ZXAncyBvd24gc3RhcnQgUE9TVCkuIFJlcG9ydGVkIGZvciBldmVyeSBiYXRjaCB0aGF0XG4gICAqIHF1YWxpZmllcyBmb3IgVFRGUyBvciBTVFNPLCBub3QganVzdCB0aGUgZmlyc3Qgc3RlcC5cbiAgICpcbiAgICogVGhpcyBpcyB0aGUgRklOQUwgcGFzcyBvbmx5OiB0aGUgb25lIHRoYXQgcmVhY2hlZCBhbmQgc2NoZWR1bGVkIHRoaXNcbiAgICogYmF0Y2guIFZhbGlkIFJTRlMgcGF0aHMgY2FuIHJlcGxheSBtb3JlIHRoYW4gb25jZSBiZWZvcmUgdGhlIGZpcnN0IHN0ZXBcbiAgICogKGUuZy4gYSB3b3JrZmxvdy1ib2R5IGBzZXRBdHRyaWJ1dGVzKClgIGRldG91ciByZXBsYXlzIHR3aWNlKSwgYW5kIGFcbiAgICogcmVkZWxpdmVyeSBvbWl0cyBlYXJsaWVyIGludm9jYXRpb25zJyByZXBsYXkgd29yayBlbnRpcmVseTsgdGhpcyB2YWx1ZSBpc1xuICAgKiBub3QgYWNjdW11bGF0ZWQgYWNyb3NzIHRob3NlIGVhcmxpZXIgcGFzc2VzLiBEbyBub3QgcmVhZCBpdCBhcyBcInRoZVxuICAgKiByZXBsYXkgcG9ydGlvbiBvZiBSU0ZTXCI6IFJTRlMgKHtAbGluayByc2ZzQW5jaG9yTXN9KSBjb3ZlcnMgdGhlIHdob2xlXG4gICAqIHJ1bl9zdGFydGVkLXRvLWZpcnN0LXN0ZXAgd2luZG93LCB0aGlzIGNvdmVycyBvbmx5IHRoZSBsYXN0IHBhc3MuXG4gICAqXG4gICAqIE9uIGEgcmV0YWluZWQgcmVzdW1lIHRoaXMgbWVhc3VyZXMgdGhlIHJlc3VtZSwgbm90IGEgcmVwbGF5LCB3aGljaCBpc1xuICAgKiB3aHkgdGhlIGRpc3RyaWJ1dGlvbiBpcyBiaW1vZGFsIGFuZCB3aHkge0BsaW5rIHJldGFpbmVkfSBpcyByZXBvcnRlZFxuICAgKiBhbG9uZ3NpZGUgaXQgYXMgdGhlIGRpbWVuc2lvbiB0aGF0IHNlcGFyYXRlcyB0aGUgdHdvIG1vZGVzLlxuICAgKi9cbiAgcmVwbGF5TXM/OiBudW1iZXI7XG4gIC8qKiBXaGV0aGVyIHR1cmJvIG1vZGUgaXMgYWN0aXZlIGZvciB0aGlzIGludm9jYXRpb24uICovXG4gIHR1cmJvOiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciBhIHJldGFpbmVkIFZNIHNlc3Npb24gc2VydmVkIHRoaXMgYmF0Y2gsIGFzIG9wcG9zZWQgdG8gYSBmdWxsXG4gICAqIHJlcGxheSBmcm9tIHRoZSBldmVudCBsb2cuIFJlcG9ydGVkIGFzIGEgYHJldGFpbmVkYCBlbnRyeSBpblxuICAgKiB7QGxpbmsgU3RlcExhdGVuY3lFdmVudERhdGEub3B0aW1pemF0aW9uc30sIGFsb25nc2lkZSBgdHVyYm9gLlxuICAgKi9cbiAgcmV0YWluZWQ6IGJvb2xlYW47XG59XG5cbi8qKlxuICogTW9zdCBuZWdhdGl2ZSByYXcgZHVyYXRpb24gc3RpbGwgYXR0cmlidXRlZCB0byBjcm9zcy1tYWNoaW5lIGNsb2NrIHNrZXdcbiAqIChhbmQgY2xhbXBlZCB0byAwKS4gQW55dGhpbmcgbW9yZSBuZWdhdGl2ZSBtZWFucyBhIGNvcnJ1cHQgYW5jaG9yIChlLmcuIGFcbiAqIG1pcy1kZWNvZGVkIHJ1bi1JRCB0aW1lc3RhbXApIGFuZCB0aGUgc2FtcGxlIGlzIGRyb3BwZWQgaW5zdGVhZDogYVxuICogc3lzdGVtYXRpY2FsbHkgY29ycnVwdCBhbmNob3Igd291bGQgb3RoZXJ3aXNlIHJlcG9ydCBhbiBleGFjdC16ZXJvIGxhdGVuY3lcbiAqIG9uIGV2ZXJ5IHNhbXBsZSwgc2lsZW50bHkgZHJhZ2dpbmcgZW50aXJlIHBlcmNlbnRpbGUgZGlzdHJpYnV0aW9ucyB0byAwXG4gKiByYXRoZXIgdGhhbiBzdXJmYWNpbmcgYXMgbWlzc2luZyBkYXRhLlxuICovXG5jb25zdCBNQVhfQ0xPQ0tfU0tFV19NUyA9IDYwXzAwMDtcblxuLyoqIExhdGVuY3kgdGVsZW1ldHJ5IGF0dGFjaGVkIHRvIGEgc3RlcCdzIHRlcm1pbmFsIGV2ZW50J3MgYGV2ZW50RGF0YWAuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0ZXBMYXRlbmN5RXZlbnREYXRhIHtcbiAgdHRmcz86IG51bWJlcjtcbiAgc3Rzbz86IG51bWJlcjtcbiAgc3RlcENvdW50PzogbnVtYmVyO1xuICBldmVudENvdW50PzogbnVtYmVyO1xuICAvKiogQ2xpZW50LW1lYXN1cmVkIHJ1bl9zdGFydGVkIOKGkiBmaXJzdCBzdGVwJ3Mgc3RhcnQgUE9TVCwgbXMuICovXG4gIHJzZnM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBDbGllbnQtbWVhc3VyZWQgd2FsbC1jbG9jayBtcyBvZiB0aGUgRklOQUwgcGFzcyB0aGF0IHNjaGVkdWxlZCB0aGlzXG4gICAqIGJhdGNoIChzZWUge0BsaW5rIFN0ZXBMYXRlbmN5VHJhY2tpbmcucmVwbGF5TXN9KTsgbm90IGFjY3VtdWxhdGVkXG4gICAqIGFjcm9zcyBlYXJsaWVyIHBhc3Nlcywgc28gaXQgbXVzdCBub3QgYmUgcmVhZCBhcyBcInRoZSByZXBsYXkgcG9ydGlvbiBvZlxuICAgKiBgcnNmc2BcIi4gUHJlc2VudCB3aGVuZXZlciBgdHRmc2Agb3IgYHN0c29gIGlzLlxuICAgKi9cbiAgZmluYWxTY2hlZHVsaW5nUmVwbGF5PzogbnVtYmVyO1xuICAvKipcbiAgICogQWN0aXZlIHJ1bnRpbWUgbW9kZXMgZm9yIHRoaXMgbWVhc3VyZW1lbnQ6IGB0dXJib2AsIGBsYXp5U3RlcFN0YXJ0YCxcbiAgICogYG9wdGltaXN0aWNTdGFydGAsIGFuZCBgcmV0YWluZWRgIChhIHJldGFpbmVkIFZNIHNlcnZlZCB0aGUgYmF0Y2g7IGl0c1xuICAgKiBhYnNlbmNlIG1lYW5zIGEgZnVsbCByZXBsYXkpLiBUaGUgc2VydmVyIHR1cm5zIGVhY2gga25vd24gZW50cnkgaW50byBhXG4gICAqIGJvdW5kZWQgYm9vbGVhbiB0YWcgb24gZXZlcnkgbGF0ZW5jeSBtZXRyaWMuXG4gICAqL1xuICBvcHRpbWl6YXRpb25zPzogc3RyaW5nW107XG59XG5cbi8qKlxuICogRXZlbnQgdHlwZXMgdGhhdCBkaXNxdWFsaWZ5IFRURlMgd2hlbiBwcmVzZW50IGluIHRoZSBldmVudCBsb2cgYXQgdGhlIHRpbWVcbiAqIHRoZSBydW4ncyBmaXJzdCBzdGVwIGJhdGNoIGlzIHNjaGVkdWxlZDpcbiAqXG4gKiAtIEFueSBzdGVwIGV2ZW50IG1lYW5zIHRoaXMgaXMgbm90IHRoZSBydW4ncyBmaXJzdCBzdGVwIGV4ZWN1dGlvbi5cbiAqIC0gYGhvb2tfcmVjZWl2ZWRgIC8gYHdhaXRfY3JlYXRlZGAgLyBgd2FpdF9jb21wbGV0ZWRgIG1lYW4gdGhlIHJ1bidzIHBhdGggdG9cbiAqICAgdGhlIGZpcnN0IHN0ZXAgZGVwZW5kZWQgb24gdXNlci1kcml2ZW4gdGltaW5nIChhIHdlYmhvb2sgYXJyaXZpbmcsIGFcbiAqICAgc2xlZXAgZWxhcHNpbmcpLCBzbyB0aGUgbWVhc3VyZW1lbnQgd291bGQgbm90IHJlZmxlY3QgcnVudGltZSBvdmVyaGVhZC5cbiAqXG4gKiBEZWxpYmVyYXRlbHkgYWJzZW50LCB3aXRoIHRoZWlyIGNvc3Qgc3VidHJhY3RlZCBpbnN0ZWFkOlxuICpcbiAqIC0gYGhvb2tfY3JlYXRlZGA6IGEgZmlyZS1hbmQtZm9yZ2V0IGBjcmVhdGVIb29rKClgIGJlZm9yZSB0aGUgZmlyc3Qgc3RlcFxuICogICBjb21taXRzIGluIHRoZSBzYW1lIGludm9jYXRpb24sIHdob3NlIG1lYXN1cmVkIGR1cmF0aW9uIGlzIHN1YnRyYWN0ZWQgdmlhXG4gKiAgIHtAbGluayBTdGVwTGF0ZW5jeVRyYWNraW5nLnByZVN0ZXBCbG9ja2luZ01zfS5cbiAqIC0gYGF0dHJfc2V0YCAod29ya2Zsb3ctYm9keSBgc2V0QXR0cmlidXRlc2ApOiByZXNvbHZlcyB0aHJvdWdoXG4gKiAgIGFuIGV4dHJhIHJlcGxheSBiZWZvcmUgc3RlcHMgcnVuLiBTdWJ0cmFjdGVkIGJ5IGVuZGluZyB0aGUgbWVhc3VyZW1lbnQgYXRcbiAqICAgdGhlIGZpcnN0IGF0dHIgd3JpdGUncyB0aW1lc3RhbXAgaW5zdGVhZDsgc2VlXG4gKiAgIHtAbGluayBTdGVwTGF0ZW5jeVRyYWNraW5nLnByZVN0ZXBBdHRyU3RhcnRNc30uXG4gKi9cbmNvbnN0IFRURlNfRElTUVVBTElGWUlOR19FVkVOVF9UWVBFUzogUmVhZG9ubHlTZXQ8RXZlbnRbJ2V2ZW50VHlwZSddPiA9IG5ldyBTZXQoXG4gIFtcbiAgICAnc3RlcF9jcmVhdGVkJyxcbiAgICAnc3RlcF9zdGFydGVkJyxcbiAgICAnc3RlcF9jb21wbGV0ZWQnLFxuICAgICdzdGVwX2ZhaWxlZCcsXG4gICAgJ3N0ZXBfcmV0cnlpbmcnLFxuICAgICdob29rX3JlY2VpdmVkJyxcbiAgICAnd2FpdF9jcmVhdGVkJyxcbiAgICAnd2FpdF9jb21wbGV0ZWQnLFxuICBdXG4pO1xuXG4vKipcbiAqIERlY2lkZSwgZnJvbSB0aGUgb3JjaGVzdHJhdG9yJ3MgdmlldyBvZiB0aGUgZXZlbnQgbG9nLCB3aGV0aGVyIHRoZSBpbmxpbmVcbiAqIHN0ZXAgYmF0Y2ggYWJvdXQgdG8gZXhlY3V0ZSBxdWFsaWZpZXMgZm9yIFRURlMgYW5kL29yIFNUU08gbWVhc3VyZW1lbnQuXG4gKiBSZXR1cm5zIHVuZGVmaW5lZCB3aGVuIG5laXRoZXIgYXBwbGllcy4gQ2FsbGVkIG9uY2UgcGVyIGJhdGNoOyB0aGUgcmVzdWx0XG4gKiBpcyBwYXNzZWQgdG8gdGhlIGJhdGNoJ3MgZmlyc3Qgc3RlcCBvbmx5LCBzbyBhIHBhcmFsbGVsIGZpcnN0IGJhdGNoIGVtaXRzIGFcbiAqIHNpbmdsZSBzYW1wbGUgcmF0aGVyIHRoYW4gb25lIHBlciBzaWJsaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVN0ZXBMYXRlbmN5VHJhY2tpbmcocGFyYW1zOiB7XG4gIC8qKiBUaGUgb3JjaGVzdHJhdG9yJ3MgY3VycmVudCBpbi1tZW1vcnkgZXZlbnQgbG9nIChhc2NlbmRpbmcgb3JkZXIpLiAqL1xuICBldmVudHM6IEV2ZW50W107XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgaW52b2NhdGlvbidzIGluaXRpYWwgZXZlbnQgbG9hZCBjb250YWluZWQgbm90aGluZyBiZXlvbmRcbiAgICogcnVuX2NyZWF0ZWQvcnVuX3N0YXJ0ZWQvYXR0cl9zZXQuIFByZS1leGlzdGluZyBob29rIGV2ZW50cyB3ZXJlIHdyaXR0ZW5cbiAgICogYnkgYW4gZWFybGllciBpbnZvY2F0aW9uLCBzbyB0aGUgdGltZSB0aGV5IGFkZGVkIChpbmNsdWRpbmcgdGhlIHF1ZXVlXG4gICAqIGhvcCBiYWNrIHRvIHRoaXMgaW52b2NhdGlvbikgaXMgdW5tZWFzdXJhYmxlIGFuZCBkaXNxdWFsaWZpZXMgVFRGUy5cbiAgICogYXR0cl9zZXQgaXMgcGVybWl0dGVkOiBhIHJlZGVsaXZlcnkgY2FuIGxhbmQgYWZ0ZXIgYSBjb21taXR0ZWQgcHJlLXN0ZXBcbiAgICogYXR0cl9zZXQsIGFuZCB0aGUgZGV0b3VyIGl0IG1hcmtzIGlzIHN1YnRyYWN0ZWQgdmlhIGBwcmVTdGVwQXR0clN0YXJ0TXNgXG4gICAqIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggaW52b2NhdGlvbiB3cm90ZSBpdC5cbiAgICovXG4gIGludm9jYXRpb25TdGFydGVkQ2xlYW46IGJvb2xlYW47XG4gIC8qKiBFcG9jaCBtcyBvZiBydW4gY3JlYXRpb24sIGlmIHJlY292ZXJhYmxlLiBBYnNlbnQgZGlzcXVhbGlmaWVzIFRURlMuICovXG4gIHJ1bkNyZWF0ZWRBdE1zOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBFcG9jaCBtcyB0aGUgYHJ1bl9zdGFydGVkYCByZXNwb25zZSB3YXMgcmVjZWl2ZWQvcGFyc2VkIGJ5IHRoZSBTREsgKG9yLFxuICAgKiB1bmRlciB0dXJibywgdGhlIGluc3RhbnQgdGhlIHJ1biB3YXMgc3ludGhlc2l6ZWQgbG9jYWxseTsgc2VlXG4gICAqIHtAbGluayBTdGVwTGF0ZW5jeVRyYWNraW5nLnJzZnNBbmNob3JNc30pLiBBYnNlbnQgZGlzcXVhbGlmaWVzIFJTRlMuXG4gICAqL1xuICBydW5TdGFydGVkUmVjZWl2ZWRBdE1zOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBXYWxsLWNsb2NrIG1zIHRoaXMgc3VzcGVuc2lvbidzIGBydW5Xb3JrZmxvd2AgY2FsbCBzcGVudCBleGVjdXRpbmdcbiAgICogc3luY2hyb25vdXNseSBiZWZvcmUgdGhyb3dpbmc6IHRoZSBGSU5BTCByZXBsYXkgcGFzcyBvbmx5LCBub3RcbiAgICogYWNjdW11bGF0ZWQgYWNyb3NzIGVhcmxpZXIgcGFzc2VzLiBTZWVcbiAgICoge0BsaW5rIFN0ZXBMYXRlbmN5VHJhY2tpbmcucmVwbGF5TXN9LlxuICAgKi9cbiAgcmVwbGF5TXM6IG51bWJlcjtcbiAgLyoqIFNlZSB7QGxpbmsgU3RlcExhdGVuY3lUcmFja2luZy5wcmVTdGVwQmxvY2tpbmdNc30uICovXG4gIHByZVN0ZXBCbG9ja2luZ01zOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgYWNjdW11bGF0b3IncyB2YWx1ZSBhcyBvZiB0aGUgc3VzcGVuc2lvbiB0aGF0IHdyb3RlIHRoZSBydW4ncyBmaXJzdFxuICAgKiBhdHRyX3NldCAoaXRzIGhvb2sgcGhhc2UgcnVucyBiZWZvcmUgaXRzIGF0dHIgd3JpdGVzKS4gV2hlbiB0aGVcbiAgICogbWVhc3VyZW1lbnQgZW5kcyBhdCB0aGUgYXR0ciB3cml0ZSwgb25seSBob29rIHRpbWUgZnJvbSBiZWZvcmUgdGhhdFxuICAgKiBwb2ludCBtYXkgYmUgc3VidHJhY3RlZDsgbGF0ZXIgaG9vayB3cml0ZXMgZmFsbCBvdXRzaWRlIHRoZSBtZWFzdXJlZFxuICAgKiB3aW5kb3cuIFVuZGVmaW5lZCB3aGVuIG5vIGF0dHIgc3VzcGVuc2lvbiBoYXBwZW5lZCBpbiB0aGlzIGludm9jYXRpb25cbiAgICogKGUuZy4gdGhlIGF0dHJfc2V0IHdhcyBsb2FkZWQgZnJvbSBhIHJlZGVsaXZlcnkncyBzbmFwc2hvdCwgd2hlcmUgbm9cbiAgICogc2FtZS1pbnZvY2F0aW9uIGhvb2sgdGltZSBwcmVjZWRlcyBpdCkuXG4gICAqL1xuICBwcmVTdGVwQmxvY2tpbmdCZWZvcmVBdHRyTXM6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHN1c3BlbnNpb24gdGhhdCBzY2hlZHVsZWQgdGhpcyBiYXRjaCBhbHNvIGNyZWF0ZWQgd2FpdHMuXG4gICAqIFRob3NlIGB3YWl0X2NyZWF0ZWRgIHdyaXRlcyBhcmUgbm90IGluIGBldmVudHNgIHlldCAodGhleSB3ZXJlIGNvbW1pdHRlZFxuICAgKiBieSB0aGlzIHN1c3BlbnNpb24gcGFzcyksIHNvIHRoZXkgbXVzdCBiZSByZXBvcnRlZCBzZXBhcmF0ZWx5LiBBXG4gICAqIHdhaXQgZGlzcXVhbGlmaWVzIGJvdGggbWVhc3VyZW1lbnRzLlxuICAgKi9cbiAgc3VzcGVuc2lvbkhhc1dhaXRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2hldGhlciB0aGUgc3VzcGVuc2lvbiB0aGF0IHNjaGVkdWxlZCB0aGlzIGJhdGNoIGFsc28gY3JlYXRlZCBob29rc1xuICAgKiAoYWxzbyBub3QgaW4gYGV2ZW50c2AgeWV0KS4gSG9va3Mga2VlcCBUVEZTIGVsaWdpYmxlICh0aGVpciBtZWFzdXJlZFxuICAgKiB3cml0ZSB0aW1lIGlzIHN1YnRyYWN0ZWQgdmlhIGBwcmVTdGVwQmxvY2tpbmdNc2ApIGJ1dCBkaXNxdWFsaWZ5IFNUU08sXG4gICAqIHdoaWNoIGlzIG9ubHkgbWVhbmluZ2Z1bCBmb3IgYSBwdXJlIGJhY2stdG8tYmFjayBzdGVwIGdhcC5cbiAgICovXG4gIHN1c3BlbnNpb25DcmVhdGVkSG9va3M6IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHR1cmJvIG1vZGUgaXMgYWN0aXZlIGZvciB0aGlzIGludm9jYXRpb24uICovXG4gIHR1cmJvOiBib29sZWFuO1xuICAvKiogU2VlIHtAbGluayBTdGVwTGF0ZW5jeVRyYWNraW5nLnJldGFpbmVkfS4gKi9cbiAgcmV0YWluZWQ6IGJvb2xlYW47XG59KTogU3RlcExhdGVuY3lUcmFja2luZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHsgZXZlbnRzIH0gPSBwYXJhbXM7XG5cbiAgbGV0IHR0ZnNFbGlnaWJsZSA9XG4gICAgcGFyYW1zLmludm9jYXRpb25TdGFydGVkQ2xlYW4gJiZcbiAgICBwYXJhbXMucnVuQ3JlYXRlZEF0TXMgIT09IHVuZGVmaW5lZCAmJlxuICAgICFwYXJhbXMuc3VzcGVuc2lvbkhhc1dhaXRzO1xuICBsZXQgcHJlU3RlcEF0dHJTdGFydE1zOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGlmICh0dGZzRWxpZ2libGUpIHtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgaWYgKFRURlNfRElTUVVBTElGWUlOR19FVkVOVF9UWVBFUy5oYXMoZXZlbnQuZXZlbnRUeXBlKSkge1xuICAgICAgICB0dGZzRWxpZ2libGUgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoZXZlbnQuZXZlbnRUeXBlID09PSAnYXR0cl9zZXQnKSB7XG4gICAgICAgIGNvbnN0IGF0dHJTdGFydE1zID0gKyhldmVudC5vY2N1cnJlZEF0ID8/IGV2ZW50LmNyZWF0ZWRBdCk7XG4gICAgICAgIHByZVN0ZXBBdHRyU3RhcnRNcyA9XG4gICAgICAgICAgcHJlU3RlcEF0dHJTdGFydE1zID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gYXR0clN0YXJ0TXNcbiAgICAgICAgICAgIDogTWF0aC5taW4ocHJlU3RlcEF0dHJTdGFydE1zLCBhdHRyU3RhcnRNcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gU1RTTzogdGhlIHR3byBzdGVwcyByYW4gYmFjay10by1iYWNrLCBzbyB0aGUgbmV3ZXN0IGtub3duIGV2ZW50IGlzIHRoZVxuICAvLyBwcmV2aW91cyBzdGVwJ3MgdGVybWluYWwgZXZlbnQsIHdpdGggbm90aGluZyAoaG9va19yZWNlaXZlZCwgd2FpdHMsXG4gIC8vIGF0dHJfc2V0LCAuLi4pIGluIGJldHdlZW4gYW5kIHRoaXMgc3VzcGVuc2lvbiBzY2hlZHVsaW5nIG5vdGhpbmcgYnV0XG4gIC8vIHN0ZXBzLlxuICBsZXQgcHJldlN0ZXBFbmRNczogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBsZXQgc3RlcENvdW50OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGxldCBldmVudENvdW50OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGxhc3RFdmVudCA9IGV2ZW50c1tldmVudHMubGVuZ3RoIC0gMV07XG4gIGlmIChcbiAgICAhcGFyYW1zLnN1c3BlbnNpb25IYXNXYWl0cyAmJlxuICAgICFwYXJhbXMuc3VzcGVuc2lvbkNyZWF0ZWRIb29rcyAmJlxuICAgIGxhc3RFdmVudCAmJlxuICAgIChsYXN0RXZlbnQuZXZlbnRUeXBlID09PSAnc3RlcF9jb21wbGV0ZWQnIHx8XG4gICAgICBsYXN0RXZlbnQuZXZlbnRUeXBlID09PSAnc3RlcF9mYWlsZWQnKVxuICApIHtcbiAgICBwcmV2U3RlcEVuZE1zID0gKyhsYXN0RXZlbnQub2NjdXJyZWRBdCA/PyBsYXN0RXZlbnQuY3JlYXRlZEF0KTtcbiAgICBjb25zdCB0ZXJtaW5hbFN0ZXBJZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgaWYgKFxuICAgICAgICAoZXZlbnQuZXZlbnRUeXBlID09PSAnc3RlcF9jb21wbGV0ZWQnIHx8XG4gICAgICAgICAgZXZlbnQuZXZlbnRUeXBlID09PSAnc3RlcF9mYWlsZWQnKSAmJlxuICAgICAgICBldmVudC5jb3JyZWxhdGlvbklkICE9PSB1bmRlZmluZWRcbiAgICAgICkge1xuICAgICAgICB0ZXJtaW5hbFN0ZXBJZHMuYWRkKGV2ZW50LmNvcnJlbGF0aW9uSWQpO1xuICAgICAgfVxuICAgIH1cbiAgICBzdGVwQ291bnQgPSB0ZXJtaW5hbFN0ZXBJZHMuc2l6ZTtcbiAgICBldmVudENvdW50ID0gZXZlbnRzLmxlbmd0aDtcbiAgfVxuXG4gIC8vIFJTRlMgc2hhcmVzIFRURlMncyBlbGlnaWJpbGl0eSBleGFjdGx5IChzYW1lIGV2ZW50LWxvZy93YWl0IGNoZWNrcyksXG4gIC8vIHBsdXMgaXRzIG93biBhbmNob3IgYmVpbmcgcmVjb3ZlcmFibGUuXG4gIGNvbnN0IHJzZnNFbGlnaWJsZSA9XG4gICAgdHRmc0VsaWdpYmxlICYmIHBhcmFtcy5ydW5TdGFydGVkUmVjZWl2ZWRBdE1zICE9PSB1bmRlZmluZWQ7XG5cbiAgaWYgKCF0dGZzRWxpZ2libGUgJiYgcHJldlN0ZXBFbmRNcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKHR0ZnNFbGlnaWJsZVxuICAgICAgPyB7XG4gICAgICAgICAgdHRmc0FuY2hvck1zOiBwYXJhbXMucnVuQ3JlYXRlZEF0TXMsXG4gICAgICAgICAgLy8gV2hlbiB0aGUgbWVhc3VyZW1lbnQgZW5kcyBhdCB0aGUgZmlyc3QgYXR0ciB3cml0ZSwgb25seSBob29rXG4gICAgICAgICAgLy8gdGltZSBmcm9tIGJlZm9yZSB0aGF0IHBvaW50IGlzIGluc2lkZSB0aGUgbWVhc3VyZWQgd2luZG93LlxuICAgICAgICAgIHByZVN0ZXBCbG9ja2luZ01zOlxuICAgICAgICAgICAgcHJlU3RlcEF0dHJTdGFydE1zICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgPyAocGFyYW1zLnByZVN0ZXBCbG9ja2luZ0JlZm9yZUF0dHJNcyA/PyAwKVxuICAgICAgICAgICAgICA6IHBhcmFtcy5wcmVTdGVwQmxvY2tpbmdNcyxcbiAgICAgICAgICAuLi4ocHJlU3RlcEF0dHJTdGFydE1zICE9PSB1bmRlZmluZWQgPyB7IHByZVN0ZXBBdHRyU3RhcnRNcyB9IDoge30pLFxuICAgICAgICB9XG4gICAgICA6IHt9KSxcbiAgICAuLi4ocnNmc0VsaWdpYmxlID8geyByc2ZzQW5jaG9yTXM6IHBhcmFtcy5ydW5TdGFydGVkUmVjZWl2ZWRBdE1zIH0gOiB7fSksXG4gICAgLi4uKHByZXZTdGVwRW5kTXMgIT09IHVuZGVmaW5lZFxuICAgICAgPyB7IHByZXZTdGVwRW5kTXMsIHN0ZXBDb3VudCwgZXZlbnRDb3VudCB9XG4gICAgICA6IHt9KSxcbiAgICAvLyBOb3QgZ2F0ZWQgb24gcnNmc0VsaWdpYmxlOiByZXBsYXkgY29zdCBpcyBtZWFuaW5nZnVsIGZvciBldmVyeSBiYXRjaFxuICAgIC8vIHRoaXMgZnVuY3Rpb24gcmV0dXJucyB0cmFja2luZyBmb3IuIEdhdGluZyBpdCBvbiBSU0ZTIGxlZnQgdGhlIFNUU09cbiAgICAvLyBwb3B1bGF0aW9uIOKAlCBvcmRpbmFyeSBzdGVwLXRvLXN0ZXAgdHJhbnNpdGlvbnMsIHRoZSBidWxrIG9mIHN0ZXBcbiAgICAvLyBzY2hlZHVsaW5nIOKAlCB3aXRoIG5vIHJlcGxheS1jb3N0IHRlbGVtZXRyeSBhdCBhbGwuXG4gICAgcmVwbGF5TXM6IHBhcmFtcy5yZXBsYXlNcyxcbiAgICB0dXJibzogcGFyYW1zLnR1cmJvLFxuICAgIHJldGFpbmVkOiBwYXJhbXMucmV0YWluZWQsXG4gIH07XG59XG5cbi8qKlxuICogQ29tcHV0ZSB0aGUgbGF0ZW5jeSB0ZWxlbWV0cnkgdG8gYXR0YWNoIHRvIHRoZSBzdGVwJ3MgdGVybWluYWwgZXZlbnQuXG4gKiBDYWxsZWQgYnkgYGV4ZWN1dGVTdGVwYCB3aXRoIHRoZSB3YWxsLWNsb2NrIHRpbWVzdGFtcCB0YWtlbiBpbW1lZGlhdGVseVxuICogYmVmb3JlIHVzZXIgc3RlcCBjb2RlIHJ1bnMuIFJldHVybnMgdW5kZWZpbmVkIHdoZW4gdGhlcmUgaXMgbm90aGluZyB0b1xuICogcmVwb3J0IChubyB0cmFja2luZywgb3IgYSByZXRyeSBhdHRlbXB0OyByZXRyaWVzIG1lYXN1cmUgbmVpdGhlciBUVEZTIG5vclxuICogU1RTTykuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wdXRlU3RlcExhdGVuY3lFdmVudERhdGEocGFyYW1zOiB7XG4gIHRyYWNraW5nOiBTdGVwTGF0ZW5jeVRyYWNraW5nIHwgdW5kZWZpbmVkO1xuICAvKiogYERhdGUubm93KClgIHRha2VuIGltbWVkaWF0ZWx5IGJlZm9yZSB1c2VyIHN0ZXAgY29kZSBiZWdhbiBleGVjdXRpbmcuICovXG4gIHN0ZXBDb2RlU3RhcnRlZEF0TXM6IG51bWJlcjtcbiAgLyoqXG4gICAqIGBEYXRlLm5vdygpYCB0YWtlbiBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGZpcnN0IHN0ZXAncyBzdGFydCBQT1NUXG4gICAqIChgc3RlcF9zdGFydGVkYCkgd2FzIGlzc3VlZC4gUHJlc2VudCBvbmx5IGZvciB0aGUgbGF6eSBpbmxpbmUgc3RlcHMgUlNGU1xuICAgKiBjYXJlcyBhYm91dDsgc2VlIHRoZSBjYWxsIHNpdGVzIGluIHN0ZXAtZXhlY3V0b3IudHMuXG4gICAqL1xuICBzdGVwU3RhcnRQb3N0U2VudEF0TXM6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgYXR0ZW1wdDogbnVtYmVyO1xuICAvKiogV2hldGhlciB0aGlzIHN0ZXAgd2FzIHN0YXJ0ZWQgbGF6aWx5IChubyBzZXBhcmF0ZSBzdGVwX2NyZWF0ZWQgd3JpdGUpLiAqL1xuICBsYXp5U3RlcFN0YXJ0OiBib29sZWFuO1xuICAvKiogV2hldGhlciB0aGUgYm9keSByYW4gb3B0aW1pc3RpY2FsbHksIHdpdGhvdXQgYXdhaXRpbmcgc3RlcF9zdGFydGVkLiAqL1xuICBvcHRpbWlzdGljU3RhcnQ6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBzdGVwJ3MgYHN0ZXBfY3JlYXRlZGAgKyBgc3RlcF9zdGFydGVkYCBwYWlyIHdhcyBwcmUtY2xhaW1lZFxuICAgKiBpbnNpZGUgdGhlIHN1c3BlbnNpb24gaGFuZGxlcidzIGJhdGNoZWQgZmFuLW91dCB3cml0ZSAobm8gc3RhcnQgUE9TVCBvZlxuICAgKiBpdHMgb3duIGF0IGFsbCkuXG4gICAqL1xuICBwcmVjbGFpbWVkU3RhcnQ/OiBib29sZWFuO1xufSk6IFN0ZXBMYXRlbmN5RXZlbnREYXRhIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgeyB0cmFja2luZyB9ID0gcGFyYW1zO1xuICBpZiAoIXRyYWNraW5nIHx8IHBhcmFtcy5hdHRlbXB0ICE9PSAxKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIFNtYWxsIG5lZ2F0aXZlIGR1cmF0aW9ucyBjbGFtcCB0byAwOiBjcm9zcy1pbnZvY2F0aW9uIHRpbWVzdGFtcHMgY2FuXG4gIC8vIGNvbWUgZnJvbSBhbm90aGVyIG1hY2hpbmUncyBjbG9jaywgc28gYm91bmRlZCBza2V3IG11c3Qgbm90IHByb2R1Y2VcbiAgLy8gbmVnYXRpdmUgdmFsdWVzLiBEdXJhdGlvbnMgbW9yZSBuZWdhdGl2ZSB0aGFuIE1BWF9DTE9DS19TS0VXX01TIGFyZSBub3RcbiAgLy8gc2tldyBidXQgYSBjb3JydXB0IGFuY2hvciwgYW5kIHRoZSBzYW1wbGUgaXMgZHJvcHBlZCAoc2VlIHRoZSBjb25zdGFudCdzXG4gIC8vIGRvYyBjb21tZW50KS5cbiAgLy9cbiAgLy8gQSBwcmUtc3RlcCBzZXRBdHRyaWJ1dGVzIGRldG91ciBlbmRzIHRoZSBtZWFzdXJlbWVudCBhdCB0aGUgZmlyc3QgYXR0clxuICAvLyB3cml0ZSBpbnN0ZWFkIG9mIHRoZSBzdGVwJ3MgY29kZSBzdGFydDogdGhlIHJlbWFpbmRlciBpcyB0aGUgZHVyYXRpb25cbiAgLy8gb2YgdGhlIHNldEF0dHJpYnV0ZXMgY2FsbCAocmVzb2x2ZWQgdmlhIGFuIGV4dHJhIHJlcGxheSksIHdoaWNoIGlzXG4gIC8vIHN1YnRyYWN0ZWQgcmF0aGVyIHRoYW4gZGlzcXVhbGlmeWluZyB0aGUgc2FtcGxlLiBJbiB0aGF0IGNhc2VcbiAgLy8gYHRyYWNraW5nLnByZVN0ZXBCbG9ja2luZ01zYCBhbHJlYWR5IGhvbGRzIG9ubHkgdGhlIGhvb2sgdGltZSBmcm9tXG4gIC8vIEJFRk9SRSB0aGUgYXR0ciB3cml0ZTsgaG9vayB3cml0ZXMgYWZ0ZXIgdGhlIHdpbmRvdyBjbG9zZWQgYXJlIGV4Y2x1ZGVkXG4gIC8vIGJ5IGNvbXB1dGVTdGVwTGF0ZW5jeVRyYWNraW5nIChzZWUgcHJlU3RlcEJsb2NraW5nQmVmb3JlQXR0ck1zKS5cbiAgY29uc3QgdHRmc0VuZE1zID0gdHJhY2tpbmcucHJlU3RlcEF0dHJTdGFydE1zID8/IHBhcmFtcy5zdGVwQ29kZVN0YXJ0ZWRBdE1zO1xuICBjb25zdCByYXdUdGZzID1cbiAgICB0cmFja2luZy50dGZzQW5jaG9yTXMgIT09IHVuZGVmaW5lZFxuICAgICAgPyB0dGZzRW5kTXMgLSB0cmFja2luZy50dGZzQW5jaG9yTXMgLSAodHJhY2tpbmcucHJlU3RlcEJsb2NraW5nTXMgPz8gMClcbiAgICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCB0dGZzID1cbiAgICByYXdUdGZzICE9PSB1bmRlZmluZWQgJiYgcmF3VHRmcyA+PSAtTUFYX0NMT0NLX1NLRVdfTVNcbiAgICAgID8gTWF0aC5tYXgoMCwgcmF3VHRmcylcbiAgICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCByYXdTdHNvID1cbiAgICB0cmFja2luZy5wcmV2U3RlcEVuZE1zICE9PSB1bmRlZmluZWRcbiAgICAgID8gcGFyYW1zLnN0ZXBDb2RlU3RhcnRlZEF0TXMgLSB0cmFja2luZy5wcmV2U3RlcEVuZE1zXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgY29uc3Qgc3RzbyA9XG4gICAgcmF3U3RzbyAhPT0gdW5kZWZpbmVkICYmIHJhd1N0c28gPj0gLU1BWF9DTE9DS19TS0VXX01TXG4gICAgICA/IE1hdGgubWF4KDAsIHJhd1N0c28pXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgLy8gUlNGUyBlbmRzIGF0IHRoZSBhY3R1YWwgc3RhcnQtUE9TVCBpbnN0YW50LCBub3QgYXQgdHRmc0VuZE1zOiB1bmxpa2VcbiAgLy8gVFRGUyBpdCBpcyBub3Qgc3ViamVjdCB0byB0aGUgcHJlLXN0ZXAgYXR0ci13cml0ZSBzaG9ydGN1dCwgc28gYVxuICAvLyBwcmUtc3RlcCBzZXRBdHRyaWJ1dGVzIGRldG91ciAocmFyZSkgbWFrZXMgUlNGUyBpbmNsdWRlIHRoZSBkZXRvdXJcbiAgLy8gd2hpbGUgVFRGUyBleGNsdWRlcyBpdC4gYGZpbmFsU2NoZWR1bGluZ1JlcGxheWAgaXMgYSBkaXJlY3QgcGFzc3Rocm91Z2hcbiAgLy8gb2YgYHRyYWNraW5nLnJlcGxheU1zYCwgdGhlIEZJTkFMIHJlcGxheSBwYXNzIG9ubHkgKHNlZVxuICAvLyBTdGVwTGF0ZW5jeVRyYWNraW5nLnJlcGxheU1zKSwgc28gbm8gZnVydGhlciBzdWJ0cmFjdGlvbiBhcHBsaWVzLCBidXRcbiAgLy8gaXQgYWxzbyBtZWFucyBpdCBpcyBOT1QgYWNjdW11bGF0ZWQgYWNyb3NzIGFueSBlYXJsaWVyIHByZS1maXJzdC1zdGVwXG4gIC8vIHBhc3NlcyAoZS5nLiBhIHNldEF0dHJpYnV0ZXMgZGV0b3VyKSBhbmQgbXVzdCBub3QgYmUgcmVhZCBhcyBcInRoZVxuICAvLyByZXBsYXkgcG9ydGlvbiBvZiByc2ZzXCI7IHJzZnMgY292ZXJzIHRoZSB3aG9sZSB3aW5kb3cuXG4gIC8vXG4gIC8vIGZpbmFsU2NoZWR1bGluZ1JlcGxheSBkdXBsaWNhdGVzIHdoYXQgT1RFTCBhbHJlYWR5IGNhcHR1cmVzIG9uIHRoZVxuICAvLyBydW4vaW52b2NhdGlvbiBzcGFuLCBidXQgaXMgZGVsaWJlcmF0ZWx5IGNvbGxlY3RlZCBhcyBjbGllbnQgdGVsZW1ldHJ5XG4gIC8vIHNvIHRoZSBzZXJ2ZXIgY2FuIGVtaXQgaXQgYXMgYW4gVU5TQU1QTEVELCBmdWxsLXBvcHVsYXRpb24gbWV0cmljOlxuICAvLyB3b3JrZmxvdy1zZXJ2ZXIncyBzZXJ2ZXIgc3BhbnMgYXJlIGhlYXZpbHkgc2FtcGxlZCBpbiBwcm9kdWN0aW9uICh+NyUpLFxuICAvLyBzbyB0aGV5IGNhbm5vdCBzZXJ2ZSBhcyB0aGUgZGFzaGJvYXJkJ3MgZXhhY3QgVFRGUyBkZWNvbXBvc2l0aW9uLlxuICBjb25zdCByc2ZzID1cbiAgICB0cmFja2luZy5yc2ZzQW5jaG9yTXMgIT09IHVuZGVmaW5lZCAmJlxuICAgIHBhcmFtcy5zdGVwU3RhcnRQb3N0U2VudEF0TXMgIT09IHVuZGVmaW5lZFxuICAgICAgPyBNYXRoLm1heCgwLCBwYXJhbXMuc3RlcFN0YXJ0UG9zdFNlbnRBdE1zIC0gdHJhY2tpbmcucnNmc0FuY2hvck1zKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGZpbmFsU2NoZWR1bGluZ1JlcGxheSA9XG4gICAgdHJhY2tpbmcucmVwbGF5TXMgIT09IHVuZGVmaW5lZFxuICAgICAgPyBNYXRoLm1heCgwLCB0cmFja2luZy5yZXBsYXlNcylcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gIGlmICh0dGZzID09PSB1bmRlZmluZWQgJiYgc3RzbyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IG9wdGltaXphdGlvbnM6IHN0cmluZ1tdID0gW107XG4gIGlmICh0cmFja2luZy50dXJibykgb3B0aW1pemF0aW9ucy5wdXNoKCd0dXJibycpO1xuICBpZiAocGFyYW1zLmxhenlTdGVwU3RhcnQpIG9wdGltaXphdGlvbnMucHVzaCgnbGF6eVN0ZXBTdGFydCcpO1xuICBpZiAocGFyYW1zLm9wdGltaXN0aWNTdGFydCkgb3B0aW1pemF0aW9ucy5wdXNoKCdvcHRpbWlzdGljU3RhcnQnKTtcbiAgaWYgKHBhcmFtcy5wcmVjbGFpbWVkU3RhcnQpIG9wdGltaXphdGlvbnMucHVzaCgncHJlY2xhaW1lZFN0YXJ0Jyk7XG4gIC8vIFJpZGVzIHRoZSBleGlzdGluZyBvcHRpbWl6YXRpb25zIGxpc3QgcmF0aGVyIHRoYW4gYSBkZWRpY2F0ZWQgd2lyZVxuICAvLyBmaWVsZDogdGhlIHNlcnZlciBhbHJlYWR5IHBhcnNlcyB0aGlzIGFycmF5IGFuZCB0dXJucyBlYWNoIGtub3duIGVudHJ5XG4gIC8vIGludG8gYSBib3VuZGVkIGJvb2xlYW4gdGFnIG9uIGV2ZXJ5IGxhdGVuY3kgbWV0cmljLCBzbyBgcmV0YWluZWRgXG4gIC8vIGRpbWVuc2lvbnMgdHRmcy9zdHNvL3JzZnMvZmluYWxTY2hlZHVsaW5nUmVwbGF5IGZvciBmcmVlLlxuICBpZiAodHJhY2tpbmcucmV0YWluZWQpIG9wdGltaXphdGlvbnMucHVzaCgncmV0YWluZWQnKTtcblxuICByZXR1cm4ge1xuICAgIC4uLih0dGZzICE9PSB1bmRlZmluZWQgPyB7IHR0ZnMgfSA6IHt9KSxcbiAgICAuLi4oc3RzbyAhPT0gdW5kZWZpbmVkID8geyBzdHNvIH0gOiB7fSksXG4gICAgLi4uKHN0c28gIT09IHVuZGVmaW5lZCAmJiB0cmFja2luZy5zdGVwQ291bnQgIT09IHVuZGVmaW5lZFxuICAgICAgPyB7IHN0ZXBDb3VudDogdHJhY2tpbmcuc3RlcENvdW50IH1cbiAgICAgIDoge30pLFxuICAgIC4uLihzdHNvICE9PSB1bmRlZmluZWQgJiYgdHJhY2tpbmcuZXZlbnRDb3VudCAhPT0gdW5kZWZpbmVkXG4gICAgICA/IHsgZXZlbnRDb3VudDogdHJhY2tpbmcuZXZlbnRDb3VudCB9XG4gICAgICA6IHt9KSxcbiAgICAuLi4ocnNmcyAhPT0gdW5kZWZpbmVkID8geyByc2ZzIH0gOiB7fSksXG4gICAgLi4uKGZpbmFsU2NoZWR1bGluZ1JlcGxheSAhPT0gdW5kZWZpbmVkID8geyBmaW5hbFNjaGVkdWxpbmdSZXBsYXkgfSA6IHt9KSxcbiAgICBvcHRpbWl6YXRpb25zLFxuICB9O1xufVxuIl19
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Event } from '@workflow/world';
|
|
2
|
+
import type { StepInvocationQueueItem } from '../global.js';
|
|
3
|
+
/**
|
|
4
|
+
* Inline step ownership helpers for the pending-step dispatch decision table
|
|
5
|
+
* in runtime.ts (workflow#2780). Ownership state itself is derived per-replay
|
|
6
|
+
* from the event log by the step consumer in step.ts and surfaced on
|
|
7
|
+
* StepInvocationQueueItem; these functions interpret that state at dispatch
|
|
8
|
+
* time.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Whether inline step ownership is active for a pending step: created,
|
|
12
|
+
* latest `step_started` carries an owner stamp, and no `step_retrying` has
|
|
13
|
+
* been observed (from `step_retrying` on, the step is queue-owned by its
|
|
14
|
+
* delayed retry handoff / replay requeue, so ownership is permanently
|
|
15
|
+
* lapsed for the correlation ID).
|
|
16
|
+
*/
|
|
17
|
+
export declare function isStepOwnershipActive(step: StepInvocationQueueItem): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Seconds left on an owned step's liveness lease, anchored at its latest
|
|
20
|
+
* `step_started`. 0 means the lease has expired (or the start timestamp is
|
|
21
|
+
* missing, the degraded mode for worlds whose events lack usable
|
|
22
|
+
* timestamps), in which case dispatch falls back to the immediate enqueue.
|
|
23
|
+
*
|
|
24
|
+
* The result is clamped to the configured lease: `lastStartedAt` is the
|
|
25
|
+
* server-stamped event `createdAt` while `nowMs` is the local clock, so a
|
|
26
|
+
* client running behind the server would otherwise compute a remainder
|
|
27
|
+
* LONGER than the lease itself, and with the lease tuned to the 900s cap,
|
|
28
|
+
* a `delaySeconds` above the queue's per-message maximum, which SQS-backed
|
|
29
|
+
* worlds reject outright (the wake replay's enqueue would throw and ride
|
|
30
|
+
* the redelivery loop). The clamp makes skew strictly harmless; remaining
|
|
31
|
+
* time can never legitimately exceed the full lease anyway.
|
|
32
|
+
*/
|
|
33
|
+
export declare function stepLeaseRemainingSeconds(step: StepInvocationQueueItem, nowMs: number): number;
|
|
34
|
+
/**
|
|
35
|
+
* Idempotency key for the delayed backstop wake of an inline-owned step.
|
|
36
|
+
*
|
|
37
|
+
* The key is scoped to the current OWNERSHIP EPOCH (the timestamp of the
|
|
38
|
+
* latest `step_started`), not just the correlation ID. Within one epoch,
|
|
39
|
+
* every wake replay derives the same key, so fan-out stays capped at one
|
|
40
|
+
* pending backstop per step. But when owner recovery re-stamps the step
|
|
41
|
+
* (queue redelivery of the owning message → new `step_started` → new
|
|
42
|
+
* `lastStartedAt`), the key CHANGES. This is load-bearing for liveness:
|
|
43
|
+
* queues dedupe an idempotency key for the lifetime of the original
|
|
44
|
+
* message (including while a delivery of it is in flight), so a backstop
|
|
45
|
+
* that fires during a refreshed lease and tries to re-arm under a fixed key
|
|
46
|
+
* would dedupe against ITSELF and be dropped, leaving no escape hatch if
|
|
47
|
+
* the recovered owner later dies without further redeliveries. The epoch
|
|
48
|
+
* suffix gives the re-arm a fresh key. Pending backstops are bounded by the
|
|
49
|
+
* number of ownership epochs, i.e. the queue's redelivery budget for the
|
|
50
|
+
* owning message.
|
|
51
|
+
*
|
|
52
|
+
* The epoch value comes from the persisted event's `createdAt`, so every
|
|
53
|
+
* replayer derives the same key. Callers only build backstops when the
|
|
54
|
+
* lease has time remaining, which requires `lastStartedAt` to be set.
|
|
55
|
+
*
|
|
56
|
+
* The key must also never be the step message's own `idempotencyKey`
|
|
57
|
+
* (the bare correlation ID): the owner's retry handoff enqueues the step
|
|
58
|
+
* under that key with a short backoff, and a pending backstop sharing it
|
|
59
|
+
* would absorb the retry, turning a 1s backoff into a full-lease stall.
|
|
60
|
+
*/
|
|
61
|
+
export declare function backstopIdempotencyKey(step: StepInvocationQueueItem): string;
|
|
62
|
+
/**
|
|
63
|
+
* Whether any of the given pending correlation IDs is inline-owned by
|
|
64
|
+
* `messageId` per the raw event log: its LATEST `step_started` carries
|
|
65
|
+
* `ownerMessageId === messageId` and no `step_retrying` follows it. Used by
|
|
66
|
+
* the background-step fast path, which sees raw events (not the replay's
|
|
67
|
+
* queueItems), to decide whether to fall through to the main loop so this
|
|
68
|
+
* invocation can recover a step it owns instead of returning and leaving it
|
|
69
|
+
* to the delayed backstop.
|
|
70
|
+
*/
|
|
71
|
+
export declare function hasPendingStepOwnedByMessage(events: Event[], pendingCorrelationIds: Set<string | undefined>, messageId: string): boolean;
|
|
72
|
+
//# sourceMappingURL=step-ownership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-ownership.d.ts","sourceRoot":"","sources":["../../src/runtime/step-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAG5D;;;;;;GAMG;AAEH;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAM5E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,uBAAuB,EAC7B,KAAK,EAAE,MAAM,GACZ,MAAM,CAKR;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAE5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,KAAK,EAAE,EACf,qBAAqB,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,EAC9C,SAAS,EAAE,MAAM,GAChB,OAAO,CAgCT"}
|