Skip to content

Commit

Permalink
fix: remove snyk code client side timeout (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
Asaf Agami authored Jul 18, 2023
1 parent 5af1ccb commit 0c6ba0c
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 56 deletions.
30 changes: 1 addition & 29 deletions Snyk.Code.Library.Tests/SnykCode/AnalysisServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void AnalysisService_FailedStatusProvided_GetAnalysisThrowException()
.Setup(codeClient => codeClient.GetAnalysisAsync(dummyBundleId, It.IsAny<CancellationToken>()))
.ReturnsAsync(dummyAnalysisResultDto);

_ = Assert.ThrowsAsync<AggregateException>(() => analysisService.GetAnalysisAsync(dummyBundleId, scanCodeProgressUpdate));
_ = Assert.ThrowsAsync<AggregateException>(() => analysisService.GetAnalysisAsync(dummyBundleId, this.scanCodeProgressUpdate));

codeClientMock
.Verify(codeClient => codeClient.GetAnalysisAsync(dummyBundleId, It.IsAny<CancellationToken>()), Times.Exactly(1));
Expand Down Expand Up @@ -83,34 +83,6 @@ public async Task AnalysisService_WaitingStatusProvided_GetAnalysisSuccessInTwoA
.Verify(codeClient => codeClient.GetAnalysisAsync(dummyBundleId, It.IsAny<CancellationToken>()), Times.Exactly(24));
}

[Fact]
public async Task AnalysisService_InfiniteWaitingStatusProvided_GetAnalysisReturnFailedStatusAsync()
{
var codeClientMock = new Mock<ISnykCodeClient>();

var analysisService = new AnalysisService(codeClientMock.Object);

var analysisResultsDto = new AnalysisResultsDto();

string dummyBundleId = "dummyId";

var dummyAnalysisResultDto = new AnalysisResultDto
{
Status = AnalysisStatus.Waiting,
};

codeClientMock
.Setup(codeClient => codeClient.GetAnalysisAsync(dummyBundleId, It.IsAny<CancellationToken>()))
.ReturnsAsync(dummyAnalysisResultDto);

var analysisResult = await analysisService.GetAnalysisAsync(dummyBundleId, this.scanCodeProgressUpdate, requestAttempts: 5);

Assert.NotNull(analysisResult);
Assert.Equal(AnalysisStatus.Failed, analysisResult.Status);

codeClientMock
.Verify(codeClient => codeClient.GetAnalysisAsync(dummyBundleId, It.IsAny<CancellationToken>()), Times.Exactly(5));
}

[Fact]
public async Task AnalysisService_TwoFilesWithIssuesProvided_GetAnalysisSuccessAsync()
Expand Down
7 changes: 3 additions & 4 deletions Snyk.Code.Library.Tests/SnykCode/SnykCodeServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ public async Task SnykCodeService_CodeCacheAndFileChangesExists_UpdatePreviousSc
.Setup(analysisService => analysisService.GetAnalysisAsync(
extendedBundle.Id,
It.IsAny<FireScanCodeProgressUpdate>(),
It.IsAny<int>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(analysisResults);

Expand Down Expand Up @@ -208,7 +207,7 @@ public async Task SnykCodeService_CodeCacheExists_ReturnWithoutRemoteQueryAsync(
Assert.NotNull(analysisResult);

this.analysisServiceMock
.Verify(analysisService => analysisService.GetAnalysisAsync(It.IsAny<string>(), It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<int>(), It.IsAny<CancellationToken>()), Times.Exactly(0));
.Verify(analysisService => analysisService.GetAnalysisAsync(It.IsAny<string>(), It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<CancellationToken>()), Times.Exactly(0));

this.codeCacheServiceMock
.Verify(codeCacheService => codeCacheService.GetCachedAnalysisResult(), Times.Exactly(1));
Expand Down Expand Up @@ -285,7 +284,7 @@ public async Task SnykCodeService_TwoFilesWithIssuesProvided_ScanSuccessAsync()
.ReturnsAsync(bundle);

this.analysisServiceMock
.Setup(analysisService => analysisService.GetAnalysisAsync(bundleId, It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Setup(analysisService => analysisService.GetAnalysisAsync(bundleId, It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(analysisResults);

this.codeCacheServiceMock
Expand Down Expand Up @@ -315,7 +314,7 @@ public async Task SnykCodeService_TwoFilesWithIssuesProvided_ScanSuccessAsync()
.Verify(bundleService => bundleService.UploadMissingFilesAsync(It.IsAny<Bundle>(), It.IsAny<ICodeCacheService>(), It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<CancellationToken>()), Times.Exactly(1));

this.analysisServiceMock
.Verify(analysisService => analysisService.GetAnalysisAsync(bundleId, It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<int>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
.Verify(analysisService => analysisService.GetAnalysisAsync(bundleId, It.IsAny<FireScanCodeProgressUpdate>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
}

[Fact]
Expand Down
31 changes: 12 additions & 19 deletions Snyk.Code.Library/Service/AnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
/// <inheritdoc/>
public class AnalysisService : IAnalysisService
{
public const int RequestAttempts = 900;

private const int RequestTimeout = 1000;
private static readonly TimeSpan MaxScanDuration = TimeSpan.FromHours(3);
private static readonly TimeSpan WaitBetweenRequest = TimeSpan.FromSeconds(1);

private static readonly ILogger Logger = LogManager.ForContext<AnalysisService>();

Expand All @@ -27,10 +26,8 @@ public class AnalysisService : IAnalysisService
public AnalysisService(ISnykCodeClient codeClient) => this.codeClient = codeClient;

/// <inheritdoc/>
public async Task<AnalysisResult> GetAnalysisAsync(
string bundleHash,
public async Task<AnalysisResult> GetAnalysisAsync(string bundleHash,
FireScanCodeProgressUpdate scanCodeProgressUpdate,
int requestAttempts = RequestAttempts,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(bundleHash))
Expand All @@ -40,7 +37,7 @@ public async Task<AnalysisResult> GetAnalysisAsync(

cancellationToken.ThrowIfCancellationRequested();

var analysisResultDto = await this.TryGetAnalysisDtoAsync(bundleHash, scanCodeProgressUpdate, requestAttempts, cancellationToken);
var analysisResultDto = await this.TryGetAnalysisDtoAsync(bundleHash, scanCodeProgressUpdate, cancellationToken);

return this.MapDtoAnalysisResultToDomain(analysisResultDto);
}
Expand All @@ -49,18 +46,17 @@ public async Task<AnalysisResult> GetAnalysisAsync(
/// Try get analysis DTO 'RequestAttempts' attempts.
/// </summary>
/// <param name="bundleHash">Source bundle id.</param>
/// <param name="scanCodeProgressUpdate"></param>
/// <param name="cancellationToken"></param>
/// <returns><see cref="AnalysisResultDto"/> object.</returns>
private async Task<AnalysisResultDto> TryGetAnalysisDtoAsync(
string bundleHash,
private async Task<AnalysisResultDto> TryGetAnalysisDtoAsync(string bundleHash,
FireScanCodeProgressUpdate scanCodeProgressUpdate,
int requestAttempts,
CancellationToken cancellationToken = default)
{
Logger.Debug("Try get analysis DTO object {RequestAttempts} times.", requestAttempts);

cancellationToken.ThrowIfCancellationRequested();

for (int counter = 0; counter < requestAttempts; counter++)
var startTime = DateTime.Now;
while(DateTime.Now - startTime < MaxScanDuration)
{
cancellationToken.ThrowIfCancellationRequested();

Expand All @@ -83,8 +79,6 @@ private async Task<AnalysisResultDto> TryGetAnalysisDtoAsync(
};
}

Logger.Debug($"Request analysis status {analysisResultDto.Status}");

int progress = (int)analysisResultDto.Progress * 100;

scanCodeProgressUpdate(SnykCodeScanState.Analysing, progress);
Expand All @@ -97,18 +91,17 @@ private async Task<AnalysisResultDto> TryGetAnalysisDtoAsync(
return analysisResultDto;

case AnalysisStatus.Failed:
throw new SnykCodeException("SnykCode Analysis failed.");
throw new SnykCodeException("SnykCode Analysis failed with status code " + analysisResultDto.Status);

case AnalysisStatus.Waiting:
default:
Logger.Information("SnykCode service return {Status} status. Sleep for 1 second timeout.", analysisResultDto.Status);

Thread.Sleep(RequestTimeout);
await Task.Delay(WaitBetweenRequest, cancellationToken);
break;
}
}

Logger.Warning("Can't Get analysis after {requestAttempts} attepts. Return AnalysisResultDto with Failed status.", requestAttempts);
Logger.Warning("Snyk Code scan timed out on the client side.");

return new AnalysisResultDto { Status = AnalysisStatus.Failed, };
}
Expand Down
5 changes: 1 addition & 4 deletions Snyk.Code.Library/Service/IAnalysisService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ public interface IAnalysisService
/// </summary>
/// <param name="bundleId">Source bundle id to analysy.</param>
/// <param name="scanCodeProgressUpdate">Scan code progress update delegate.</param>
/// <param name="requestAttempts">Request attempts.</param>
/// <param name="cancellationToken"><see cref="CancellationToken"/> token to cancel request.</param>
/// <returns>Analysis results with suggestions and the relative positions.</returns>
Task<AnalysisResult> GetAnalysisAsync(
string bundleId,
Task<AnalysisResult> GetAnalysisAsync(string bundleId,
FireScanCodeProgressUpdate scanCodeProgressUpdate,
int requestAttempts = AnalysisService.RequestAttempts,
CancellationToken cancellationToken = default);
}
}

0 comments on commit 0c6ba0c

Please sign in to comment.