Skip to content

npm: the retry waits are read from what the installer asked for - #113

Merged
enesismail merged 1 commit into
mainfrom
the-retry-waits-are-recorded
Oct 11, 2026
Merged

enesismail merged 1 commit into
mainfrom
the-retry-waits-are-recorded

Conversation

@enesismail

Copy link
Copy Markdown
Contributor

What this changes

The npm wrapper's row "the waits between attempts are one second and then two" timed the pauses between three
download attempts at the server, and required each one inside a window: 900-1800 ms, then 1900-2800 ms. Once, a hosted
Windows runner stalled for several seconds. The second pause measured 5407 ms and the row went red, with the schedule
correct. In the same job, an unrelated proxy row took about forty times its usual time. A stopwatch on a shared
machine measures the machine.

The schedule is now read from the child process:

  • A preload in the test tree, npm/test/helpers/recorded-waits.js, beside the two that are already there. It
    replaces the global setTimeout in the installer's process and writes down every delay asked for, and when each one
    fires. Each line is written synchronously, because the installer exits the moment its last attempt fails. Every call
    goes to the real timer with the same delay, so each pause is still spent. The file it writes to is named by a
    variable only the preload reads.
  • The row requires the whole record:
    set 30000, set 1000, fired 1000, set 30000, set 2000, fired 2000, set 30000. It also shows that each attempt arms a
    fresh deadline, and that each pause fires before the next attempt starts.
  • The server still counts three attempts, and the pauses it sees keep their lower bounds, 900 ms and 1900 ms.
    • The ceilings are gone. The server stamps an arrival and drops it in one step, so a stalled machine can only lengthen
      a pause.
    • The floors catch a pause that was recorded and never spent.
    • Arrivals are now stamped with performance.now(). The other users of that listener only count arrivals.
  • The row is three subtests over one install. It prints its record and both pauses before asserting anything, so
    every log carries a sample, including a red one.
  • Comments: the file header and the pin row's comment now say what is taken where. The pin claims only that each
    attempt arms a fresh deadline, not that the deadline ends one.

npm/install.js is unchanged.

Mutations

Each was made in the working tree, run, and restored by checksum:

mutation count record floors other rows
a pause after the last attempt (< to <=) pass fail pass the row before this change stays green under it
second pause made one second pass fail fail the pin stays green
a fourth attempt with a third pause fail fail pass the pin and three other rows fail
await dropped before the pause pass fail (no fired lines) fail
the preload fires each pause at once, recording it as asked pass pass fail

A dropped await fails the record by order, however loaded the machine is. A preload that fires the pauses at once is
caught by the floors alone. That is normally certain, but a long enough stall could in principle lift a near-zero
pause above a floor.

Measured

Before the change, the row's recorded results across every retained CI run: 2,575 readings on the five jobs that run it,
one red. On the Windows job, fifteen passes took over 3.8 s, the slowest 7.5 s.

Locally, before the change, 500 runs idle and 500 with every core busy: no red, and no pause short of its length.

The row "the waits between attempts are one second and then two" timed
the pauses between three attempts at the server and required each one
inside a window, 900-1800 ms and then 1900-2800 ms. A hosted Windows
runner stalled for several seconds once, the second pause measured
5407 ms, and the row went red with the schedule correct. A stopwatch on
a shared machine measures the machine.

The schedule is now read from the child. A preload in the test tree,
beside the other two, replaces the global setTimeout in the installer's
process: it writes down every delay asked for and when each one fires,
synchronously, and hands every call to the real timer, so each pause is
still spent. The row requires the whole record:

  set 30000, set 1000, fired 1000, set 30000, set 2000, fired 2000,
  set 30000

which also shows each attempt arming a fresh deadline, and that each
pause fires before the next attempt starts. The installer is unchanged
and carries no hook.

The server still counts three attempts, and the pauses it sees keep
their lower bounds, 900 ms and 1900 ms. The ceilings are gone: the
server stamps an arrival and drops it in one step, so a stalled machine
can only lengthen a pause, and the floors are what catch a pause that
was recorded and never spent. Arrivals are stamped on a monotonic clock.

The row is three subtests over one install, and prints its record and
both pauses before asserting anything, so every log carries a sample.
The file header and the pin row's comment are rewritten to say what is
taken where.
@enesismail
enesismail added this pull request to the merge queue Oct 11, 2026
Merged via the queue into main with commit 9dc6855 Oct 11, 2026
13 checks passed
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