feat(stacks): per-stack action tracking, optimistic status, and bulk status endpoint (#362)

* feat(stacks): per-stack action tracking, optimistic status, and bulk status endpoint

Replace global loadingAction mutex with per-stack tracking so users can
fire actions on multiple stacks concurrently. Add optimistic status
updates to fix sidebar showing "--" after stop/start. Add bulk
GET /api/stacks/statuses endpoint using a single docker.listContainers
call instead of N docker compose ps invocations (~21s → ~110ms for 3
stacks). Falls back to per-stack queries for remote nodes on older
versions.

* fix(stacks): remove stale 'start' action check from deploy button label
This commit is contained in:
Anso
2026-04-03 17:19:10 -04:00
committed by GitHub
parent fc58158efc
commit dfd4d2858a
4 changed files with 201 additions and 72 deletions
+23
View File
@@ -364,6 +364,29 @@ class DockerController {
return this.validateApiData<any[]>(containers);
}
public async getBulkStackStatuses(stackNames: string[]): Promise<Record<string, 'running' | 'exited' | 'unknown'>> {
const allContainers = await this.docker.listContainers({ all: true });
const knownSet = new Set(stackNames);
const statuses: Record<string, 'running' | 'exited' | 'unknown'> = {};
for (const name of stackNames) {
statuses[name] = 'unknown';
}
for (const container of allContainers as any[]) {
const project: string | undefined = container.Labels?.['com.docker.compose.project'];
if (project && knownSet.has(project)) {
if (container.State === 'running') {
statuses[project] = 'running';
} else if (statuses[project] !== 'running') {
statuses[project] = 'exited';
}
}
}
return statuses;
}
public async getContainersByStack(stackName: string) {
const stackDir = path.join(COMPOSE_DIR, stackName);