/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Fetch previous run metadata from Taskcluster
async function fetchPreviousRunData() { try { const taskUrl = `${TASKCLUSTER_BASE_URL}/api/queue/v1/task/${process.env.TASK_ID}`; const taskData = await fetchJson(taskUrl); if (!taskData) {
console.log(`Failed to fetch task info from ${taskUrl}`); return;
}
const routes = taskData.routes || []; const latestRoute = routes.find(
route => route.startsWith("index.") && route.includes(".latest.")
); if (!latestRoute) {
console.log(
`No route found with 'index.' prefix and '.latest.' in name. Available routes: ${JSON.stringify(routes)}`
); return;
}
const indexUrl = `${artifactsUrl}/index.json`;
console.log(`Fetching previous run data from ${indexUrl}`); const indexData = await fetchJson(indexUrl); if (!indexData) {
console.log(`Failed to fetch index.json from ${indexUrl}`); return;
}
previousRunData = {
dates: new Set(dates),
artifactsUrl,
};
console.log("Previous run metadata loaded\n");
} catch (error) {
console.log(`Error fetching previous run metadata: ${error.message}`);
}
}
// The STMO query covers the day before it ran. function extractDateFromQuery(queryResult) { const retrieved = queryResult.retrieved_at; if (retrieved) { const d = new Date(retrieved);
d.setUTCDate(d.getUTCDate() - 1); return d.toISOString().split("T")[0];
} returnnull;
}
// Helper: create string table with findId function function createStringTables(tableNames) { const tables = {}; const maps = {}; for (const name of tableNames) {
tables[name] = [];
maps[name] = new Map();
}
function findId(tableName, value) { if (value == null || value === "") { returnnull;
} const map = maps[tableName];
let id = map.get(value); if (id === undefined) {
id = tables[tableName].length;
tables[tableName].push(value);
map.set(value, id);
} return id;
}
return { tables, findId };
}
// Sort string tables by frequency and remap all id arrays. // idArrays maps table name to one or more arrays of indices into that table. // Arrays may have different lengths (e.g. per-task vs per-worker). function sortAndRemapTables(tables, idArrays) { for (const [tableName, table] of Object.entries(tables)) { const arrays = idArrays[tableName] || []; const freq = new Array(table.length).fill(0);
for (const arr of arrays) { for (let i = 0; i < arr.length; i++) { if (arr[i] !== null) {
freq[arr[i]]++;
}
}
}
const order = table.map((val, idx) => ({ val, idx, count: freq[idx] }));
order.sort((a, b) => b.count - a.count || a.val.localeCompare(b.val));
const newTable = new Array(table.length); const oldToNew = new Array(table.length); for (let j = 0; j < order.length; j++) {
newTable[j] = order[j].val;
oldToNew[order[j].idx] = j;
}
tables[tableName] = newTable;
for (const arr of arrays) { for (let i = 0; i < arr.length; i++) { if (arr[i] !== null) {
arr[i] = oldToNew[arr[i]];
}
}
}
}
}
// Encode both summary and full task data in a single pass over the rows. // Returns { summary, taskData } ready to be serialized. function encodeData(rows, date) { const { tables, findId } = createStringTables([ "labels", "projects", "taskQueueIds", "resolutions", "workerGroups", "workerIds", "priorities", "users", "taskGroupIds",
]);
rows.sort((a, b) => Number(a.scheduled || 0) - Number(b.scheduled || 0));
const n = rows.length; const metadata = {
date,
generatedAt: new Date().toISOString(),
taskCount: n,
};
const scheduled = new Array(n); const started = new Array(n); const resolved = new Array(n); const resolutionIds = new Array(n); const taskQueueIdIds = new Array(n); const projectIds = new Array(n); const taskIds = new Array(n); const labelIds = new Array(n); const priorityIds = new Array(n); const taskGroupIdIds = new Array(n); const userIds = new Array(n); const workerIdIds = new Array(n); const runCosts = new Array(n);
const workerGroupIds = new Array(n); const rawProjectIds = new Array(n);
const absScheduled = new Array(n); for (let i = 0; i < n; i++) {
absScheduled[i] = Number(rows[i].scheduled || 0);
}
// Differential compression for scheduled times if (n > 0) {
scheduled[0] = absScheduled[0]; for (let i = 1; i < n; i++) {
scheduled[i] = absScheduled[i] - absScheduled[i - 1];
}
}
for (let i = 0; i < n; i++) { const row = rows[i]; const absStarted = row.started ? Number(row.started) : null; const absResolved = Number(row.resolved || 0);
// Build per-worker and per-task-group arrays from the remapped per-task arrays. const workerGroupForWorkerId = new Array(tables.workerIds.length).fill(null); const projectForTaskGroup = new Array(tables.taskGroupIds.length).fill(null); for (let i = 0; i < n; i++) { if (workerIdIds[i] !== null) {
workerGroupForWorkerId[workerIdIds[i]] = workerGroupIds[i];
} if (taskGroupIdIds[i] !== null && rawProjectIds[i] !== null) {
projectForTaskGroup[taskGroupIdIds[i]] = rawProjectIds[i];
}
}
// Derive per-task projectIds for the summary from the per-task-group mapping. for (let i = 0; i < n; i++) { const tgid = taskGroupIdIds[i];
projectIds[i] = tgid !== null ? projectForTaskGroup[tgid] : null;
}
async function main() { const scriptStartTime = Date.now();
if (process.env.TASK_ID) {
await fetchPreviousRunData();
}
// Fetch current data from STMO
console.log("Fetching worker task data from STMO..."); const stmoData = await fetchJson(DATA_URL); if (!stmoData) {
console.error("Failed to fetch data from STMO");
process.exit(1);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.