Skip to content
This repository was archived by the owner on Feb 1, 2023. It is now read-only.

Commit 4b0a661

Browse files
authored
Merge pull request #20 from snyk/feat/get_analysis_by_POST
feat: use POST for Get Analysis call (to request updated results only)
2 parents 6aa2abc + 1b74147 commit 4b0a661

File tree

6 files changed

+89
-114
lines changed

6 files changed

+89
-114
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66

77
group = "io.snyk.code.sdk"
88
archivesBaseName = "snyk-code-client"
9-
version = "2.1.7"
9+
version = "2.1.8"
1010

1111
repositories {
1212
mavenCentral()

src/integTest/java/ai/deepcode/javaclient/DeepCodeRestApiTest.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import org.junit.Test;
1010
import org.junit.runners.MethodSorters;
1111

12-
import java.io.*;
12+
import java.io.File;
13+
import java.io.FileOutputStream;
14+
import java.io.IOException;
1315
import java.nio.charset.StandardCharsets;
1416
import java.nio.file.Files;
1517
import java.nio.file.Paths;
@@ -406,14 +408,17 @@ public void _090_getAnalysis() {
406408
System.out.println("\n--------------Get Analysis----------------\n");
407409
assertNotNull(
408410
"`bundleId` should be initialized at `_030_createBundle_from_source()`", bundleId);
411+
final String deepcodedFilePath =
412+
createFileHashRequest(null).getFiles().keySet().stream().findFirst().orElseThrow();
413+
final List<String> analysedFiles = Collections.singletonList(deepcodedFilePath);
409414
assertAndPrintGetAnalysisResponse(
410-
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, null, false));
415+
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, null, false, analysedFiles));
411416
System.out.println("\n---- With `Linters` param:\n");
412417
assertAndPrintGetAnalysisResponse(
413-
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, null, true));
418+
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, null, true, analysedFiles));
414419
System.out.println("\n---- With `severity=2` param:\n");
415420
assertAndPrintGetAnalysisResponse(
416-
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, 2, false));
421+
DeepCodeRestApi.getAnalysis(loggedToken, bundleId, 2, false, analysedFiles));
417422
}
418423

419424
private void assertAndPrintGetAnalysisResponse(GetAnalysisResponse response) {

src/main/java/ai/deepcode/javaclient/DeepCodeRestApi.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ public static CreateBundleResponse checkBundle(
252252
return result;
253253
}
254254

255-
256255
private interface ExtendBundleCall {
257256
@retrofit2.http.Headers("Content-Type: application/json")
258257
@PUT("bundle/{bundleId}")
@@ -363,13 +362,14 @@ public static EmptyResponse UploadFiles(
363362
}
364363

365364
private interface GetAnalysisCall {
366-
// @retrofit2.http.Headers("Content-Type: application/json")
367-
@GET("analysis/{bundleId}")
365+
@retrofit2.http.Headers("Content-Type: application/json")
366+
@POST("analysis/{bundleId}")
368367
Call<GetAnalysisResponse> doGetAnalysis(
369368
@Header("Session-Token") String token,
370369
@Path(value = "bundleId", encoded = true) String bundleId,
371370
@Query("severity") Integer severity,
372-
@QueryName String linters);
371+
@QueryName String linters,
372+
@Body GetAnalysisRequest filesToAnalyse);
373373
}
374374

375375
/**
@@ -379,12 +379,21 @@ Call<GetAnalysisResponse> doGetAnalysis(
379379
*/
380380
@NotNull
381381
public static GetAnalysisResponse getAnalysis(
382-
String token, String bundleId, Integer severity, boolean useLinters) {
382+
String token,
383+
String bundleId,
384+
Integer severity,
385+
boolean useLinters,
386+
List<String> filesToAnalyse) {
383387
GetAnalysisCall getAnalysisCall = retrofit.create(GetAnalysisCall.class);
384388
try {
385389
Response<GetAnalysisResponse> retrofitResponse =
386390
getAnalysisCall
387-
.doGetAnalysis(token, bundleId, severity, (useLinters) ? "linters" : null)
391+
.doGetAnalysis(
392+
token,
393+
bundleId,
394+
severity,
395+
(useLinters) ? "linters" : null,
396+
new GetAnalysisRequest(filesToAnalyse))
388397
.execute();
389398
GetAnalysisResponse result = retrofitResponse.body();
390399
if (result == null) result = new GetAnalysisResponse();

src/main/java/ai/deepcode/javaclient/core/AnalysisDataBase.java

Lines changed: 40 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ public Set<Object> getAllCachedProject() {
9797
return mapProject2BundleId.keySet();
9898
}
9999

100+
private static final Map<Object, Set<Object>> mapProject2RemovedFiles = new ConcurrentHashMap<>();
101+
100102
public void removeFilesFromCache(@NotNull Collection<Object> files) {
101103
try {
102104
dcLogger.logInfo("Request to remove from cache " + files.size() + " files: " + files);
@@ -107,6 +109,9 @@ public void removeFilesFromCache(@NotNull Collection<Object> files) {
107109
for (Object file : files) {
108110
if (file != null && isFileInCache(file)) {
109111
mapFile2Suggestions.remove(file);
112+
mapProject2RemovedFiles
113+
.computeIfAbsent(pdUtils.getProject(file), p -> new HashSet<>())
114+
.add(file);
110115
hashContentUtils.removeFileHashContent(file);
111116
removeCounter++;
112117
}
@@ -132,6 +137,7 @@ public void removeProjectFromCaches(@NotNull Object project) {
132137
dcLogger.logInfo("Removed from cache: " + project);
133138
}
134139
removeFilesFromCache(cachedFilesOfProject(project));
140+
mapProject2RemovedFiles.remove(project);
135141
}
136142

137143
private Collection<Object> cachedFilesOfProject(@NotNull Object project) {
@@ -171,22 +177,20 @@ public void waitForUpdateAnalysisFinish(@NotNull Object project, @Nullable Objec
171177
}
172178
}
173179

174-
/*
175-
public static void updateCachedResultsForFile(@NotNull Object psiFile) {
176-
updateCachedResultsForFiles(Collections.singleton(psiFile), Collections.emptyList());
177-
}
178-
*/
179-
180180
public void updateCachedResultsForFiles(
181181
@NotNull Object project,
182-
@NotNull Collection<Object> psiFiles,
183-
@NotNull Collection<Object> filesToRemove,
182+
@NotNull Collection<Object> allProjectFiles,
184183
@NotNull Object progress) {
185-
if (psiFiles.isEmpty() && filesToRemove.isEmpty()) {
184+
Collection<Object> filesToRemove = mapProject2RemovedFiles.remove(project);
185+
if (filesToRemove == null) filesToRemove = Collections.emptyList();
186+
// remove from server only files physically removed from Project
187+
filesToRemove.removeAll(allProjectFiles);
188+
if (allProjectFiles.isEmpty() && filesToRemove.isEmpty()) {
186189
dcLogger.logWarn("updateCachedResultsForFiles requested for empty list of files");
187190
return;
188191
}
189-
dcLogger.logInfo("Update requested for " + psiFiles.size() + " files: " + psiFiles.toString());
192+
dcLogger.logInfo(
193+
"Update requested for " + allProjectFiles.size() + " files: " + allProjectFiles.toString());
190194
if (!deepCodeParams.consentGiven(project)) {
191195
dcLogger.logWarn("Consent check fail! Project: " + pdUtils.getProjectName(project));
192196
return;
@@ -196,7 +200,7 @@ public void updateCachedResultsForFiles(
196200
dcLogger.logInfo("MUTEX LOCK");
197201
setUpdateInProgress(project);
198202
Collection<Object> filesToProceed =
199-
psiFiles.stream()
203+
allProjectFiles.stream()
200204
.filter(Objects::nonNull)
201205
.filter(file -> !mapFile2Suggestions.containsKey(file))
202206
.collect(Collectors.toSet());
@@ -212,29 +216,19 @@ public void updateCachedResultsForFiles(
212216
+ " ["
213217
+ fileHash
214218
+ "]");
215-
if (filesToProceed.size() == 1 && filesToRemove.isEmpty()) {
216-
// if only one file updates then its most likely from annotator. So we need to get
217-
// suggestions asap:
218-
// we do that through createBundle with fileContent
219-
mapFile2Suggestions.put(firstFile, retrieveSuggestions(firstFile, progress));
220-
// and then request normal extendBundle later to synchronize results on server
221-
pdUtils.runInBackgroundCancellable(
222-
firstFile,
223-
"Synchronize analysis result with server...",
224-
(progress1) ->
225-
retrieveSuggestions(project, filesToProceed, filesToRemove, progress1));
226-
} else {
227-
mapFile2Suggestions.putAll(
228-
retrieveSuggestions(project, filesToProceed, filesToRemove, progress));
229-
}
230219
} else if (!filesToRemove.isEmpty()) {
220+
dcLogger.logWarn(
221+
"Nothing to update for "
222+
+ allProjectFiles.size()
223+
+ " files: "
224+
+ allProjectFiles.toString());
225+
}
226+
if (!filesToRemove.isEmpty()) {
231227
dcLogger.logInfo(
232228
"Files to remove: " + filesToRemove.size() + " files: " + filesToRemove.toString());
233-
retrieveSuggestions(project, filesToProceed, filesToRemove, progress);
234-
} else {
235-
dcLogger.logWarn(
236-
"Nothing to update for " + psiFiles.size() + " files: " + psiFiles.toString());
237229
}
230+
mapFile2Suggestions.putAll(
231+
retrieveSuggestions(project, filesToProceed, filesToRemove, progress));
238232
} finally {
239233
// if (filesToProceed != null && !filesToProceed.isEmpty())
240234
dcLogger.logInfo("MUTEX RELEASED");
@@ -286,15 +280,23 @@ private Map<Object, List<SuggestionForFile>> retrieveSuggestions(
286280

287281
List<String> missingFiles = createBundleStep(project, filesToProceed, filesToRemove, progress);
288282

283+
if (filesToProceed.isEmpty()) { // no sense to proceed
284+
return EMPTY_MAP;
285+
}
289286
uploadFilesStep(project, filesToProceed, missingFiles, progress);
290287

291288
// ---------------------------------------- Get Analysis
292289
final String bundleId = mapProject2BundleId.getOrDefault(project, "");
293-
if (bundleId.isEmpty()) return EMPTY_MAP; // no sense to proceed without bundleId
290+
if (bundleId.isEmpty()) { // no sense to proceed
291+
return EMPTY_MAP;
292+
}
294293
long startTime = System.currentTimeMillis();
295294
pdUtils.progressSetText(progress, WAITING_FOR_ANALYSIS_TEXT);
296295
pdUtils.progressCheckCanceled(progress);
297-
GetAnalysisResponse getAnalysisResponse = doGetAnalysis(project, bundleId, progress);
296+
List<String> filesToAnalyse =
297+
filesToProceed.stream().map(pdUtils::getDeepCodedFilePath).collect(Collectors.toList());
298+
GetAnalysisResponse getAnalysisResponse =
299+
doGetAnalysis(project, bundleId, progress, filesToAnalyse);
298300
Map<Object, List<SuggestionForFile>> result =
299301
parseGetAnalysisResponse(project, filesToProceed, getAnalysisResponse, progress);
300302
dcLogger.logInfo(
@@ -397,59 +399,6 @@ private void uploadFilesStep(
397399
"--- Upload Files took: " + (System.currentTimeMillis() - startTime) + " milliseconds");
398400
}
399401

400-
/** Perform costly network request. <b>No cache checks!</b> */
401-
@NotNull
402-
private List<SuggestionForFile> retrieveSuggestions(
403-
@NotNull Object file, @NotNull Object progress) {
404-
final Object project = pdUtils.getProject(file);
405-
List<SuggestionForFile> result;
406-
long startTime;
407-
// ---------------------------------------- Create Bundle
408-
startTime = System.currentTimeMillis();
409-
dcLogger.logInfo("Creating temporary Bundle from File content");
410-
pdUtils.progressCheckCanceled(progress);
411-
412-
FileContent fileContent =
413-
new FileContent(pdUtils.getDeepCodedFilePath(file), hashContentUtils.getFileContent(file));
414-
FileContentRequest fileContentRequest =
415-
new FileContentRequest(Collections.singletonList(fileContent));
416-
417-
// todo?? it might be cheaper on server side to extend one temporary bundle
418-
// rather then create the new one every time
419-
final CreateBundleResponse createBundleResponse =
420-
DeepCodeRestApi.createBundle(deepCodeParams.getSessionToken(), fileContentRequest);
421-
isNotSucceed(project, createBundleResponse, "Bad Create/Extend Bundle request: ");
422-
423-
final String bundleId = createBundleResponse.getBundleId();
424-
if (bundleId.isEmpty()) return Collections.emptyList(); // no sense to proceed without bundleId
425-
426-
List<String> missingFiles = createBundleResponse.getMissingFiles();
427-
dcLogger.logInfo(
428-
"--- Create temporary Bundle took: "
429-
+ (System.currentTimeMillis() - startTime)
430-
+ " milliseconds"
431-
+ "\nbundleId: "
432-
+ bundleId
433-
+ "\nmissingFiles: "
434-
+ missingFiles);
435-
if (!missingFiles.isEmpty()) dcLogger.logWarn("missingFiles is NOT empty!");
436-
437-
// ---------------------------------------- Get Analysis
438-
pdUtils.progressCheckCanceled(progress);
439-
startTime = System.currentTimeMillis();
440-
GetAnalysisResponse getAnalysisResponse = doGetAnalysis(project, bundleId, progress);
441-
result =
442-
parseGetAnalysisResponse(
443-
project, Collections.singleton(file), getAnalysisResponse, progress)
444-
.getOrDefault(file, Collections.emptyList());
445-
mapProject2analysisUrl.put(project, "");
446-
447-
dcLogger.logInfo(
448-
"--- Get Analysis took: " + (System.currentTimeMillis() - startTime) + " milliseconds");
449-
// progress.stop();
450-
return result;
451-
}
452-
453402
private void uploadFiles(
454403
@NotNull Object project,
455404
@NotNull Collection<Object> filesToProceed,
@@ -589,7 +538,10 @@ private void doUploadFiles(
589538

590539
@NotNull
591540
private GetAnalysisResponse doGetAnalysis(
592-
@NotNull Object project, @NotNull String bundleId, @NotNull Object progress) {
541+
@NotNull Object project,
542+
@NotNull String bundleId,
543+
@NotNull Object progress,
544+
List<String> filesToAnalyse) {
593545
GetAnalysisResponse response;
594546
int counter = 0;
595547
final int timeout = 100; // seconds
@@ -601,7 +553,8 @@ private GetAnalysisResponse doGetAnalysis(
601553
deepCodeParams.getSessionToken(),
602554
bundleId,
603555
deepCodeParams.getMinSeverity(),
604-
deepCodeParams.useLinter());
556+
deepCodeParams.useLinter(),
557+
filesToAnalyse);
605558

606559
pdUtils.progressCheckCanceled(progress);
607560
dcLogger.logInfo(response.toString());

src/main/java/ai/deepcode/javaclient/core/RunUtilsBase.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ && getRunningProgresses(project).remove(prevProgressIndicator)) {
284284

285285
// actual rescan
286286
if (invalidateCaches) analysisData.removeProjectFromCaches(project);
287-
updateCachedAnalysisResults(project, null, progress);
287+
updateCachedAnalysisResults(project, progress);
288288

289289
if (bulkModeRequests.remove(actualRequestId)) {
290290
bulkModeUnset(project);
@@ -310,25 +310,13 @@ public void asyncAnalyseProjectAndUpdatePanel(@Nullable Object project) {
310310
}
311311
}
312312

313-
public void updateCachedAnalysisResults(
314-
@NotNull Object project, @Nullable Collection<Object> files, @NotNull Object progress) {
315-
updateCachedAnalysisResults(project, files, Collections.emptyList(), progress);
316-
}
317-
318-
public void updateCachedAnalysisResults(
319-
@NotNull Object project,
320-
@Nullable Collection<Object> files,
321-
@NotNull Collection<Object> filesToRemove,
322-
@NotNull Object progress) {
313+
public void updateCachedAnalysisResults(@NotNull Object project, @NotNull Object progress) {
323314
try {
324315
analysisData.updateCachedResultsForFiles(
325-
project,
326-
(files != null) ? files : deepCodeUtils.getAllSupportedFilesInProject(project),
327-
filesToRemove,
328-
progress);
316+
project, deepCodeUtils.getAllSupportedFilesInProject(project), progress);
329317
} finally {
330318
updateAnalysisResultsUIPresentation(
331-
project, (files != null) ? files : analysisData.getAllFilesWithSuggestions(project));
319+
project, analysisData.getAllFilesWithSuggestions(project));
332320
}
333321
}
334322

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ai.deepcode.javaclient.requests;
2+
3+
import java.util.List;
4+
5+
public class GetAnalysisRequest {
6+
private List<String> files;
7+
8+
/**
9+
* @param files List of FilePaths
10+
*/
11+
public GetAnalysisRequest(List<String> files) {
12+
super();
13+
this.files = files;
14+
}
15+
16+
public List<String> getFiles() {
17+
return files;
18+
}
19+
20+
}

0 commit comments

Comments
 (0)