Skip to content

[APPS-2961] Update: run local backend function calls in parallel, with per-call log prefixes - #603

Open
tyffical wants to merge 1 commit into
tiffany.trinh/apps-2961-child-permission-modelfrom
tiffany.trinh/apps-2961-parallel-local-execution
Open

tyffical wants to merge 1 commit into
tiffany.trinh/apps-2961-child-permission-modelfrom
tiffany.trinh/apps-2961-parallel-local-execution

Conversation

@tyffical

@tyffical tyffical commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Architecture

sequenceDiagram
    participant App as App frontend (dev client)
    participant D as Vite dev server
    participant C1 as Call 1 process
    participant C2 as Call 2 process
    participant API as Datadog API
    App->>D: executeAction (call 1)
    App->>D: executeAction (call 2)
    D->>API: One runtime-context lookup, shared by both calls
    API-->>D: Runtime context ($)
    par Calls run in parallel, no local limit
        D->>C1: start
        C1-->>D: Log lines, printed as [fn#35;1] ...
    and
        D->>C2: start
        C2-->>D: Log lines, printed as [fn#35;2] ...
    end
    C1->>D: $.Actions call fails
    D-->>C1: Rejects with the platform's bare string
    C1->>D: result
    D-->>App: 200 with the result
    C2->>D: Uncaught error
    D-->>App: 500 {error: "Execution failed: #lt;message#gt;"}
    Note over App: The dev client throws BackendFunctionError("Execution failed: #lt;message#gt;")
Loading

Changes

10 changes across local-execution-process.ts, dev-server.ts, local-execution-shared.ts, dev-server-transport.ts, the README and tests
What changed File
Runs calls in parallel, with no local limit. local-execution-process.ts
Prefixes each logged line with [fn#N]. local-execution-process.ts
Carries thrown strings and failure detail across IPC. local-execution-process.ts
Shares one runtime context query between concurrent calls. dev-server.ts
Rejects a failed $.Actions call with the platform's bare string. dev-server.ts
Reports an uncaught failure as Execution failed: <stack or value>. dev-server.ts
Rejects invalid $.Actions calls with deployed-wording strings. local-execution-shared.ts
Throws the response's error, else the status and body. dev-server-transport.ts
Documents parallel calls, the shared query and log prefixes. README.md
Tests each change. local-execution-process.integration.test.ts, dev-server.test.ts, execute-backend-function.test.ts

QA Instructions

yarn typecheck:all
# Expected: exit 0 ✅ VERIFIED
yarn lint
# Expected: exit 0 ✅ VERIFIED
yarn cli integrity
# Expected: exit 0, no changes ✅ VERIFIED
TMPDIR=/private/tmp yarn test:unit packages/plugins/apps
# Expected: Test Suites: 40 passed; Tests: 1041 passed ✅ VERIFIED
  • Parallel calls and log prefixes on Vite 5 to 8: Apps local execution jobs in the CI matrix PR's CI run, which includes this branch.
  • Against a Datadog staging org, failures match a deployed app:
Case Result
No connection a connection is required for …
No arguments or inputs No arguments provided …, or … must have an inputs field that is an object
Unknown connection rpc error: code = NotFound …
Real read-only connection resolves
Uncaught failure BackendFunctionError: Execution failed: <message or stack>
Fixtures, helper scripts and raw output
  • Fixtures in a scaffolded app with the packed plugin:
// src/parity.backend.ts
import { listMonitors } from '@datadog/action-catalog/dd/monitor';
import { list } from '@datadog/action-catalog/github/pulls';

declare const $: any;

function describe(err: unknown) {
    return err instanceof Error ? { type: 'Error', message: err.message } : { type: typeof err, value: err };
}

async function attempt(call: () => Promise<unknown>) {
    try {
        const value = await call();
        return { resolved: Array.isArray(value) ? `array of ${value.length}` : typeof value };
    } catch (err) {
        return describe(err);
    }
}

export async function missingConnection() {
    return attempt(() => $.Actions.github.pulls.list({ inputs: { owner: 'DataDog', repo: 'datadog-agent' } }));
}

export async function missingConnectionTyped() {
    return attempt(() => list({ inputs: { owner: 'DataDog', repo: 'datadog-agent' } } as any));
}

export async function noArguments() {
    return attempt(() => $.Actions.github.pulls.list());
}

export async function missingInputs() {
    return attempt(() => $.Actions.github.pulls.list({ owner: 'DataDog', repo: 'datadog-agent' }));
}

export async function fakeConnection() {
    return attempt(() => listMonitors({ inputs: { limit: 1 }, connectionId: '00000000-0000-0000-0000-000000000000' }));
}

export async function unlistedConnection() {
    return attempt(() => $.Actions.dd.monitor.listMonitors({ inputs: { limit: 1 }, connectionId: 'qa-unlisted-connection' }));
}

export async function realConnection() {
    return attempt(() => listMonitors({ inputs: { limit: 1 }, connectionId: '<read-only-connection-id>' }));
}
// src/parityUncaught.backend.ts
declare const $: any;

export async function uncaughtMissingConnection() {
    return $.Actions.github.pulls.list({ inputs: { owner: 'DataDog', repo: 'datadog-agent' } });
}

export async function uncaughtString() {
    const failure = 'plain string failure';
    throw failure;
}
// src/uncaughtError.backend.ts
export async function uncaughtError() {
    throw new TypeError('plain error x');
}
  • Runner and request logger:
# run.sh
#!/usr/bin/env bash
# Usage (with DD_API_KEY and DD_APP_KEY for a Datadog staging org): run.sh <app-dir> <port> <out-prefix> <fixture>:<fn> ...
# Starts the app's Vite dev server in development mode, POSTs each function to /__dd/executeAction,
# records full response bodies, then stops the server by its own PID.
set -u
APP="$1"; PORT="$2"; OUT="$3"; shift 3
D="$(cd "$(dirname "$0")" && pwd)"
NET_LOG="$OUT.net.log"; VITE_LOG="$OUT.vite.log"; RESP="$OUT.responses.txt"
: > "$NET_LOG"; : > "$RESP"
cd "$APP" || exit 1
if [ -n "$(lsof -ti tcp:$PORT -sTCP:LISTEN)" ]; then echo "port $PORT is busy"; exit 1; fi
env -u DD_OAUTH_ACCESS_TOKEN -u DATADOG_OAUTH_ACCESS_TOKEN DD_SITE=<staging site> QA_NET_LOG="$NET_LOG" \
    NODE_OPTIONS="--import $D/log-requests.mjs" \
    node node_modules/vite/bin/vite.js --mode development --port "$PORT" --strictPort < /dev/null > "$VITE_LOG" 2>&1 &
VPID=$!
echo "vite pid $VPID" >> "$RESP"
for _ in $(seq 1 90); do curl -s -o /dev/null "http://localhost:$PORT/" && break; sleep 1; done
for spec in "$@"; do
  ROUTE=executeAction; TAG=""
  case "$spec" in cloud:*) ROUTE=executeActionViaCloud; TAG="cloud-"; spec="${spec#cloud:}";; esac
  fixture="${spec%%:*}"; fn="${spec#*:}"
  module="$(curl -s "http://localhost:$PORT/src/$fixture.backend.ts")"
  if ! printf %s "$module" | grep -q executeBackendFunction; then
    echo "$fixture: rejected by transform: $(printf %s "$module" | head -c 600)" >> "$RESP"; continue
  fi
  FN="$(printf %s "src/$fixture" | shasum -a 256 | cut -d' ' -f1).$fn"
  echo "=== $ROUTE $fixture.$fn" >> "$RESP"
  curl -s -m 180 -D "$OUT.$TAG$fn.headers" -o "$OUT.$TAG$fn.body" -w 'HTTP %{http_code}\n' -X POST -H 'Content-Type: application/json' \
    -d "{\"functionName\":\"$FN\",\"args\":[]}" "http://localhost:$PORT/__dd/$ROUTE" >> "$RESP"
  cat "$OUT.$TAG$fn.body" >> "$RESP"; echo >> "$RESP"
done
LPID="$(lsof -ti tcp:$PORT -sTCP:LISTEN)"
echo "listener pid $LPID" >> "$RESP"
kill "$VPID" $LPID 2>/dev/null
sleep 3
for p in $VPID $LPID; do if kill -0 "$p" 2>/dev/null; then echo "pid $p still alive" >> "$RESP"; else echo "pid $p stopped" >> "$RESP"; fi; done
// log-requests.mjs, which run.sh preloads to log each Datadog request and long-poll body
// Preloaded with --import: logs method, URL and status of every fetch, plus the request body of
// preview-async POSTs and the response body of every long-poll, to $QA_NET_LOG.
import { appendFileSync } from 'node:fs';

const realFetch = globalThis.fetch;
const log = (line) => appendFileSync(process.env.QA_NET_LOG, line + '\n');
globalThis.fetch = async (input, init) => {
    const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
    const method = init?.method ?? (typeof input === 'object' && 'method' in input ? input.method : 'GET');
    if (url.includes('preview-async') && typeof init?.body === 'string') {
        try {
            const spec = JSON.parse(init.body).data.attributes.query.properties.spec;
            const shown = spec.inputs?.script ? { ...spec, inputs: { ...spec.inputs, script: '<script>' } } : spec;
            log(`REQ ${method} ${url.split('?')[0]} spec=${JSON.stringify(shown)}`);
        } catch {
            log(`REQ ${method} ${url.split('?')[0]} <unparsed body>`);
        }
    }
    const res = await realFetch(input, init);
    if (url.includes('execution-long-polling')) {
        const text = await res.clone().text();
        log(`RES ${res.status} ${url.split('?')[0].replace(/execution-long-polling\/.*/, 'execution-long-polling/<receipt>')} body=${text.slice(0, 400)}`);
    } else {
        log(`RES ${res.status} ${method} ${url.split('?')[0]}`);
    }
    return res;
};
DD_API_KEY=<staging API key> DD_APP_KEY=<staging app key> bash run.sh ./qa-app 5774 out/after parity:missingConnection parity:missingConnectionTyped parity:noArguments parity:missingInputs parity:fakeConnection parity:unlistedConnection parity:realConnection parityUncaught:uncaughtMissingConnection parityUncaught:uncaughtString uncaughtError:uncaughtError
vite pid 21145
=== executeAction parity.missingConnection
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"a connection is required for com.datadoghq.github.pulls"}}}
=== executeAction parity.missingConnectionTyped
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"a connection is required for com.datadoghq.github.pulls"}}}
=== executeAction parity.noArguments
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"No arguments provided to action $.Actions.github.pulls.list"}}}
=== executeAction parity.missingInputs
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"First argument to action $.Actions.github.pulls.list must have an inputs field that is an object"}}}
=== executeAction parity.fakeConnection
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"rpc error: code = NotFound desc = connection not found"}}}
=== executeAction parity.unlistedConnection
HTTP 200
{"success":true,"result":{"data":{"type":"string","value":"Action $.Actions.dd.monitor.listMonitors used connection \"qa-unlisted-connection\", which is not in this function's allowed connections: [00000000-0000-0000-0000-000000000000, <read-only-connection-id>]"}}}
=== executeAction parity.realConnection
HTTP 200
{"success":true,"result":{"data":{"resolved":"object"}}}
=== executeAction parityUncaught.uncaughtMissingConnection
HTTP 500
{"success":false,"error":"Execution failed: a connection is required for com.datadoghq.github.pulls"}
=== executeAction parityUncaught.uncaughtString
HTTP 500
{"success":false,"error":"Execution failed: plain string failure"}
=== executeAction uncaughtError.uncaughtError
HTTP 500
{"success":false,"error":"Execution failed: TypeError: plain error x\n    at uncaughtError (/tmp/qa/qa-app/src/uncaughtError.backend.ts?dd-local-exec:2:11)\n    at file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:17222\n    at w (file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:562)\n    at Vt (file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:17215)\n    at processTicksAndRejections (node:internal/process/task_queues:104:5)\n    at file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:15402"}
listener pid 21148
pid 21145 stopped
pid 21148 stopped
  • Client check through executeBackendFunction:
// transport-harness.mjs
// Calls backend functions through the plugin's own packed client runtime, the code app frontends use.
import { createHash } from 'node:crypto';
import { pathToFileURL } from 'node:url';

const [runtimePath, origin, ...specs] = process.argv.slice(2);
const realFetch = globalThis.fetch;
globalThis.fetch = async (url, init) => {
    try {
        return await realFetch(new URL(url, origin), init);
    } catch (error) {
        console.log(JSON.stringify({ fetchFailure: String(error.cause ?? error) }));
        throw error;
    }
};
await import(pathToFileURL(runtimePath).href);
for (const spec of specs) {
    const [fixture, fn] = spec.split(':');
    const name = `${createHash('sha256').update(`src/${fixture}`).digest('hex')}.${fn}`;
    try {
        const data = await globalThis.DD_APPS_RUNTIME.executeBackendFunction(name, []);
        console.log(JSON.stringify({ spec, resolved: data }));
    } catch (error) {
        console.log(JSON.stringify({ spec, name: error.name, message: error.message, statusCode: error.statusCode }));
    }
}
# transport-run.sh
#!/usr/bin/env bash
# Usage (with DD_API_KEY and DD_APP_KEY for a Datadog staging org): transport-run.sh <app-dir> <port> <out-file> <fixture>:<fn> ...
set -u
APP="$1"; PORT="$2"; OUT="$3"; shift 3
D="$(cd "$(dirname "$0")" && pwd)"
cd "$APP" || exit 1
if [ -n "$(lsof -ti tcp:$PORT -sTCP:LISTEN)" ]; then echo "port $PORT is busy"; exit 1; fi
env -u DD_OAUTH_ACCESS_TOKEN -u DATADOG_OAUTH_ACCESS_TOKEN DD_SITE=<staging site> \
    node node_modules/vite/bin/vite.js --mode development --port "$PORT" --strictPort < /dev/null > "$OUT.vite.log" 2>&1 &
VPID=$!
for _ in $(seq 1 90); do curl -s -o /dev/null "http://localhost:$PORT/" && break; sleep 1; done
for spec in "$@"; do curl -s -o /dev/null "http://localhost:$PORT/src/${spec%%:*}.backend.ts"; done
node "$D/transport-harness.mjs" "$APP/node_modules/@datadog/vite-plugin/dist/src/apps-runtime.mjs" "http://localhost:$PORT" "$@" > "$OUT" 2>&1
LPID="$(lsof -ti tcp:$PORT -sTCP:LISTEN)"
kill "$VPID" $LPID 2>/dev/null
sleep 3
for p in $VPID $LPID; do if kill -0 "$p" 2>/dev/null; then echo "pid $p still alive" >> "$OUT"; fi; done
DD_API_KEY=<staging API key> DD_APP_KEY=<staging app key> bash transport-run.sh ./qa-app 5773 out/transport.txt parityUncaught:uncaughtMissingConnection parityUncaught:uncaughtString uncaughtError:uncaughtError parity:realConnection getGreeting:getGreeting
{"spec":"parityUncaught:uncaughtMissingConnection","name":"BackendFunctionError","message":"Execution failed: a connection is required for com.datadoghq.github.pulls","statusCode":500}
{"spec":"parityUncaught:uncaughtString","name":"BackendFunctionError","message":"Execution failed: plain string failure","statusCode":500}
{"spec":"uncaughtError:uncaughtError","name":"BackendFunctionError","message":"Execution failed: TypeError: plain error x\n    at uncaughtError (/tmp/qa/qa-app/src/uncaughtError.backend.ts?dd-local-exec:2:11)\n    at file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:17222\n    at w (file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:562)\n    at Vt (file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:17215)\n    at processTicksAndRejections (node:internal/process/task_queues:104:5)\n    at file:///tmp/qa/qa-app/node_modules/@datadog/vite-plugin/dist/src/local-execution-child.mjs:1:15402","statusCode":500}
{"spec":"parity:realConnection","resolved":{"resolved":"object"}}
{"spec":"getGreeting:getGreeting","resolved":"Hello, undefined! This greeting ran as a backend function."}

Blast Radius

  • Local development only; builds and deploys are unchanged.
  • Parallel calls need Vite 6.0.4+; the error changes reach every local path, dev:verify included.
  • No feature flag. Low risk: a burst of calls starts that many processes.

Out of Scope / Follow-ups

1 item deferred
Item Status Next step
Timeout and exit errors lack the [fn#N] prefix. Deferred Add it.

Documentation

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Live Debugger Runtime Benchmark

Benchmark results were not produced. Check the workflow logs for details.

@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from 1b04081 to cfac113 Compare October 21, 2026 19:41
@tyffical
tyffical changed the base branch from master to tiffany.trinh/apps-2961-child-process-execution October 21, 2026 19:41
@tyffical tyffical changed the title [APPS-2961] Update: run local backend functions in parallel, each in a fresh sandboxed process [APPS-2961] Update: run local backend function calls in parallel, with per-call log prefixes Oct 21, 2026
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from cfac113 to 401268c Compare October 21, 2026 19:51
@tyffical
tyffical requested a balanced review from Copilot October 21, 2026 20:08
@tyffical

Copy link
Copy Markdown
Contributor Author

@codex review

@tyffical
tyffical marked this pull request as ready for review October 21, 2026 20:08
@tyffical
tyffical requested a review from a team as a code owner October 21, 2026 20:08
@tyffical
tyffical requested review from oliverli and removed request for a team October 21, 2026 20:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-22T18:50:01.782740Z cf49bfa Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@tyffical
tyffical added this pull request to stack #612 October 21, 2026 20:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 401268c033

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/plugins/apps/src/vite/local-execution-process.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No blocking issues were identified in concurrency accounting, query sharing, error handling, logging, or regression coverage.

No open issues 🎉

What changed in this PR

Builds on process isolation to run local backend calls concurrently on Vite 6+, while preserving serial execution for the in-process fallback.

Changes:

  • Allows up to 25 concurrent calls, returning HTTP 429 when full.
  • Adds per-call log prefixes and shares in-flight runtime-context queries.
  • Updates regression tests and local-execution documentation.
File Description
packages/​plugins/​apps/​src/​vite/​local-execution.ts Makes the in-process queue helper private.
packages/​plugins/​apps/​src/​vite/​local-execution-process.ts Adds concurrency limits and per-call log prefixes.
packages/​plugins/​apps/​src/​vite/​local-execution-process.test.ts Tests parallelism, slot release, isolation, and logging.
packages/​plugins/​apps/​src/​vite/​dev-server.ts Shares context queries and handles HTTP 429 responses.
packages/​plugins/​apps/​src/​vite/​dev-server.test.ts Tests query sharing, refresh, and concurrency errors.
packages/​plugins/​apps/​README.md Documents concurrent execution and prefixed logs.

Review effort: Balanced

@oliverli oliverli left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. The change is correct. I added two optional nits.

Comment thread packages/plugins/apps/src/vite/local-execution-process.ts Outdated
Comment thread packages/plugins/apps/README.md Outdated
@tyffical
tyffical requested a review from a team as a code owner October 22, 2026 01:06
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from 401268c to 002f14e Compare October 22, 2026 01:07
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch 2 times, most recently from f698ad5 to 7e9b4b4 Compare October 22, 2026 03:37
@tyffical
tyffical requested a balanced review from Copilot October 22, 2026 06:08
@tyffical

Copy link
Copy Markdown
Contributor Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No blocking issues remain, targeted regression coverage addresses the changed behavior, and the referenced CI run succeeded.

No open issues 🎉

Review effort: Balanced

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 7e9b4b45e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tyffical

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: cf49bfaeb3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No blocking issues remain, focused regression coverage accompanies the changes, and the linked CI run succeeded.

1 open issue

Review effort: Balanced

@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from cf49bfa to 314d9ca Compare October 23, 2026 13:09
@tyffical
tyffical removed this pull request from stack #612 October 23, 2026 13:10
@tyffical
tyffical changed the base branch from tiffany.trinh/apps-2961-child-process-execution to tiffany.trinh/apps-2961-child-permission-model October 23, 2026 13:11
@tyffical
tyffical added this pull request to stack #618 October 23, 2026 13:11
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from 314d9ca to 86c8430 Compare October 23, 2026 13:41
@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: b50260f | Docs | View more details | Give us feedback!

…l log prefixes

Each call already gets a fresh process, so calls no longer queue and run
in parallel, with no local limit: production's concurrency limits vary by
org, and dev:verify runs against them. Calls that start together share
one runtime context query, so a burst sends Datadog one query instead of
one per call. Each line a call writes is prefixed with its function name
and call number.

A failed $.Actions call now rejects as it does in a deployed app: with a
bare string holding the platform's error detail, the deployed inputs or
no-arguments message, or the local allowlist message, not an Error.

An uncaught failure in the function's code reports as it does in a
deployed app: the dev server's error is "Execution failed: " followed by
the thrown Error's stack or the thrown value, and the dev transport
throws that message instead of the status and raw response body.

Refs: APPS-2961

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2961-parallel-local-execution branch from 86c8430 to b50260f Compare October 23, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants