Repository navigation
Commit 088de0a
Various Performance Improvements (#932)
* Parallelize async operations in step handler for performance
- Parallelize getPort(), getSpanKind(), and world.steps.get() calls
- Start step_started event creation while hydrating arguments (CPU work)
- Parallelize step_completed event with trace serialization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix race condition: await step_started before hydration
Reverts Optimization 1 to fix a race condition where hydrateStepArguments()
could throw before stepStartedPromise was awaited, causing stale step.attempt
in the catch handler and potentially allowing extra retries.
Optimizations 0 and 2 are preserved as they don't have this issue.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Skip initial world.steps.get() in step handler for performance
Eliminate the world.steps.get() HTTP call by calling step_started first
and relying on server-side validation. This saves 50-80ms per step
execution by removing one HTTP round-trip.
The server (workflow-server) now validates:
- Step not in terminal state (returns 409)
- retryAfter timestamp reached (returns 425 with Retry-After header)
- Workflow still active (returns 410 if completed)
Changes:
- Remove world.steps.get() from initial Promise.all
- Call step_started first to get step entity and validate state
- Handle 409 (terminal state) by re-queueing workflow
- Handle 425 (retryAfter not reached) by returning timeout
- Handle 410 (workflow gone) as no-op
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add retryAfter validation to local and postgres worlds
Add server-side retryAfter validation to match workflow-server behavior:
- Check retryAfter timestamp before allowing step_started
- Return HTTP 425 with retryAfter timestamp in response meta
- Clear retryAfter field when step starts successfully
This ensures consistent behavior across all world implementations
and allows the step-handler optimization to work correctly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix step terminal state HTTP status code to 409 (Conflict)
Aligns local and postgres worlds with workflow-server, which returns
409 via InvalidOperationStateError for step in terminal state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix world-vercel telemetry to use parent application's tracer
The world-vercel package was creating spans under a separate
'workflow-world-vercel' service name, causing HTTP spans for
workflow-server API calls (step_started, step_completed) to be
filtered out when viewing traces for the main application service.
Now uses the same 'workflow' tracer name as @workflow/core to
ensure all spans are reported under the parent application's service.
* Update /demo command to include OTEL tracing with Jaeger
- Start Jaeger container for local trace visualization
- Configure OTEL exporter environment variables for dev server
- Open Jaeger UI automatically
- Add documentation about available trace attributes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add OTEL instrumentation to world-local and improve trace consistency
- Add telemetry.ts and instrumentObject.ts to world-local for tracing parity
with world-vercel (world.runs, world.steps, world.events, world.hooks spans)
- Change workflow span name from uppercase "WORKFLOW" to lowercase "workflow"
for consistency with step spans and OTEL naming conventions
- Add step.execute child span to trace actual user step function execution
separately from step handler infrastructure
These changes enable local development to have the same observability as
production deployments, making performance analysis and debugging easier.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Use uppercase WORKFLOW and STEP span names for consistency with HTTP spans
HTTP spans use uppercase methods like "GET /path" and "POST /path".
Following the same convention, workflow and step spans now use:
- WORKFLOW <workflow-name>
- STEP <step-name>
Child spans (workflow.run, workflow.loadEvents, step.execute, world.events.create)
remain lowercase as they represent internal operations, not top-level entries.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add W3C trace context headers to step queue messages
Include traceparent and tracestate headers when queueing step
execution messages. This enables automatic trace propagation
by Vercel's infrastructure, potentially linking step invocation
spans to the parent workflow trace.
The trace carrier is now serialized once and included in both:
- Payload: for manual context restoration in step handler
- Headers: for automatic HTTP-based trace propagation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Improve OTEL tracing with service attribution and enhanced instrumentation
- Add peer.service attributes for workflow-server and VQS for Datadog service maps
- Rename queueMessage span to queue.publish for consistency
- Add step.hydrate, step.dehydrate, and workflow.replay spans
- Include event type in world.events.create span names (e.g., "world.events.create step_started")
- Add span.recordException() for errors with category classification (fatal/retryable/transient)
- Add span events for milestones: retry.scheduled, step.skipped, step.delayed
- Add HTTP semantic conventions with peer.service for world-vercel HTTP calls
- Add baggage propagation for workflow context (run_id, workflow_name)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update changesets to reflect all PR changes
- step-handler-parallelization.md: Add race condition fix and 409 status code fix
- world-vercel-telemetry-tracer.md: Add peer.service and event type in span names
- otel-tracing-improvements.md: New changeset for comprehensive OTEL improvements
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Use span name for rpc.method to show event type in Datadog resource
Datadog derives the resource name from rpc.method attribute. Updated to
use the full span name (which includes event type) instead of just the
method name, so Datadog shows "world.events.create step_started" instead
of "world.events.create workflow-server".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Use lazy ref resolution for events where client discards response data
Skip expensive S3 ref resolution (~200-460ms) for event types where
the client doesn't use the response entity data (step_created,
step_completed, step_failed, run_completed, etc). Only resolve refs
for run_created, run_started, and step_started where the client
reads the response.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update changeset to include lazy ref resolution optimization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address PR review comments: module scope const, comment cleanup, status code audit
- Move eventsNeedingResolve Set to module scope (PR review #2)
- Rewrite changelog-style OPTIMIZATION comments as current-state docs (PR review #4)
- Fix run terminal state errors: 410 → 409 in world-local and world-postgres to
match workflow-server's InvalidOperationStateError (409) (PR review #3)
- Fix remaining step terminal state 410 → 409 in world-postgres fallback paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>1 parent fc07710 commit 088de0a
19 files changed
Lines changed: 974 additions & 347 deletions
File tree
- .changeset
- .claude/commands
- packages
- core/src
- runtime
- telemetry
- world-local/src
- storage
- world-postgres/src
- world-vercel/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | | - | |
| 8 | + | |
8 | 9 | | |
9 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
0 commit comments