added cache

This commit is contained in:
2026-10-30 19:12:05 -07:00
parent 35192b1693
commit 6a77e21c8d

View File

@@ -1,20 +1,132 @@
var RELEASE_CACHE = {};
var RELEASE_REQUESTS = {};
var RELEASE_CACHE_TTL = 15 * 60 * 1000;
var RELEASE_BACKOFF = {};
var RELEASE_MAX_RETRIES = 3;
function fetchProjectReleases(project) {
if (RELEASE_CACHE[project]) return Promise.resolve(RELEASE_CACHE[project]);
var url = "https://gitlab.com/api/v4/projects/vyla-entertainment%2F" + encodeURIComponent(project) + "/releases";
return fetch(url)
.then(function (res) {
if (!res.ok) throw new Error();
return res.json();
})
.then(function (data) {
RELEASE_CACHE[project] = Array.isArray(data) ? data : [];
return RELEASE_CACHE[project];
})
var now = Date.now();
var cached = RELEASE_CACHE[project];
if (cached && now - cached.timestamp < RELEASE_CACHE_TTL) {
return Promise.resolve(cached.data);
}
if (RELEASE_REQUESTS[project]) {
return RELEASE_REQUESTS[project];
}
var backoff = RELEASE_BACKOFF[project];
if (backoff && now < backoff.until) {
return Promise.resolve(cached ? cached.data : []);
}
var url = "https://gitlab.com/api/v4/projects/vyla-entertainment%2F" +
encodeURIComponent(project) + "/releases";
var request = function (attempt) {
return fetch(url)
.then(function (res) {
if (res.status === 429) {
var retryAfter = Number(res.headers.get("Retry-After"));
var delay = retryAfter > 0
? retryAfter * 1000
: Math.min(5000 * Math.pow(2, attempt), 60000);
RELEASE_BACKOFF[project] = {
until: Date.now() + delay
};
if (attempt < RELEASE_MAX_RETRIES) {
return new Promise(function (resolve) {
setTimeout(resolve, delay);
}).then(function () {
return request(attempt + 1);
});
}
throw new Error("GitLab rate limit exceeded");
}
if (!res.ok) {
throw new Error("GitLab API returned " + res.status);
}
return res.json();
})
.then(function (data) {
if (!Array.isArray(data)) {
throw new Error("Invalid GitLab releases response");
}
RELEASE_CACHE[project] = {
data: data,
timestamp: Date.now()
};
delete RELEASE_BACKOFF[project];
return data;
});
};
RELEASE_REQUESTS[project] = request(0)
.catch(function () {
return [];
return cached ? cached.data : [];
})
.finally(function () {
delete RELEASE_REQUESTS[project];
});
return RELEASE_REQUESTS[project];
}
function findAssetInReleases(releases, ext) {
for (var r = 0; r < releases.length; r++) {
var rel = releases[r];
var tag = rel.tag_name || "";
var links = (rel.assets && rel.assets.links) || [];
for (var i = 0; i < links.length; i++) {
var l = links[i];
var name = (l.name || "").toLowerCase();
var url = (l.url || "").toLowerCase();
if (name.indexOf(ext.toLowerCase()) !== -1 ||
url.indexOf(ext.toLowerCase()) !== -1) {
return {
tag: tag,
url: l.direct_asset_url || l.url
};
}
}
if (rel.description) {
var escapedExt = ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
var reg = new RegExp(
"\\[([^\\]]+)\\]\\((https?:[^)]+\\." + escapedExt + "[^)]*)\\)",
"i"
);
var match = rel.description.match(reg);
if (match) {
return { tag: tag, url: match[2] };
}
var rawMatch = rel.description.match(
new RegExp("(https?:\\S+\\." + escapedExt + ")", "i")
);
if (rawMatch) {
return { tag: tag, url: rawMatch[1] };
}
}
}
return null;
}
function findAssetInReleases(releases, ext) {