fix(k9s): add release update timeout

This commit is contained in:
AJ ONeal
2023-01-15 08:34:08 +00:00
parent 21c668b4b7
commit bab564bdeb
3 changed files with 104 additions and 83 deletions

View File

@@ -1,7 +1,7 @@
'use strict';
var fs = require('fs');
var path = require('path');
var fs = require('node:fs');
var path = require('node:path');
var request = require('@root/request');
var _normalize = require('../_webi/normalize.js');
@@ -9,22 +9,23 @@ var reInstallTpl = /\s*#?\s*{{ installer }}/;
var Releases = module.exports;
Releases.get = async function (pkgdir) {
var get;
let get;
try {
get = require(path.join(pkgdir, 'releases.js'));
} catch (e) {
throw new Error('no releases.js for', pkgdir.split(/[\/\\]+/).pop());
}
return get(request).then(function (all) {
return _normalize(all);
});
let all = await get(request);
return _normalize(all);
};
function padScript(txt) {
return txt.replace(/^/g, ' ');
}
Releases.renderBash = function (
Releases.renderBash = async function (
pkgdir,
rel,
{ baseurl, pkg, tag, ver, os = '', arch = '', formats },
@@ -153,7 +154,7 @@ Releases.renderBash = function (
});
};
Releases.renderBatch = function (
Releases.renderBatch = async function (
pkgdir,
rel,
{ baseurl, pkg, tag, ver, os, arch, formats },
@@ -193,7 +194,7 @@ Releases.renderBatch = function (
});
};
Releases.renderPowerShell = function (
Releases.renderPowerShell = async function (
pkgdir,
rel,
{ baseurl, pkg, tag, ver, os, arch, formats },

View File

@@ -52,41 +52,41 @@ module.exports = async function serveInstaller(
// TODO maybe move package/version/lts/channel detection into getReleases
var myOs = uaDetect.os(ua);
var myArch = uaDetect.arch(ua);
return packages.get(pkg).then(function (cfg) {
return getReleases({
pkg: cfg.alias || pkg,
ver,
os: myOs,
arch: myArch,
lts,
channel,
formats,
limit: 1,
}).then(function (rels) {
var rel = rels.releases[0];
var pkgdir = path.join(installersDir, pkg);
var opts = {
baseurl,
pkg: cfg.alias || pkg,
ver,
tag,
os: myOs,
arch: myArch,
lts,
channel,
formats,
limit: 1,
};
rel.oses = rels.oses;
rel.arches = rels.arches;
rel.formats = rels.formats;
if ('bat' === ext) {
return Releases.renderBatch(pkgdir, rel, opts);
} else if ('ps1' === ext) {
return Releases.renderPowerShell(pkgdir, rel, opts);
} else {
return Releases.renderBash(pkgdir, rel, opts);
}
});
let cfg = await packages.get(pkg);
let rels = await getReleases({
pkg: cfg.alias || pkg,
ver,
os: myOs,
arch: myArch,
lts,
channel,
formats,
limit: 1,
});
var rel = rels.releases[0];
var pkgdir = path.join(installersDir, pkg);
var opts = {
baseurl,
pkg: cfg.alias || pkg,
ver,
tag,
os: myOs,
arch: myArch,
lts,
channel,
formats,
limit: 1,
};
rel.oses = rels.oses;
rel.arches = rels.arches;
rel.formats = rels.formats;
if ('bat' === ext) {
return Releases.renderBatch(pkgdir, rel, opts);
}
if ('ps1' === ext) {
return Releases.renderPowerShell(pkgdir, rel, opts);
}
return Releases.renderBash(pkgdir, rel, opts);
};

View File

@@ -64,41 +64,55 @@ function createFormatsSorter(formats) {
async function getCachedReleases(pkg) {
// returns { download: '<template string>', releases: [{ version, date, os, arch, lts, channel, download}] }
function putCache() {
cache[pkg].promise = cache[pkg].promise.then(function () {
var age = Date.now() - cache[pkg].updatedAt;
if (age < staleAge) {
//console.debug('NOT STALE ANYMORE - updated in previous promise');
return cache[pkg].all;
}
//console.debug('DOWNLOADING NEW "%s" releases', pkg);
var pkgdir = path.join(installerDir, pkg);
return Releases.get(pkgdir)
.then(function (all) {
//console.debug('DOWNLOADED NEW "%s" releases', pkg);
cache[pkg].updatedAt = Date.now();
cache[pkg].all = all;
})
.catch(function (e) {
console.error(
'Error fetching releases for "%s": %s',
pkg,
e.toString(),
);
cache[pkg].all = { download: '', releases: [] };
})
.then(function () {
return cache[pkg].all;
});
});
async function chainCachePromise(fn) {
cache[pkg].promise = cache[pkg].promise.then(fn);
return cache[pkg].promise;
}
var p;
async function sleep(ms) {
return await new Promise(function (resolve, reject) {
setTimeout(resolve, ms);
});
}
async function putCache() {
var age = Date.now() - cache[pkg].updatedAt;
if (age < staleAge) {
//console.debug('NOT STALE ANYMORE - updated in previous promise');
return cache[pkg].all;
}
//console.debug('DOWNLOADING NEW "%s" releases', pkg);
var pkgdir = path.join(installerDir, pkg);
// workaround for request timeout seeming to not work
let complete = false;
await Promise.race([
Releases.get(pkgdir).then(function (all) {
// Note: it is possible for slightly older data
// to replace slightly newer data, but this is better
// than being in a cycle where release updates _always_
// take longer than expected.
//console.debug('DOWNLOADED NEW "%s" releases', pkg);
cache[pkg].updatedAt = Date.now();
cache[pkg].all = all;
complete = true;
}),
sleep(5000).then(function () {
if (complete) {
return;
}
console.error(`request timeout waiting for '${pkg}' release info`);
}),
]);
return cache[pkg].all;
}
if (!cache[pkg]) {
cache[pkg] = {
updatedAt: 0,
all: null,
all: { download: '', releases: [] },
promise: Promise.resolve(),
};
}
@@ -106,17 +120,23 @@ async function getCachedReleases(pkg) {
var age = Date.now() - cache[pkg].updatedAt;
if (age >= expiredAge) {
//console.debug("EXPIRED - waiting");
p = putCache();
} else if (age >= staleAge) {
//console.debug("STALE - background update");
putCache();
p = Promise.resolve(cache[pkg].all);
} else {
//console.debug("FRESH");
p = Promise.resolve(cache[pkg].all);
return await Promise.race([
chainCachePromise(putCache),
new Promise(function (resolve) {
setTimeout(function () {
resolve(cache[pkg].all);
}, 5000);
}),
]);
}
return p;
if (age >= staleAge) {
//console.debug("STALE - background update");
chainCachePromise(putCache);
}
//console.debug("FRESH");
return await cache[pkg].all;
}
async function filterReleases(