feat(platform): add source readiness operations view
This commit is contained in:
@@ -287,6 +287,47 @@ test('onlineVehicleStatuses reads paged online vehicle status rows', async () =>
|
||||
expect(result.items[0].offlineDurationMinutes).toBe(18);
|
||||
});
|
||||
|
||||
test('sourceReadiness reads ops source readiness plan', async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
data: {
|
||||
totalVehicles: 1033,
|
||||
onlineVehicles: 208,
|
||||
kafkaLag: 0,
|
||||
activeConnections: 178,
|
||||
redisOnlineKeys: 258,
|
||||
platformRelease: 'platform-source-test',
|
||||
sources: [{
|
||||
protocol: 'GB32960',
|
||||
role: '整车与氢能实时数据主来源',
|
||||
online: 73,
|
||||
total: 340,
|
||||
onlineRate: 21.47,
|
||||
missingVehicles: 693,
|
||||
severity: 'warning',
|
||||
status: '覆盖不足',
|
||||
evidence: '在线 73/340',
|
||||
action: '核对平台转发清单',
|
||||
acceptance: '缺失来源车辆下降',
|
||||
vehiclesHash: '#/vehicles?missingProtocol=GB32960',
|
||||
realtimeHash: '#/realtime?protocol=GB32960',
|
||||
historyHash: '#/history-query?protocol=GB32960&tab=raw',
|
||||
alertHash: '#/alert-events?protocol=GB32960'
|
||||
}]
|
||||
},
|
||||
traceId: 'trace-test',
|
||||
timestamp: 1783094400000
|
||||
})
|
||||
} as Response);
|
||||
|
||||
const result = await api.sourceReadiness();
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith('/api/ops/source-readiness', undefined);
|
||||
expect(result.platformRelease).toBe('platform-source-test');
|
||||
expect(result.sources[0].protocol).toBe('GB32960');
|
||||
});
|
||||
|
||||
test('api errors include backend message, detail, and trace id', async () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue({
|
||||
ok: false,
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
QualityIssueRow,
|
||||
RawFrameRow,
|
||||
RealtimeLocationRow,
|
||||
SourceReadinessPlan,
|
||||
VehicleRealtimeRow,
|
||||
VehicleCoverageRow,
|
||||
VehicleCoverageSummary,
|
||||
@@ -117,5 +118,6 @@ export const api = {
|
||||
alertEvents: (params = new URLSearchParams()) => request<Page<QualityIssueRow>>(`/api/alert-events?${params.toString()}`),
|
||||
alertEventNotificationPlan: (params = new URLSearchParams()) => request<QualityNotificationPlan>(`/api/alert-events/notification-plan?${params.toString()}`),
|
||||
reverseGeocode: (params = new URLSearchParams()) => request<MapReverseGeocode>(`/api/map/reverse-geocode?${params.toString()}`),
|
||||
opsHealth: () => request<OpsHealth>('/api/ops/health')
|
||||
opsHealth: () => request<OpsHealth>('/api/ops/health'),
|
||||
sourceReadiness: () => request<SourceReadinessPlan>('/api/ops/source-readiness')
|
||||
};
|
||||
|
||||
@@ -359,6 +359,34 @@ export interface OpsHealth {
|
||||
runtime: RuntimeInfo;
|
||||
}
|
||||
|
||||
export interface SourceReadinessPlan {
|
||||
totalVehicles: number;
|
||||
onlineVehicles: number;
|
||||
kafkaLag: number | null;
|
||||
activeConnections: number | null;
|
||||
redisOnlineKeys: number | null;
|
||||
platformRelease: string;
|
||||
sources: SourceReadinessRow[];
|
||||
}
|
||||
|
||||
export interface SourceReadinessRow {
|
||||
protocol: string;
|
||||
role: string;
|
||||
online: number;
|
||||
total: number;
|
||||
onlineRate: number;
|
||||
missingVehicles: number;
|
||||
severity: 'ok' | 'warning' | 'error' | string;
|
||||
status: string;
|
||||
evidence: string;
|
||||
action: string;
|
||||
acceptance: string;
|
||||
vehiclesHash: string;
|
||||
realtimeHash: string;
|
||||
historyHash: string;
|
||||
alertHash: string;
|
||||
}
|
||||
|
||||
export interface CapacityMetrics {
|
||||
activeConnections: number;
|
||||
kafkaLag: number;
|
||||
|
||||
Reference in New Issue
Block a user