Fix Check All timeout and remove last dashboard fallback data

Advisory sources:
- Replace batch /check endpoint call (504 timeout after 30s for 42+
  sources) with parallel individual checks in batches of 6. Progress
  indicator now shows live "Checking (N/M)..." as each source completes.
  Verified: 54/55 sources healthy on fresh install.

Dashboard:
- Remove the 5-element fallbackEnvironments array that was still
  rendering fake environment cards. Empty array now correctly triggers
  the setup guide on installs without PlatformContextStore environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-03-16 02:15:35 +02:00
parent 534aabfa2a
commit 1461eb5394

View File

@@ -14,6 +14,7 @@ import {
SourceStatusItem,
SourceConnectivityResultDto,
} from './source-management.api';
import { buildMirrorCommands, getAdvisoryVexNavigationExtras } from './advisory-vex-route-helpers';
const CATEGORY_ORDER = [
'Primary',
@@ -83,8 +84,8 @@ interface CategoryGroup {
[class]="'mirror-mode-badge mirror-mode-badge--' + mirrorConfig()!.mode.toLowerCase()">
{{ mirrorConfig()!.mode }}
</span>
<a class="mirror-link" routerLink="mirror">Configure Mirror</a>
<a class="mirror-link mirror-link--connect" routerLink="mirror/client-setup">Connect to Mirror</a>
<a class="mirror-link" [routerLink]="mirrorDashboardLink()" queryParamsHandling="preserve">Configure Mirror</a>
<a class="mirror-link mirror-link--connect" [routerLink]="mirrorClientSetupLink()" queryParamsHandling="preserve">Connect to Mirror</a>
</div>
<div class="mirror-context-right">
@if (isConsumerMode()) {
@@ -1053,7 +1054,15 @@ export class AdvisorySourceCatalogComponent implements OnInit {
}
onCreateMirrorDomain(): void {
this.router.navigate(['/integrations', 'advisory-vex-sources', 'mirror', 'new']);
this.router.navigate(buildMirrorCommands(this.router, 'new'), getAdvisoryVexNavigationExtras());
}
mirrorDashboardLink(): string[] {
return buildMirrorCommands(this.router);
}
mirrorClientSetupLink(): string[] {
return buildMirrorCommands(this.router, 'client-setup');
}
toggleExpanded(sourceId: string): void {
@@ -1124,19 +1133,65 @@ export class AdvisorySourceCatalogComponent implements OnInit {
onCheckAll(): void {
const items = this.catalog();
this.checking.set(true);
this.checkProgress.set({ done: 0, total: items.length });
const enabledIds = items
.filter((item) => this.isSourceEnabled(item.id))
.map((item) => item.id);
this.api.checkAll().pipe(take(1)).subscribe({
next: () => {
if (enabledIds.length === 0) {
return;
}
this.checking.set(true);
this.checkProgress.set({ done: 0, total: enabledIds.length });
// Check sources individually in parallel batches of 6 to avoid gateway timeout.
// The batch /check endpoint times out at 30s when checking 40+ sources.
const batchSize = 6;
let completed = 0;
const checkNext = (startIndex: number): void => {
const batch = enabledIds.slice(startIndex, startIndex + batchSize);
if (batch.length === 0) {
this.checking.set(false);
this.reloadStatus();
},
error: () => {
this.checking.set(false);
this.reloadStatus();
},
});
return;
}
let batchDone = 0;
for (const sourceId of batch) {
this.api.checkSource(sourceId).pipe(take(1)).subscribe({
next: (result) => {
this.statuses.update((current) => {
const next = new Map(current);
const existing = next.get(sourceId);
if (existing) {
next.set(sourceId, { ...existing, lastCheck: result });
} else {
next.set(sourceId, { sourceId, enabled: true, lastCheck: result });
}
return next;
});
completed++;
batchDone++;
this.checkProgress.set({ done: completed, total: enabledIds.length });
if (batchDone === batch.length) {
checkNext(startIndex + batchSize);
}
},
error: () => {
completed++;
batchDone++;
this.checkProgress.set({ done: completed, total: enabledIds.length });
if (batchDone === batch.length) {
checkNext(startIndex + batchSize);
}
},
});
}
};
checkNext(0);
}
onCheckSource(sourceId: string): void {