Skip to content

fix: pm.execution.runRequest hanging with customParallelIterations - #1565

Open
Kart03 wants to merge 3 commits into
developfrom
fix/run-request-custom-parallel-iterations
Open

Kart03 wants to merge 3 commits into
developfrom
fix/run-request-custom-parallel-iterations

Conversation

@Kart03

@Kart03 Kart03 commented Oct 15, 2026 •

Copy link
Copy Markdown

Summary

pm.execution.runRequest hangs in runs that use customParallelIterations (one partition per virtual user, driven through run.startParallelIteration). Runs that don't use partitions (the app's collection runner, newman, maxConcurrency: 1) are unaffected and behave as before.

There were three separate problems:

Problem Cause Effect
Nested run never executes The nested run is built from ...self.options, so it inherits customParallelIterations: true. PartitionManager#createPartitions then creates no partitions and nothing starts one for the nested run. done never fires; the caller's await pm.execution.runRequest(...) waits forever.
Chain state shared across partitions state.nestedRequest (root item, root cursor, call stack, vault flag) lives on the run, so every partition shares one slot. With 2+ partitions, one partition's runRequest makes the others' top-level scripts look nested, and delete this.state.nestedRequest at the end of one script races with another partition's in-flight call. The run hangs.
Nested requests use a fresh cookie jar Each nested run gets a new requester pool, which creates a new RequestCookieJar. Nested requests don't send the calling partition's cookies, and cookies they receive never reach it.

Changes

  • Sequential nested run. The nested run is started with customParallelIterations: false and maxConcurrency: 1: it runs once, for the script that called it.
  • Chain kept per script execution. event.command creates a nestedRequestScope for each script execution and passes it to runNestedRequest. The top-level script starts its chain on its first runRequest, and the chain is passed to the nested run explicitly (nestedRequest option), so nested levels share it and partitions never do. The existing run-collection-request.test.js passes unchanged.
  • Calling partition's cookie jar. In a partitioned run the nested run gets requester.cookieJar set to the caller's jar: the partition's own jar with requester.perPartitionCookieJar, otherwise the run's shared jar. An explicit jar already wins over per-partition jars (Run constructor), and deeper nested runs inherit it through requester. Non-partitioned runs keep their requester options unchanged.
  • Stopping a partition aborts its nested runs. Each Partition tracks the nested runs its scripts started (nestedRuns). stopSinglePartition calls Partition#abortNestedRuns, which aborts them, refuses new ones from the stopped occupant, and gives the reused index a fresh set.
  • CHANGELOG.yaml: unreleased entry.

Behaviour change for partitioned runs

This changes what existing partitioned runs (customParallelIterations / maxConcurrency > 1) see from pm.execution.runRequest, on purpose:

  • Nested requests run one at a time. A nested run used to inherit the caller's partition options. It now always runs once, sequentially, for the script that called it.
  • Nested requests share the caller's cookies. A nested run used to get a fresh cookie jar. It now uses the calling partition's jar (its own with perPartitionCookieJar, else the run's shared jar). So cookies a nested request sets, such as from a login, are visible to the caller, and the nested request sends the caller's cookies.

Runs without partitions are unchanged: same requester options, and no jar unless one is passed explicitly.

Validation

  • npm run test-unit: 572 passing, 10 pending.
  • npm run test-integration: 1915 passing, 33 pending, 0 failing.
  • New test/integration/runner-spec/run-collection-request-parallel.test.js (14 tests, local HTTP server):
    • a single partition: the nested request runs and the run completes
    • partitions calling runRequest concurrently: one nested request per partition, logs (nested ones included) tagged to their own partition
    • runRequest inside runRequest: depth limit enforced per partition and reported on that partition's root request
    • without partitions: an explicit requester.cookieJar is shared with nested requests; with no jar, nested requests keep their own (today's behaviour)
    • requester.perPartitionCookieJar: nested requests send the calling partition's cookies, cookies they receive land in its jar, no per-partition-jar warning
    • a partition stopped mid-runRequest: the run completes, the stopped occupant can't start new nested requests, the next occupant gets its own chain
  • New unit test in test/unit/partition-manager.test.js for stopSinglePartition aborting nested runs.
  • Lint: I ran ESLint on the changed files with this repo's .eslintrc and test/.eslintrc (clean). npm run test-lint itself doesn't run in my checkout because it's a worktree nested inside another clone, and ESLint picks up the parent's .eslintrc too (Plugin "n" was conflicted).
  • End to end, in a load-test consumer that runs each virtual user as a partition: with this branch, 3 VUs for 1 minute, a request whose test script calls pm.execution.runRequest and checks cookies both ways passed every assertion (134/134 and 133/133). With 7.56.1 the same run made 3 requests and no assertions, i.e. it hung.

Notes

  • Pre-existing, not changed here: a customParallelIterations run ended with run.abort calls done a second time with callback timed out once timeout.global elapses (3 minutes by default), because only _process's completion clears that timer. Reproduced on develop with timeout.global: 500. The new integration test ignores the second call, like perPartitionCookieJar.test.js does. Happy to fix it separately.

Generated with Claude Code

The nested run inherited customParallelIterations, so no partition ever ran
it. Its chain state lived on the run and was shared by every partition, and
each nested run got a fresh cookie jar.

- run the nested request once, sequentially
- keep the runRequest chain per script execution and pass it to nested runs
- give nested requests the calling partition's cookie jar
- abort a stopped partition's in-flight nested runs

Co-Authored-By: Claude <[email protected]>
@codecov

codecov Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 26.31579% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.77%. Comparing base (9c2d10d) to head (449cae5).

Files with missing lines Patch % Lines
lib/runner/nested-request.js 3.70% 26 Missing ⚠️
lib/runner/extensions/event.command.js 60.00% 2 Missing ⚠️

❌ Your patch check has failed because the patch coverage (26.31%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage.

❗ There is a different number of reports uploaded between BASE (9c2d10d) and HEAD (449cae5). Click for more details.

HEAD has 29 uploads less than BASE
Flag BASE (9c2d10d) HEAD (449cae5)
unit 10 1
integration 10 0
legacy 10 0
Additional details and impacted files
@@             Coverage Diff              @@
##           develop    #1565       +/-   ##
============================================
- Coverage    77.54%   46.77%   -30.77%     
============================================
  Files           51       51               
  Lines         4338     4361       +23     
  Branches      1223     1234       +11     
============================================
- Hits          3364     2040     -1324     
- Misses         731     2156     +1425     
+ Partials       243      165       -78     
Flag Coverage Δ
integration ?
legacy ?
unit 46.77% <26.31%> (-0.09%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Kart03 and others added 2 commits October 15, 2026 08:34
After run.abort, timeout.global still calls done once more, so the spy's
second call ran mocha's done() again and failed the hook on slower CI
runners. The product double-completion is fixed separately in #1559
(2c4489c).

Co-Authored-By: Claude <[email protected]>
@Kart03
Kart03 marked this pull request as ready for review October 15, 2026 14:53

This branch has not been deployed

No deployments
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.

1 participant