Files
windmill/cli/src/commands/workers/workers.ts
T
centdix 59f39d860a chore(cli): better folder structure + add config utils (#6319)
* organize in folders

* add config command

* fix

* cleaning

* move utility functions

* merge

* only show token with option

* only show token with option

* fix

* remove config command

* add config utils

* change paths

* nit

* clean path assigner

---------

Co-authored-by: Alexander Petric <alpetric@users.noreply.github.com>
2025-08-05 13:59:07 +00:00

106 lines
3.4 KiB
TypeScript

import { Command, Table } from "../../../deps.ts";
import { log } from "../../../deps.ts";
import * as wmill from "../../../gen/services.gen.ts";
import { pickInstance } from "../instance/instance.ts";
type GlobalOptions = {
instance?: string;
baseUrl?: string;
};
function toPercent(value: number | undefined): string {
return value != undefined ? `${(value * 100).toFixed(1)}%` : '?%';
}
async function displayWorkers(opts: GlobalOptions) {
const activeInstance = await pickInstance(opts, true);
if (activeInstance) {
const workerGroups = await wmill.listWorkerGroups();
const workers = await wmill.listWorkers({
pingSince: 10
});
const groupedWorkers = workerGroups.map(group => {
const groupWorkers = workers.filter(worker => worker.worker_group === group.name);
return {
groupName: group.name,
workers: groupWorkers
};
});
// Add workers that don't belong to any worker group
const ungroupedWorkers = workers.filter(worker =>
!workerGroups.some(group => group.name === worker.worker_group)
);
if (ungroupedWorkers.length > 0) {
ungroupedWorkers.forEach(worker => {
const groupName = worker.worker_group || "Ungrouped";
let group = groupedWorkers.find(g => g.groupName === groupName);
if (!group) {
group = { groupName, workers: [] };
groupedWorkers.push(group);
}
group.workers.push(worker);
});
}
// Sort groupedWorkers
groupedWorkers.sort((a, b) => {
// Always put 'default' first
if (a.groupName === 'default') return -1;
if (b.groupName === 'default') return 1;
// Then sort by number of workers (descending order)
return b.workers.length - a.workers.length;
});
groupedWorkers.forEach(group => {
log.info(`\nWorker Group: ${group.groupName} (${group.workers.length} workers)`);
if (group.workers.length === 0) {
log.info(" No workers in this group");
} else {
new Table()
.header(["Worker ID", "Host", "Queues", "Jobs", "Occupancy rate 15s/5m/30m/ever)", "Last job", "Last Ping"])
.padding(2)
.border(true)
.maxColWidth(30)
.body(group.workers.map(worker => [
worker.worker,
worker.worker_instance,
worker.custom_tags?.join(', ') || '',
worker.jobs_executed,
`${toPercent(worker.occupancy_rate_15s)}/${toPercent(worker.occupancy_rate_5m)}/${toPercent(worker.occupancy_rate_30m)}/${toPercent(worker.occupancy_rate)}`,
worker.last_job_id ? worker.last_job_id + ' ' +worker.last_job_workspace_id : '',
`${worker.last_ping}s ago`
]))
.render();
}
});
} else {
log.info("No active instance found");
log.info("Use 'wmill instance add' to add a new instance");
}
}
const command = new Command()
.description("List all workers grouped by worker groups")
.option(
"--instance [instance]",
"Name of the instance to push to, override the active instance"
)
.option(
"--base-url [baseUrl]",
"If used with --token, will be used as the base url for the instance"
)
.action(displayWorkers as any);
export default command;