60 lines
3.0 KiB
TypeScript
60 lines
3.0 KiB
TypeScript
import type { GpoBackupStatusRecord, GpoBackupStatusResponse } from '../../src/api/assessor-api-contract';
|
|
import type { ImportProcessingRun, IngestionJob } from '../../src/domain/ingestion-persistence';
|
|
import type { AssessorRepository } from '../../src/persistence/assessor-repository';
|
|
import { RepositoryNotFoundError } from '../../src/persistence/repository-errors';
|
|
|
|
function latestByUpdatedAt(jobs: IngestionJob[]): IngestionJob | undefined {
|
|
return jobs.slice().sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt) || right.id.localeCompare(left.id))[0];
|
|
}
|
|
|
|
function latestRun(runs: ImportProcessingRun[]): ImportProcessingRun | undefined {
|
|
return runs.slice().sort((left, right) => Date.parse(right.completedAt) - Date.parse(left.completedAt) || right.id.localeCompare(left.id))[0];
|
|
}
|
|
|
|
function displayState(job: IngestionJob | undefined, run: ImportProcessingRun | undefined): GpoBackupStatusRecord['state'] {
|
|
if (!job) return 'recovery-required';
|
|
if (job.status === 'dead-letter') return 'dead-letter';
|
|
if (job.status === 'queued' || job.status === 'running') return job.status;
|
|
return run?.status === 'partial' ? 'partial' : 'succeeded';
|
|
}
|
|
|
|
export async function listProjectGpoBackupStatus(
|
|
repository: AssessorRepository,
|
|
projectId: string,
|
|
generatedAt: string
|
|
): Promise<GpoBackupStatusResponse> {
|
|
if (!await repository.getProject(projectId)) throw new RepositoryNotFoundError(`Projekt ${projectId} ist nicht vorhanden.`);
|
|
const [artifacts, jobs, instances, runs] = await Promise.all([
|
|
repository.listImportArtifacts(projectId),
|
|
repository.listIngestionJobs(projectId),
|
|
repository.listGpoBackupInstances(projectId),
|
|
repository.listProjectProcessingRuns(projectId)
|
|
]);
|
|
const records: GpoBackupStatusRecord[] = [];
|
|
for (const artifact of artifacts.filter(item => item.kind === 'source-file' && item.relativePath.startsWith('gpo-backups/'))) {
|
|
const job = latestByUpdatedAt(jobs.filter(item => item.kind === 'analyze-gpo-backup' && item.artifactId === artifact.id));
|
|
const run = latestRun(runs.filter(item => item.artifactId === artifact.id));
|
|
const gpoCount = run ? instances.filter(item => item.processingRunId === run.id).length : 0;
|
|
records.push({
|
|
version: 1,
|
|
artifactId: artifact.id,
|
|
assessmentId: artifact.assessmentId,
|
|
jobId: job?.id,
|
|
fileName: artifact.relativePath.slice('gpo-backups/'.length),
|
|
sizeBytes: artifact.sizeBytes,
|
|
submittedAt: artifact.createdAt,
|
|
updatedAt: job?.updatedAt ?? artifact.createdAt,
|
|
state: displayState(job, run),
|
|
attempts: job?.attempts ?? 0,
|
|
maxAttempts: job?.maxAttempts ?? 3,
|
|
lastErrorCode: job?.lastErrorCode,
|
|
processingStatus: run?.status,
|
|
completedAt: run?.completedAt,
|
|
gpoCount,
|
|
backupInstanceCount: gpoCount
|
|
});
|
|
}
|
|
records.sort((left, right) => Date.parse(right.submittedAt) - Date.parse(left.submittedAt) || right.artifactId.localeCompare(left.artifactId));
|
|
return { version: 1, projectId, generatedAt, records };
|
|
}
|