@oclif/plugin-update 4.7.45 → 4.7.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,7 +81,7 @@ EXAMPLES
81
81
  $ oclif-example update --available
82
82
  ```
83
83
 
84
- _See code: [src/commands/update.ts](https://github.com/oclif/plugin-update/blob/4.7.45/src/commands/update.ts)_
84
+ _See code: [src/commands/update.ts](https://github.com/oclif/plugin-update/blob/4.7.46/src/commands/update.ts)_
85
85
  <!-- commandsstop -->
86
86
 
87
87
  # Contributing
package/dist/update.js CHANGED
@@ -8,7 +8,7 @@ import { mkdir, readdir, readFile, rm, stat, symlink, utimes, writeFile } from '
8
8
  import { basename, dirname, join } from 'node:path';
9
9
  import { ProxyAgent } from 'proxy-agent';
10
10
  import { Extractor } from './tar.js';
11
- import { ls, wait } from './util.js';
11
+ import { ls } from './util.js';
12
12
  const debug = makeDebug('oclif:update');
13
13
  const filesize = (n) => {
14
14
  const [num, suffix] = fileSize(n, { output: 'array' });
@@ -287,25 +287,52 @@ const s3VersionManifestKey = ({ config, hash, version }) => {
287
287
  const s3SubDir = composeS3SubDir(config);
288
288
  return join(s3SubDir, 'versions', version, hash, `${bin}-v${version}-${hash}-${determinePlatform(config)}-${arch}-buildmanifest`);
289
289
  };
290
- // when autoupdating, wait until the CLI isn't active
291
- const debounce = async (cacheDir) => {
292
- let output = false;
290
+ // When autoupdating, wait until the CLI isn't active (lastrun mtime > 1 hour old).
291
+ //
292
+ // IMPORTANT: every CLI invocation touches lastrun before this function runs, so
293
+ // while the user is actively using the CLI, `lastrun + 1hr` keeps shifting
294
+ // forward and this wait never naturally resolves. The previous implementation
295
+ // recursed forever in that scenario, leaving each spawned autoupdate child
296
+ // pinned in memory as a full node process for the entire active session. When
297
+ // combined with the race documented in hooks/init.ts (which could spawn
298
+ // multiple such children per debounce window), the leaked children compounded
299
+ // until OOM on machines doing heavy CLI setup.
300
+ //
301
+ // Fix: cap the wait at a sensible wall-clock max. If the user is still active
302
+ // after that, abandon this autoupdate run — the next CLI invocation will fire
303
+ // a new one when it's again "needed".
304
+ const MAX_DEBOUNCE_WAIT_MS = 6 * 60 * 60 * 1000; // 6 hours
305
+ const DEBOUNCE_POLL_INTERVAL_MS = 60 * 1000; // 1 minute
306
+ const debounce = (cacheDir) => {
293
307
  const lastrunfile = join(cacheDir, 'lastrun');
294
- const m = await mtime(lastrunfile);
295
- m.setHours(m.getHours() + 1);
296
- if (m > new Date()) {
297
- const msg = `waiting until ${m.toISOString()} to update`;
298
- if (output) {
299
- debug(msg);
300
- }
301
- else {
302
- ux.stdout(msg);
303
- output = true;
304
- }
305
- await wait(60 * 1000); // wait 1 minute
306
- return debounce(cacheDir);
307
- }
308
- ux.stdout('time to update');
308
+ const startedAt = Date.now();
309
+ let announced = false;
310
+ return new Promise((resolve) => {
311
+ const check = async () => {
312
+ const m = await mtime(lastrunfile);
313
+ m.setHours(m.getHours() + 1);
314
+ if (m <= new Date()) {
315
+ ux.stdout('time to update');
316
+ resolve();
317
+ return;
318
+ }
319
+ if (Date.now() - startedAt >= MAX_DEBOUNCE_WAIT_MS) {
320
+ ux.stdout('autoupdate: debounce wait exceeded; abandoning this run');
321
+ resolve();
322
+ return;
323
+ }
324
+ const msg = `waiting until ${m.toISOString()} to update`;
325
+ if (announced) {
326
+ debug(msg);
327
+ }
328
+ else {
329
+ ux.stdout(msg);
330
+ announced = true;
331
+ }
332
+ setTimeout(check, DEBOUNCE_POLL_INTERVAL_MS);
333
+ };
334
+ check();
335
+ });
309
336
  };
310
337
  const setChannel = async (channel, dataDir) => writeFile(join(dataDir, 'channel'), channel, 'utf8');
311
338
  const fetchChannelManifest = async (channel, config) => {
@@ -106,5 +106,5 @@
106
106
  ]
107
107
  }
108
108
  },
109
- "version": "4.7.45"
109
+ "version": "4.7.46"
110
110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oclif/plugin-update",
3
- "version": "4.7.45",
3
+ "version": "4.7.46",
4
4
  "author": "Salesforce",
5
5
  "bugs": "https://github.com/oclif/plugin-update/issues",
6
6
  "dependencies": {