@@ -131,7 +131,7 @@ public void removeFilesFromCache(@NotNull Collection<Object> files) {
131
131
"Request to remove from cache " + files .size () + " files: " + first50FilesName );
132
132
// todo: do we really need mutex here?
133
133
MUTEX .lock ();
134
- dcLogger .logInfo ("MUTEX LOCK" );
134
+ dcLogger .logInfo ("MUTEX LOCK, hold count = " + MUTEX . getHoldCount () );
135
135
int removeCounter = 0 ;
136
136
for (Object file : files ) {
137
137
if (file != null && isFileInCache (file )) {
@@ -149,8 +149,8 @@ public void removeFilesFromCache(@NotNull Collection<Object> files) {
149
149
+ " files. Were not in cache: "
150
150
+ (files .size () - removeCounter ));
151
151
} finally {
152
- dcLogger .logInfo ("MUTEX RELEASED" );
153
152
MUTEX .unlock ();
153
+ dcLogger .logInfo ("MUTEX RELEASED, hold count = " + MUTEX .getHoldCount ());
154
154
}
155
155
updateUIonFilesRemovalFromCache (files );
156
156
}
@@ -229,7 +229,7 @@ public void updateCachedResultsForFiles(
229
229
}
230
230
try {
231
231
MUTEX .lock ();
232
- dcLogger .logInfo ("MUTEX LOCK" );
232
+ dcLogger .logInfo ("MUTEX LOCK, hold count = " + MUTEX . getHoldCount () );
233
233
setUpdateInProgress (project );
234
234
Collection <Object > filesToProceed =
235
235
allProjectFiles .stream ()
@@ -256,39 +256,71 @@ public void updateCachedResultsForFiles(
256
256
dcLogger .logInfo ("Files to remove: " + filesToRemove .size () + " files: " + filesToRemove );
257
257
}
258
258
mapFile2Suggestions .putAll (
259
- retrieveSuggestions (project , filesToProceed , filesToRemove , progress ));
259
+ retrieveSuggestions (project , filesToProceed , filesToRemove , progress )
260
+ );
261
+ } catch (BundleIdExpire404Exception e ) {
262
+ // re-try to create bundle from scratch
263
+ retryFullUpdateCachedResults (project , allProjectFiles , progress , 2 );
260
264
} finally {
261
- // if (filesToProceed != null && !filesToProceed.isEmpty())
262
- dcLogger .logInfo ("MUTEX RELEASED" );
263
265
MUTEX .unlock ();
266
+ dcLogger .logInfo ("MUTEX RELEASED, hold count = " + MUTEX .getHoldCount ());
264
267
unsetUpdateInProgress (project );
265
268
pdUtils .refreshPanel (project );
266
- // ServiceManager.getService(project, myTodoView.class).refresh();
267
269
}
268
270
}
269
271
272
+ private void retryFullUpdateCachedResults (
273
+ @ NotNull Object project ,
274
+ @ NotNull Collection <Object > allProjectFiles ,
275
+ @ NotNull Object progress ,
276
+ int attemptCounter
277
+ ) {
278
+ if (attemptCounter <= 0 ) {
279
+ showWarnIfNeeded (project , "Operations with bundle failed. Please try again later or contact Snyk support" );
280
+ return ;
281
+ }
282
+ removeProjectFromCaches (project );
283
+ try {
284
+ mapFile2Suggestions .putAll (
285
+ retrieveSuggestions (project , allProjectFiles , Collections .emptyList (), progress )
286
+ );
287
+ } catch (BundleIdExpire404Exception ex ) {
288
+ retryFullUpdateCachedResults (project , allProjectFiles , progress , attemptCounter - 1 );
289
+ }
290
+ }
291
+
292
+ private static class TokenInvalid401Exception extends Exception {}
293
+
294
+ private static class BundleIdExpire404Exception extends Exception {}
295
+
296
+ private static class ApiCallNotSucceedException extends Exception {}
297
+
270
298
private static final Set <Object > projectsLoginRequested = ConcurrentHashMap .newKeySet ();
271
299
private static final Set <Object > projectsWithNotSucceedWarnShown = ConcurrentHashMap .newKeySet ();
272
300
273
- private boolean isNotSucceed (
274
- @ NotNull Object project , EmptyResponse response , String internalMessage ) {
301
+ private void showWarnIfNeeded (@ NotNull Object project , @ NotNull String message ) {
302
+ pdUtils .showWarn (message , project , !projectsWithNotSucceedWarnShown .add (project ));
303
+ }
304
+
305
+ private void checkApiCallSucceed (
306
+ @ NotNull Object project , EmptyResponse response , String internalMessage
307
+ ) throws ApiCallNotSucceedException , TokenInvalid401Exception , BundleIdExpire404Exception {
275
308
if (response .getStatusCode () == 200 ) {
276
309
projectsWithNotSucceedWarnShown .remove (project );
277
310
projectsLoginRequested .remove (project );
278
311
} else {
279
312
final String fullLogMessage =
280
313
internalMessage + response .getStatusCode () + " " + response .getStatusDescription ();
281
314
dcLogger .logWarn (fullLogMessage );
282
- final boolean wasWarnShown = projectsWithNotSucceedWarnShown .contains (project );
283
315
if (response .getStatusCode () == 401 ) {
284
- pdUtils .isLogged (project , !projectsLoginRequested .contains (project ));
285
- projectsLoginRequested .add (project );
316
+ pdUtils .isLogged (project , !projectsLoginRequested .add (project ));
317
+ throw new TokenInvalid401Exception ();
318
+ } else if (response .getStatusCode () == 404 ) {
319
+ throw new BundleIdExpire404Exception ();
286
320
} else {
287
- pdUtils . showWarn ( response . getStatusDescription (), project , wasWarnShown );
321
+ throw new ApiCallNotSucceedException ( );
288
322
}
289
- projectsWithNotSucceedWarnShown .add (project );
290
323
}
291
- return response .getStatusCode () != 200 ;
292
324
}
293
325
294
326
static final int MAX_BUNDLE_SIZE = 4000000 ; // bytes
@@ -299,22 +331,31 @@ private Map<Object, List<SuggestionForFile>> retrieveSuggestions(
299
331
@ NotNull Object project ,
300
332
@ NotNull Collection <Object > filesToProceed ,
301
333
@ NotNull Collection <Object > filesToRemove ,
302
- @ NotNull Object progress ) {
334
+ @ NotNull Object progress
335
+ ) throws BundleIdExpire404Exception {
303
336
if (filesToProceed .isEmpty () && filesToRemove .isEmpty ()) {
304
337
dcLogger .logWarn ("Both filesToProceed and filesToRemove are empty" );
305
338
return EMPTY_MAP ;
306
339
}
307
340
// no needs to check login here as it will be checked anyway during every api response's check
308
341
// if (!LoginUtils.isLogged(project, false)) return EMPTY_MAP;
309
342
310
- List <String > missingFiles = createBundleStep (project , filesToProceed , filesToRemove , progress );
343
+ List <String > missingFiles = null ;
344
+ try {
345
+ missingFiles = createBundleStep (project , filesToProceed , filesToRemove , progress );
346
+ } catch (ApiCallNotSucceedException e ) {
347
+ // re-try createBundleStep from scratch for few times, i.e. do the same as if parent bundle is expired
348
+ mapProject2BundleId .put (project , "" );
349
+ throw new BundleIdExpire404Exception ();
350
+ } catch (TokenInvalid401Exception e ) {
351
+ return EMPTY_MAP ;
352
+ }
311
353
312
354
if (filesToProceed .isEmpty ()) { // no sense to proceed
313
355
return EMPTY_MAP ;
314
356
}
315
357
boolean filesUploaded = uploadFilesStep (project , filesToProceed , missingFiles , progress );
316
358
if (!filesUploaded ) { // no sense to proceed
317
- dcLogger .logWarn ("Files upload FAIL" );
318
359
return EMPTY_MAP ;
319
360
}
320
361
@@ -328,8 +369,12 @@ private Map<Object, List<SuggestionForFile>> retrieveSuggestions(
328
369
pdUtils .progressCheckCanceled (progress );
329
370
List <String > filesToAnalyse =
330
371
filesToProceed .stream ().map (pdUtils ::getDeepCodedFilePath ).collect (Collectors .toList ());
331
- GetAnalysisResponse getAnalysisResponse =
332
- doGetAnalysis (project , bundleId , progress , filesToAnalyse );
372
+ GetAnalysisResponse getAnalysisResponse ;
373
+ try {
374
+ getAnalysisResponse = doGetAnalysis (project , bundleId , progress , filesToAnalyse );
375
+ } catch (TokenInvalid401Exception e ) {
376
+ return EMPTY_MAP ;
377
+ }
333
378
Map <Object , List <SuggestionForFile >> result =
334
379
parseGetAnalysisResponse (project , filesToProceed , getAnalysisResponse , progress );
335
380
dcLogger .logInfo (
@@ -346,7 +391,8 @@ private List<String> createBundleStep(
346
391
@ NotNull Object project ,
347
392
@ NotNull Collection <Object > filesToProceed ,
348
393
@ NotNull Collection <Object > filesToRemove ,
349
- @ NotNull Object progress ) {
394
+ @ NotNull Object progress
395
+ ) throws BundleIdExpire404Exception , ApiCallNotSucceedException , TokenInvalid401Exception {
350
396
long startTime = System .currentTimeMillis ();
351
397
pdUtils .progressSetText (progress , PREPARE_FILES_TEXT );
352
398
dcLogger .logInfo (PREPARE_FILES_TEXT );
@@ -401,7 +447,8 @@ private boolean uploadFilesStep(
401
447
@ NotNull Object project ,
402
448
@ NotNull Collection <Object > filesToProceed ,
403
449
@ NotNull List <String > missingFiles ,
404
- @ NotNull Object progress ) {
450
+ @ NotNull Object progress
451
+ ) throws BundleIdExpire404Exception {
405
452
long startTime = System .currentTimeMillis ();
406
453
pdUtils .progressSetText (progress , UPLOADING_FILES_TEXT );
407
454
pdUtils .progressCheckCanceled (progress );
@@ -424,11 +471,21 @@ private boolean uploadFilesStep(
424
471
+ " more times:\n missingFiles = "
425
472
+ missingFiles );
426
473
}
427
- uploadFiles (project , filesToProceed , missingFiles , bundleId , progress );
428
- List <String > newMissingFiles = checkBundle (project , bundleId );
429
- missingFiles = (newMissingFiles != null ) ? newMissingFiles : missingFiles ;
474
+ List <String > newMissingFiles ;
475
+ try {
476
+ uploadFiles (project , filesToProceed , missingFiles , bundleId , progress );
477
+ newMissingFiles = checkBundle (project , bundleId );
478
+ } catch (TokenInvalid401Exception e ) {
479
+ break ;
480
+ } catch (ApiCallNotSucceedException e ) {
481
+ newMissingFiles = missingFiles ;
482
+ }
483
+ missingFiles = newMissingFiles ;
430
484
counter ++;
431
485
}
486
+ if (counter >= attempts ) {
487
+ showWarnIfNeeded (project , "Failed to upload files. Please try again later or contact Snyk support" );
488
+ }
432
489
}
433
490
dcLogger .logInfo (
434
491
"--- Upload Files took: " + (System .currentTimeMillis () - startTime ) + " milliseconds" );
@@ -440,7 +497,8 @@ private void uploadFiles(
440
497
@ NotNull Collection <Object > filesToProceed ,
441
498
@ NotNull List <String > missingFiles ,
442
499
@ NotNull String bundleId ,
443
- @ NotNull Object progress ) {
500
+ @ NotNull Object progress
501
+ ) throws ApiCallNotSucceedException , TokenInvalid401Exception , BundleIdExpire404Exception {
444
502
Map <String , Object > mapPath2File =
445
503
filesToProceed .stream ().collect (Collectors .toMap (pdUtils ::getDeepCodedFilePath , it -> it ));
446
504
int fileCounter = 0 ;
@@ -487,20 +545,21 @@ private void uploadFiles(
487
545
*
488
546
* @return list of the current missingFiles or NULL if not succeed.
489
547
*/
490
- @ Nullable
491
- private List <String > checkBundle (@ NotNull Object project , @ NotNull String bundleId ) {
548
+ private List <String > checkBundle (
549
+ @ NotNull Object project ,
550
+ @ NotNull String bundleId
551
+ ) throws TokenInvalid401Exception , BundleIdExpire404Exception , ApiCallNotSucceedException {
492
552
CreateBundleResponse checkBundleResponse =
493
553
restApi .checkBundle (deepCodeParams .getSessionToken (), bundleId );
494
- if (isNotSucceed (project , checkBundleResponse , "Bad CheckBundle request: " )) {
495
- return null ;
496
- }
554
+ checkApiCallSucceed (project , checkBundleResponse , "Bad CheckBundle request: " );
497
555
return checkBundleResponse .getMissingFiles ();
498
556
}
499
557
500
558
private CreateBundleResponse makeNewBundle (
501
559
@ NotNull Object project ,
502
560
@ NotNull FileHashRequest request ,
503
- @ NotNull Collection <Object > filesToRemove ) {
561
+ @ NotNull Collection <Object > filesToRemove
562
+ ) throws BundleIdExpire404Exception , ApiCallNotSucceedException , TokenInvalid401Exception {
504
563
final String parentBundleId = mapProject2BundleId .getOrDefault (project , "" );
505
564
if (!parentBundleId .isEmpty ()
506
565
&& !filesToRemove .isEmpty ()
@@ -540,19 +599,17 @@ private CreateBundleResponse makeNewBundle(
540
599
"/DEEPCODE_PRIVATE_BUNDLE/0000000000000000000000000000000000000000000000000000000000000000" )) {
541
600
newBundleId = "" ;
542
601
}
602
+ checkApiCallSucceed (project , bundleResponse , "Bad Create/Extend Bundle request: " );
543
603
mapProject2BundleId .put (project , newBundleId );
544
- isNotSucceed (project , bundleResponse , "Bad Create/Extend Bundle request: " );
545
- // just make new bundle in case of 404 Parent bundle has expired
546
- return (bundleResponse .getStatusCode () == 404 )
547
- ? makeNewBundle (project , request , filesToRemove )
548
- : bundleResponse ;
604
+ return bundleResponse ;
549
605
}
550
606
551
607
private void doUploadFiles (
552
608
@ NotNull Object project ,
553
609
@ NotNull Collection <Object > psiFiles ,
554
610
@ NotNull String bundleId ,
555
- @ NotNull Object progress ) {
611
+ @ NotNull Object progress
612
+ ) throws ApiCallNotSucceedException , TokenInvalid401Exception , BundleIdExpire404Exception {
556
613
dcLogger .logInfo ("Uploading " + psiFiles .size () + " files... " );
557
614
if (psiFiles .isEmpty ()) return ;
558
615
@@ -571,18 +628,19 @@ private void doUploadFiles(
571
628
deepCodeParams .getSessionToken (),
572
629
bundleId ,
573
630
new ExtendBundleWithContentRequest (files , Collections .emptyList ()));
574
- isNotSucceed (project , uploadFilesResponse , "Bad UploadFiles request: " );
631
+ checkApiCallSucceed (project , uploadFilesResponse , "Bad UploadFiles request: " );
575
632
}
576
633
577
634
@ NotNull
578
635
private GetAnalysisResponse doGetAnalysis (
579
636
@ NotNull Object project ,
580
637
@ NotNull String bundleId ,
581
638
@ NotNull Object progress ,
582
- List <String > filesToAnalyse ) {
639
+ List <String > filesToAnalyse
640
+ ) throws TokenInvalid401Exception {
583
641
GetAnalysisResponse response ;
584
642
int counter = 0 ;
585
- int failWith404counts = 0 ;
643
+ int skippedFailsCount = 0 ;
586
644
final long timeout = deepCodeParams .getTimeoutForGettingAnalysesMs ();
587
645
final long attempts = timeout / PlatformDependentUtilsBase .DEFAULT_DELAY ;
588
646
final long endTime = System .currentTimeMillis () + timeout ;
@@ -600,16 +658,18 @@ private GetAnalysisResponse doGetAnalysis(
600
658
601
659
pdUtils .progressCheckCanceled (progress );
602
660
dcLogger .logInfo (response .toString ());
603
- if (isNotSucceed (project , response , "Bad GetAnalysis request: " )) {
604
- if (response .getStatusCode () != 404 || failWith404counts >= 5 ) {
661
+
662
+ try {
663
+ checkApiCallSucceed (project , response , "Bad GetAnalysis request: " );
664
+ skippedFailsCount = 0 ;
665
+ } catch (BundleIdExpire404Exception | ApiCallNotSucceedException e ) {
666
+ if (skippedFailsCount >= 5 ) {
667
+ showWarnIfNeeded (project , "Failed to get analysis results. Please try again later or contact Snyk support" );
605
668
return new GetAnalysisResponse ();
606
669
} else {
607
- failWith404counts ++;
670
+ skippedFailsCount ++;
608
671
}
609
- } else {
610
- failWith404counts = 0 ;
611
672
}
612
-
613
673
double responseProgress = response .getProgress ();
614
674
if (responseProgress <= 0 || responseProgress > 1 ) {
615
675
responseProgress = ((double ) counter ) / attempts ;
@@ -620,13 +680,13 @@ private GetAnalysisResponse doGetAnalysis(
620
680
621
681
if (System .currentTimeMillis () >= endTime ) {
622
682
dcLogger .logWarn ("Timeout expire for waiting analysis results." );
623
- pdUtils . showWarn (
624
- "Can't get analysis results from the server. Timeout of "
625
- + timeout / 1000
626
- + " sec. is reached."
627
- + " Please, increase timeout or try again later." ,
628
- project ,
629
- false );
683
+ showWarnIfNeeded (
684
+ project ,
685
+ "Can't get analysis results from the server. Timeout of "
686
+ + timeout / 1000
687
+ + " sec. is reached."
688
+ + " Please, increase timeout or try again later."
689
+ );
630
690
break ;
631
691
}
632
692
0 commit comments