querysub 0.710.0 → 0.711.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.711.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
80
80
|
"pako": "^2.1.0",
|
|
81
81
|
"peggy": "^5.0.6",
|
|
82
|
-
"sliftutils": "^1.
|
|
82
|
+
"sliftutils": "^1.8.20",
|
|
83
83
|
"socket-function": "^1.3.1",
|
|
84
84
|
"terser": "^5.31.0",
|
|
85
85
|
"typenode": "^6.6.1",
|
|
@@ -9,7 +9,8 @@ import { runPromise } from "../functional/runCommand";
|
|
|
9
9
|
import { getExternalIP } from "socket-function/src/networking";
|
|
10
10
|
import { errorToUndefined, errorToUndefinedSilent } from "../errors";
|
|
11
11
|
import { getDomain } from "../config";
|
|
12
|
-
import { formatTime } from "socket-function/src/formatting/format";
|
|
12
|
+
import { formatDateTime, formatTime } from "socket-function/src/formatting/format";
|
|
13
|
+
import { httpsRequest, HttpsResponseInfo } from "socket-function/src/https";
|
|
13
14
|
import { sort, timeInMinute, timeInSecond, watchSlowPromise } from "socket-function/src/misc";
|
|
14
15
|
import { isDefined, setPreciseTimeout } from "../misc";
|
|
15
16
|
import { logLoadTime } from "../logModuleLoadTimes";
|
|
@@ -247,6 +248,30 @@ function checkGitSyncedAndClean(gitFolder: string, gitRef: string): Promise<bool
|
|
|
247
248
|
return cached;
|
|
248
249
|
}
|
|
249
250
|
|
|
251
|
+
async function recordMissingDependency(config: { gitFolder: string; screenName: string; error: unknown }) {
|
|
252
|
+
let { gitFolder, screenName } = config;
|
|
253
|
+
let match = String((config.error as Error)?.stack || config.error).match(/(https?:\/\/\S+?\.tgz): Request failed "404 Not Found"/);
|
|
254
|
+
if (!match) return;
|
|
255
|
+
let failedUrl = new URL(match[1]);
|
|
256
|
+
let tarballUrl = NPM_REGISTRY_ORIGIN + failedUrl.pathname;
|
|
257
|
+
let outResponse: HttpsResponseInfo = { headers: {} };
|
|
258
|
+
try {
|
|
259
|
+
await httpsRequest(tarballUrl, undefined, "HEAD", false, { outResponse });
|
|
260
|
+
} catch { }
|
|
261
|
+
if (outResponse.statusCode !== 404) {
|
|
262
|
+
console.warn(`Yarn install for ${screenName} failed on ${match[1]} returning 404, but npm returned ${outResponse.statusCode} for ${tarballUrl}, so it is not missing and we are not backing off`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
let failures = (missingDependencyRetries.get(gitFolder)?.failures || 0) + 1;
|
|
266
|
+
let nextAttemptTime = failures >= MISSING_DEPENDENCY_MAX_FAILURES && Number.POSITIVE_INFINITY || Date.now() + MISSING_DEPENDENCY_RETRY_DELAY;
|
|
267
|
+
missingDependencyRetries.set(gitFolder, { failures, nextAttemptTime, tarballUrl });
|
|
268
|
+
if (failures >= MISSING_DEPENDENCY_MAX_FAILURES) {
|
|
269
|
+
console.error(`Giving up yarn installing for ${screenName}, ${tarballUrl} is still missing from npm after ${failures} failed installs. Retrying only on a config change.`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
console.warn(`Yarn install for ${screenName} failed because ${tarballUrl} is missing from npm (failure ${failures}/${MISSING_DEPENDENCY_MAX_FAILURES}), retrying at ${formatDateTime(nextAttemptTime)}`);
|
|
273
|
+
}
|
|
274
|
+
|
|
250
275
|
async function getQuerysubVersionMismatch(gitFolder: string): Promise<string> {
|
|
251
276
|
let packageJson = JSON.parse(await fs.promises.readFile(gitFolder + "package.json", "utf8")) as { dependencies?: { [name: string]: string } };
|
|
252
277
|
let requested = packageJson.dependencies?.querysub;
|
|
@@ -322,6 +347,11 @@ const RESYNC_INTERVAL = timeInSecond * 30;
|
|
|
322
347
|
const CONFIG_REFRESH_INTERVAL = RESYNC_INTERVAL * 6;
|
|
323
348
|
|
|
324
349
|
const LAUNCH_VERIFY_DELAY = 2000;
|
|
350
|
+
|
|
351
|
+
const NPM_REGISTRY_ORIGIN = "https://registry.npmjs.org";
|
|
352
|
+
const MISSING_DEPENDENCY_RETRY_DELAY = timeInMinute * 5;
|
|
353
|
+
const MISSING_DEPENDENCY_MAX_FAILURES = 5;
|
|
354
|
+
let missingDependencyRetries = new Map<string, { failures: number; nextAttemptTime: number; tarballUrl: string }>();
|
|
325
355
|
// How far a re-read start time may drift from the recorded one and still be the same process. Well under any interval a pid could be reused in, and wide enough for sources that only resolve to the second.
|
|
326
356
|
const START_TIME_TOLERANCE = timeInSecond * 5;
|
|
327
357
|
|
|
@@ -503,9 +533,22 @@ async function ensureScreen(config: {
|
|
|
503
533
|
let afterGitRef = await getGitRefLive(gitFolder);
|
|
504
534
|
let nodeModulesMissing = !await fsExistsAsync(gitFolder + "node_modules");
|
|
505
535
|
let querysubMismatch = await getQuerysubVersionMismatch(gitFolder);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
536
|
+
let missingRetry = missingDependencyRetries.get(gitFolder);
|
|
537
|
+
if (afterGitRef !== prevGitRef || nodeModulesMissing || querysubMismatch || missingRetry) {
|
|
538
|
+
if (missingRetry && Date.now() < missingRetry.nextAttemptTime) {
|
|
539
|
+
throw new Error(`Not yarn installing for ${screenName}, ${missingRetry.tarballUrl} was missing from npm after ${missingRetry.failures} failed installs. ${missingRetry.failures >= MISSING_DEPENDENCY_MAX_FAILURES && "Gave up, waiting for a config change to retry" || `Next attempt at ${formatDateTime(missingRetry.nextAttemptTime)}`}`);
|
|
540
|
+
}
|
|
541
|
+
console.log(green(`Yarn installing for ${magenta(screenName)} (ref ${prevGitRef} -> ${afterGitRef}, nodeModulesMissing=${nodeModulesMissing}, querysubMismatch=${querysubMismatch || "none"}, missingDependencyFailures=${missingRetry?.failures || 0})`));
|
|
542
|
+
try {
|
|
543
|
+
await runPromise(`yarn install --mutex network`, { cwd: gitFolder });
|
|
544
|
+
} catch (e) {
|
|
545
|
+
await recordMissingDependency({ gitFolder, screenName, error: e });
|
|
546
|
+
throw e;
|
|
547
|
+
}
|
|
548
|
+
if (missingRetry) {
|
|
549
|
+
console.log(green(`Yarn install for ${magenta(screenName)} succeeded after ${missingRetry.failures} failures from ${missingRetry.tarballUrl} missing from npm`));
|
|
550
|
+
missingDependencyRetries.delete(gitFolder);
|
|
551
|
+
}
|
|
509
552
|
}
|
|
510
553
|
}
|
|
511
554
|
|
|
@@ -654,6 +697,10 @@ const resyncServicesBase = runInSerial(measureWrap(async function resyncServices
|
|
|
654
697
|
/** A resync that re-reads the configs, however recently they were last read - for when something tells us they changed. */
|
|
655
698
|
async function resyncServicesWithFreshConfigs() {
|
|
656
699
|
configRefreshRequested = true;
|
|
700
|
+
if (missingDependencyRetries.size) {
|
|
701
|
+
console.log(`Config changed, clearing the missing dependency backoff for ${Array.from(missingDependencyRetries.keys()).join(", ")}`);
|
|
702
|
+
missingDependencyRetries.clear();
|
|
703
|
+
}
|
|
657
704
|
await resyncServices();
|
|
658
705
|
}
|
|
659
706
|
async function resyncServices() {
|