Skip to content

[durable-functions v4] Investigate restoring context.df.callHttp as a worker-side durable activity #318

Description

@YunchuWang

Follow-up from PR #282 (review comment #18, P3)

PR #282 added the packages/azure-functions-durable compat package (npm durable-functions v4) on the @microsoft/durabletask-js gRPC core. As part of it, context.df.callHttp(...) was made to throw, documented as a breaking change in the CHANGELOG (review comment #18). This issue tracks whether callHttp can be restored as a worker-side durable activity rather than left unsupported.

Short answer from investigation: yes, it is supportable — but as a scoped feature with behavioral deltas, not a byte-for-byte drop-in. Filing so the design + tradeoffs get a real decision.

Why it is supportable

callHttp was never an engine/backend primitive. In v3 the orchestrator emitted a CallHttp action (ActionType.CallHttp = 8) and the Functions host ran the raw HTTP send as a built-in WebJobs activity:

  • host chain: OutOfProcOrchestrationShim.cs:177 -> context.CallHttpAsync -> TaskHttpActivityShim : TaskActivity -> httpClient.SendAsync (extension Listener/TaskHttpActivityShim.cs L20/49/58)

Confirmed absent from the gRPC backend surface: proto (0 HTTP messages), durabletask-dotnet (0 CallHttp), durabletask-python core (0). So there is no host-managed durable-HTTP to inherit over gRPC.

Because it is "make an HTTP request from an orchestration, replay-safely", any backend with activities can provide it: register an auto-injected fetch-based durable activity and call it from the orchestrator. The orchestrator never does I/O; the activity does; the result is journaled -> replay-safe.

Helpful nuance re: the async (202) polling pattern

In v3 the polling loop is already SDK-orchestrated, not host-magic: DurableOrchestrationContext.callHttp returns a CallHttpWithPollingTask that drives a durable timer + re-poll loop (defaultHttpAsyncRequestSleepTimeMillseconds) when asynchronousPatternEnabled/enablePolling is true (default). Only each individual HTTP send went to the host activity. That means a worker-side port can reuse the same structure: core createTimer + repeated activity calls in orchestrator space, with the activity replacing TaskHttpActivityShim.

v3 API surface to match:

  • callHttp(options: CallHttpOptions): Task<DurableHttpResponse>
  • CallHttpOptions: method, url, body, headers, tokenSource, enablePolling (alias asynchronousPatternEnabled, default true)
  • types: DurableHttpRequest, DurableHttpResponse, ManagedIdentityTokenSource / TokenSource

What must be (re)built, and the real tradeoffs

  1. HTTP-send activity (replaces host TaskHttpActivityShim) — auto-registered fetch-based durable activity; single request/response; replay-safe. (cheap, core of the feature)
  2. 202 async-polling loop — reimplement CallHttpWithPollingTask semantics with core createTimer + repeat activity (follow Location/Retry-After until terminal). (moderate; structure exists in v3 to copy)
  3. Managed-identity auth — reimplement tokenSource / ManagedIdentityTokenSource token acquisition inside the activity. (needs an identity/token dependency decision)
  4. Trust / network boundary shift (design call, not code) — HTTP now originates from the app process, not the Functions host. Different egress, identity, and security story than v3. Must be documented; may matter for some users.
  5. Timeout / retry / error-shape parity with DurableHttpResponse.

Suggested phasing

  • Phase 1: basic callHttp (single request/response via fetch activity, no polling, no managed identity). Restores the common case; keep throwing only for the unsupported options.
  • Phase 2: 202 async-polling parity.
  • Phase 3: managed-identity tokenSource parity.

Acceptance

Links

Follow-up to PR #282 review comment #18.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions