mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-03-03 09:50:19 +00:00
fix(k9s): add release update timeout
This commit is contained in:
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user