Fix duplicate variant analysis results downloads
This adds a new file `repo_states.json` which tracks the download status of all repositories of a variant analysis. We will write this file when a download has completed and skip a repository download if the repo state is marked as `succeeded`. This should prevent duplicate downloads. This will still queue all repositories, even those which have already been downloaded. However, I expect the actual cost in the download method to be negligible since it's just an in-memory check.
This commit is contained in:
@@ -29,6 +29,8 @@ import * as fs from 'fs-extra';
|
||||
|
||||
|
||||
export class VariantAnalysisManager extends DisposableObject implements VariantAnalysisViewManager<VariantAnalysisView> {
|
||||
private static readonly REPO_STATES_FILENAME = 'repo_states.json';
|
||||
|
||||
private readonly _onVariantAnalysisAdded = this.push(new EventEmitter<VariantAnalysis>());
|
||||
public readonly onVariantAnalysisAdded = this._onVariantAnalysisAdded.event;
|
||||
private readonly _onVariantAnalysisStatusUpdated = this.push(new EventEmitter<VariantAnalysis>());
|
||||
@@ -43,6 +45,8 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
private static readonly maxConcurrentDownloads = 3;
|
||||
private readonly queue = new PQueue({ concurrency: VariantAnalysisManager.maxConcurrentDownloads });
|
||||
|
||||
private readonly repoStates = new Map<number, Record<number, VariantAnalysisScannedRepositoryState>>();
|
||||
|
||||
constructor(
|
||||
private readonly ctx: ExtensionContext,
|
||||
private readonly storagePath: string,
|
||||
@@ -63,6 +67,15 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
this._onVariantAnalysisRemoved.fire(variantAnalysis);
|
||||
} else {
|
||||
await this.setVariantAnalysis(variantAnalysis);
|
||||
|
||||
try {
|
||||
const repoStates = await fs.readJson(this.getRepoStatesStoragePath(variantAnalysis.id));
|
||||
this.repoStates.set(variantAnalysis.id, repoStates);
|
||||
} catch (e) {
|
||||
// Ignore this error, we simply might not have downloaded anything yet
|
||||
this.repoStates.set(variantAnalysis.id, {});
|
||||
}
|
||||
|
||||
if (status === QueryStatus.InProgress) {
|
||||
// In this case, last time we checked, the query was still in progress.
|
||||
// We need to setup the monitor to check for completion.
|
||||
@@ -148,6 +161,8 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
|
||||
await this.prepareStorageDirectory(variantAnalysis.id);
|
||||
|
||||
this.repoStates.set(variantAnalysis.id, {});
|
||||
|
||||
this._onVariantAnalysisAdded.fire(variantAnalysis);
|
||||
}
|
||||
|
||||
@@ -162,6 +177,14 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
|
||||
private async onRepoStateUpdated(variantAnalysisId: number, repoState: VariantAnalysisScannedRepositoryState): Promise<void> {
|
||||
await this.getView(variantAnalysisId)?.updateRepoState(repoState);
|
||||
|
||||
let repoStates = this.repoStates.get(variantAnalysisId);
|
||||
if (!repoStates) {
|
||||
repoStates = {};
|
||||
this.repoStates.set(variantAnalysisId, repoStates);
|
||||
}
|
||||
|
||||
repoStates[repoState.repositoryId] = repoState;
|
||||
}
|
||||
|
||||
public async monitorVariantAnalysis(
|
||||
@@ -176,6 +199,10 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
cancellationToken: CancellationToken
|
||||
): Promise<void> {
|
||||
if (this.repoStates.get(variantAnalysisSummary.id)?.[scannedRepo.repository.id]?.downloadStatus === VariantAnalysisScannedRepositoryDownloadStatus.Succeeded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const repoState = {
|
||||
repositoryId: scannedRepo.repository.id,
|
||||
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.Pending,
|
||||
@@ -215,6 +242,8 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Succeeded;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
|
||||
await fs.outputJson(this.getRepoStatesStoragePath(variantAnalysisSummary.id), this.repoStates.get(variantAnalysisSummary.id));
|
||||
}
|
||||
|
||||
public async enqueueDownload(
|
||||
@@ -236,6 +265,13 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
);
|
||||
}
|
||||
|
||||
private getRepoStatesStoragePath(variantAnalysisId: number): string {
|
||||
return path.join(
|
||||
this.getVariantAnalysisStorageLocation(variantAnalysisId),
|
||||
VariantAnalysisManager.REPO_STATES_FILENAME
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a directory for storing results for a variant analysis.
|
||||
* This directory contains a timestamp file, which will be
|
||||
|
||||
Reference in New Issue
Block a user