Files
Karthik Kalyan a0ccfe0f50 feat(core): measure hook-triggered time to resume (#3437)
Report end-to-end TTR for a hook resumption — entry into the public resume
API through to the first line of the next durable step — on that step's
`step.execute` span, decomposed into non-overlapping phases that sum
exactly to the total:

  workflow.resume.total_ms
  workflow.resume.phase.{producer_prep,queue_delivery,resume_setup,
                         replay,step_dispatch,step_claim,step_prepare}_ms

dimensioned by trigger, dispatch strategy, setup source, and whether the
step ran inline or was dispatched to another invocation.

T0 is stamped by whichever public entry point the caller used, so
`resumeWebhook` — which does its own by-token lookup and key resolution
before reaching the shared implementation — measures the same window as
`resumeHook` rather than a systematically shorter one. T7 is taken inside
`contextStorage.run`, immediately before `stepFn.apply()`, so the
`step_prepare` phase covers the step-context setup it is defined to cover.

`resumeHook()` puts the producer boundaries on an optional
`hookResumeTiming` field on the queue message (both dispatch paths); the
consuming invocation adds its own and hands them to the execution that
will actually ATTEMPT the next durable step. That decision is made against
the dispatch loop's own classification, so an owned-recovery step keeps
the measurement here instead of it riding off on a queued sibling, and a
step converted into a delayed backstop wake — which this delivery does not
attempt — never takes it. Within an inline batch the tracking is shared
and a one-shot latch picks the single step that reaches user code, so the
sample survives the batch's first step losing its create-claim. A
deployment-affinity re-route forwards the timing untouched, keeping the
wasted hop inside `queue_delivery`.

The field is optional in every direction (new producer/old consumer, new
consumer/old message, no workflow-server change) and parses with
`.catch(undefined)` so a malformed value can never fail a delivery. A
sample is emitted only when every required boundary is present, finite,
and monotonic — a skewed or incomplete set is dropped rather than
reported as a negative phase.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 11:14:03 -07:00
..
2026-08-11 12:30:28 -07:00
2026-08-11 12:30:28 -07:00

@workflow/world

Core interfaces and types for Workflow SDK storage backends.

This package defines the World interface that abstracts workflow storage, queuing, authentication, and streaming operations. Implementation packages like @workflow/world-local and @workflow/world-vercel provide concrete implementations.

Used internally by @workflow/core and world implementations. Should not be used directly in application code.