querysub 0.580.0 → 0.582.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.582.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",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
72
72
|
"pako": "^2.1.0",
|
|
73
73
|
"peggy": "^5.0.6",
|
|
74
|
-
"sliftutils": "^1.7.
|
|
74
|
+
"sliftutils": "^1.7.51",
|
|
75
75
|
"socket-function": "^1.2.26",
|
|
76
76
|
"terser": "^5.31.0",
|
|
77
77
|
"typenode": "^6.6.1",
|
|
@@ -28,7 +28,8 @@ const PAST_COLOR = { h: 0, s: 0, l: 90 };
|
|
|
28
28
|
const FUTURE_COLOR = { h: 45, s: 80, l: 85 };
|
|
29
29
|
// Windows are days or hours wide, so the countdown only has to be roughly right
|
|
30
30
|
const TIME_REFRESH_INTERVAL = 60 * 1000;
|
|
31
|
-
|
|
31
|
+
// Watching exists to see a config change as it happens - a deploy or a server disagreeing with the others - so it polls far faster than the window countdowns need to update
|
|
32
|
+
const WATCH_POLL_INTERVAL = 5 * 1000;
|
|
32
33
|
const WATCH_ACTIVE_COLOR = { h: 195, s: 60, l: 85 };
|
|
33
34
|
const WINDOW_HEADER_SIZE = 13;
|
|
34
35
|
const WINDOW_TIME_SIZE = 14;
|
|
@@ -513,7 +514,8 @@ class RouteConfigGroupView extends qreact.Component<{ group: RouteConfigGroup }>
|
|
|
513
514
|
class LiveWatchView extends qreact.Component<{ watchKey: string; watch: LiveWatch }> {
|
|
514
515
|
render() {
|
|
515
516
|
let { watchKey, watch } = this.props;
|
|
516
|
-
|
|
517
|
+
// Ticks with the polling, not with the window countdowns - "updated 1 minute ago" on something refreshed seconds ago reads as broken
|
|
518
|
+
let now = Querysub.timeDelayed(WATCH_POLL_INTERVAL);
|
|
517
519
|
let sources = (watch.routing?.sources || []).map(normalizeSource);
|
|
518
520
|
return <div className={css.vbox(10).fillWidth.pad2(10, 8).bord2(WATCH_ACTIVE_COLOR.h, WATCH_ACTIVE_COLOR.s, WATCH_ACTIVE_COLOR.l - 25)}>
|
|
519
521
|
<div className={css.hbox(8).wrap.fontSize(WINDOW_HEADER_SIZE)}>
|
|
@@ -220,6 +220,11 @@ const ensureGitSynced = measureWrap(async function ensureGitSynced(config: {
|
|
|
220
220
|
let launchesPerService = new Map<string, number>();
|
|
221
221
|
let lastLaunchedTimePerService = new Map<string, number>();
|
|
222
222
|
|
|
223
|
+
// How often we check that everything that should be running still is. Cheap - it asks tmux and the local filesystem - so it runs often enough that a crashed process is noticed in seconds rather than minutes.
|
|
224
|
+
const RESYNC_INTERVAL = timeInSecond * 30;
|
|
225
|
+
// How often the configs themselves are re-read. Reading them hits backblaze, so this is the interval that has to stay conservative, and it is entirely independent of how often we check liveness.
|
|
226
|
+
const CONFIG_REFRESH_INTERVAL = RESYNC_INTERVAL * 6;
|
|
227
|
+
|
|
223
228
|
const LAUNCH_VERIFY_DELAY = 2000;
|
|
224
229
|
// 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.
|
|
225
230
|
const START_TIME_TOLERANCE = timeInSecond * 5;
|
|
@@ -448,10 +453,29 @@ function sameRestartParameters(prevParametersJSON: string, next: ServiceParamete
|
|
|
448
453
|
}
|
|
449
454
|
}
|
|
450
455
|
|
|
456
|
+
// The configs come from backblaze, and reading them is by far the most expensive thing a resync does - far too expensive to do every time we want to check that the processes are still up, which is the other, much cheaper half of a resync. So the configs are re-read on their own schedule and reused in between.
|
|
457
|
+
let cachedConfigs: ServiceConfig[] | undefined;
|
|
458
|
+
let cachedConfigsTime = 0;
|
|
459
|
+
// Set when something tells us the configs actually changed, which no interval can predict
|
|
460
|
+
let configRefreshRequested = false;
|
|
461
|
+
async function getResyncConfigs(): Promise<{ configs: ServiceConfig[]; refreshed: boolean }> {
|
|
462
|
+
let force = configRefreshRequested;
|
|
463
|
+
if (!force && cachedConfigs && Date.now() - cachedConfigsTime < CONFIG_REFRESH_INTERVAL) {
|
|
464
|
+
return { configs: cachedConfigs, refreshed: false };
|
|
465
|
+
}
|
|
466
|
+
// Cleared before the read, so a change arriving DURING it is not swallowed by our own success
|
|
467
|
+
configRefreshRequested = false;
|
|
468
|
+
cachedConfigs = await getEffectiveServiceConfigs();
|
|
469
|
+
cachedConfigsTime = Date.now();
|
|
470
|
+
return { configs: cachedConfigs, refreshed: true };
|
|
471
|
+
}
|
|
472
|
+
|
|
451
473
|
const resyncServicesBase = runInSerial(measureWrap(async function resyncServices() {
|
|
452
|
-
console.log(magenta("Resyncing services"));
|
|
453
474
|
let machineId = getOwnMachineId(getDomain());
|
|
454
|
-
let allConfigs = await
|
|
475
|
+
let { configs: allConfigs, refreshed } = await getResyncConfigs();
|
|
476
|
+
if (refreshed) {
|
|
477
|
+
console.log(magenta("Resyncing services, with freshly read configs"));
|
|
478
|
+
}
|
|
455
479
|
let relevantConfigs = allConfigs
|
|
456
480
|
.filter(config => getMachineIdList(getLiveServiceParameters(config)).includes(machineId) || getMachineIdList(config.parameters).includes(machineId) || config.oldParameters && getMachineIdList(config.oldParameters).includes(machineId))
|
|
457
481
|
.filter(x => getLiveServiceParameters(x).deploy || x.parameters.deploy || x.oldParameters?.deploy);
|
|
@@ -500,11 +524,19 @@ const resyncServicesBase = runInSerial(measureWrap(async function resyncServices
|
|
|
500
524
|
}
|
|
501
525
|
|
|
502
526
|
await machineInfos.set(machineId, machineInfo);
|
|
503
|
-
|
|
527
|
+
// Only on the runs that read the configs. The rest are a liveness check that happens many times a minute, and dumping the whole machine info each time buries everything that actually matters.
|
|
528
|
+
if (refreshed) {
|
|
529
|
+
console.log(`${magenta(`Resynced ${relevantConfigs.length} services`)}:\n${JSON.stringify(machineInfo, null, 2)}`);
|
|
530
|
+
}
|
|
504
531
|
|
|
505
532
|
// Don't resync TOO often, so always wait a bit
|
|
506
533
|
await delay(5000);
|
|
507
534
|
}));
|
|
535
|
+
/** A resync that re-reads the configs, however recently they were last read - for when something tells us they changed. */
|
|
536
|
+
async function resyncServicesWithFreshConfigs() {
|
|
537
|
+
configRefreshRequested = true;
|
|
538
|
+
await resyncServices();
|
|
539
|
+
}
|
|
508
540
|
async function resyncServices() {
|
|
509
541
|
try {
|
|
510
542
|
await resyncServicesBase();
|
|
@@ -568,10 +600,10 @@ export async function machineApplyMain() {
|
|
|
568
600
|
|
|
569
601
|
|
|
570
602
|
await Querysub.hostService("machine-apply");
|
|
571
|
-
onServiceConfigChange(
|
|
603
|
+
onServiceConfigChange(resyncServicesWithFreshConfigs);
|
|
572
604
|
|
|
573
605
|
|
|
574
|
-
runInfinitePoll(
|
|
606
|
+
runInfinitePoll(RESYNC_INTERVAL, async () => {
|
|
575
607
|
//console.log(magenta(`Quick outdated check at ${new Date().toISOString()}`));
|
|
576
608
|
// console.log(magenta("Likely outdated, resyncing now"));
|
|
577
609
|
// NOTE: I'm not sure why we were hesitant to call this. It shouldn't be that slow...
|