@@ -90,6 +90,7 @@ protected override void LoadComplete()
9090 clearOutdatedStarRatings ( ) ;
9191 populateMissingStarRatings ( ) ;
9292 processOnlineBeatmapSetsWithNoUpdate ( ) ;
93+
9394 // Note that the previous method will also update these on a fresh run.
9495 processBeatmapsWithMissingObjectCounts ( ) ;
9596 processScoresWithMissingStatistics ( ) ;
@@ -102,6 +103,7 @@ protected override void LoadComplete()
102103 if ( t . Exception ? . InnerException is ObjectDisposedException )
103104 {
104105 Logger . Log ( "Finished background aborted during shutdown" ) ;
106+
105107 return ;
106108 }
107109
@@ -234,7 +236,7 @@ void flushPendingUpdates()
234236 var beatmap = realmAccess . Run ( r => r . Find < BeatmapInfo > ( id ) ? . Detach ( ) ) ;
235237
236238 if ( beatmap == null )
237- return ;
239+ continue ;
238240
239241 try
240242 {
@@ -277,6 +279,7 @@ private void processOnlineBeatmapSetsWithNoUpdate()
277279 //
278280 // We may eventually consider making the Process call more specific (or avoid this in any number
279281 // of other possible ways), but for now avoid queueing if the user isn't logged in at startup.
282+
280283 if ( api . IsLoggedIn )
281284 {
282285 foreach ( var b in r . All < BeatmapInfo > ( ) . Where ( b => b . OnlineID > 0 && b . LastOnlineUpdate == null && b . BeatmapSet != null ) )
@@ -424,28 +427,40 @@ private void processScoresWithMissingStatistics()
424427 break ;
425428
426429 updateNotificationProgress ( notification , processedCount , scoreIds . Count ) ;
427-
428430 sleepIfRequired ( ) ;
429431
430432 var updates = new List < ( Guid id , string json ) > ( ) ;
431433 var failedIds = new List < Guid > ( ) ;
434+ int missingCount = 0 ;
432435
433- foreach ( var id in chunk )
436+ var detachedScores = realmAccess . Run ( r =>
434437 {
435- try
438+ var scores = new List < ScoreInfo > ( ) ;
439+
440+ foreach ( var id in chunk )
436441 {
437- var score = scoreManager . Query ( s => s . ID == id ) ;
442+ var s = r . Find < ScoreInfo > ( id ) ;
438443
439- if ( score != null )
440- {
441- scoreManager . PopulateMaximumStatistics ( score ) ;
442- updates . Add ( ( id , JsonConvert . SerializeObject ( score . MaximumStatistics ) ) ) ;
443- }
444+ if ( s != null )
445+ scores . Add ( s . Detach ( ) ) ;
446+ else
447+ missingCount ++ ;
448+ }
449+
450+ return scores ;
451+ } ) ;
452+
453+ foreach ( var score in detachedScores )
454+ {
455+ try
456+ {
457+ scoreManager . PopulateMaximumStatistics ( score ) ;
458+ updates . Add ( ( score . ID , JsonConvert . SerializeObject ( score . MaximumStatistics ) ) ) ;
444459 }
445460 catch ( Exception e )
446461 {
447- Logger . Log ( @$ "Failed to populate maximum statistics for { id } : { e } ") ;
448- failedIds . Add ( id ) ;
462+ Logger . Log ( @$ "Failed to populate maximum statistics for { score . ID } : { e } ") ;
463+ failedIds . Add ( score . ID ) ;
449464 }
450465 }
451466
@@ -460,13 +475,15 @@ private void processScoresWithMissingStatistics()
460475 foreach ( var update in updates )
461476 {
462477 var s = r . Find < ScoreInfo > ( update . id ) ;
478+
463479 if ( s != null )
464480 s . MaximumStatisticsJson = update . json ;
465481 }
466482
467483 foreach ( var id in failedIds )
468484 {
469485 var s = r . Find < ScoreInfo > ( id ) ;
486+
470487 if ( s != null )
471488 s . BackgroundReprocessingFailed = true ;
472489 }
@@ -482,8 +499,11 @@ private void processScoresWithMissingStatistics()
482499 catch ( Exception e )
483500 {
484501 Logger . Log ( $ "Fatal error writing batch in score statistics population: { e } ") ;
502+ failedCount += updates . Count + failedIds . Count ;
485503 }
486504 }
505+
506+ processedCount += missingCount ;
487507 }
488508
489509 completeNotification ( notification , processedCount , scoreIds . Count , failedCount ) ;
@@ -497,16 +517,17 @@ private void convertLegacyTotalScoreToStandardised()
497517 r . All < ScoreInfo > ( )
498518 . Filter ( $ "{ nameof ( ScoreInfo . BackgroundReprocessingFailed ) } == false && { nameof ( ScoreInfo . BeatmapInfo ) } != null && { nameof ( ScoreInfo . IsLegacyScore ) } == true && { nameof ( ScoreInfo . TotalScoreVersion ) } < $0", LegacyScoreEncoder . LATEST_VERSION )
499519 . AsEnumerable ( )
520+
500521 // must be done after materialisation, as realm doesn't want to support
501522 // nested property predicates
502523 . Where ( s => s . Ruleset . IsLegacyRuleset ( ) )
503524 . Select ( s => s . ID ) ) ) ;
504525
505- Logger . Log ( $ "Found { scoreIds . Count } scores which require total score conversion.") ;
506-
507526 if ( scoreIds . Count == 0 )
508527 return ;
509528
529+ Logger . Log ( $ "Found { scoreIds . Count } scores which require total score conversion.") ;
530+
510531 var notification = showProgressNotification ( scoreIds . Count , "Upgrading scores to new scoring algorithm" , "scores have been upgraded to the new scoring algorithm" ) ;
511532
512533 int processedCount = 0 ;
@@ -518,11 +539,11 @@ private void convertLegacyTotalScoreToStandardised()
518539 break ;
519540
520541 updateNotificationProgress ( notification , processedCount , scoreIds . Count ) ;
521-
522542 sleepIfRequired ( ) ;
523543
524544 var updates = new List < ( Guid id , long totalScore , long totalScoreWithoutMods , double accuracy , ScoreRank rank ) > ( ) ;
525545 var failedIds = new List < Guid > ( ) ;
546+ int missingCount = 0 ;
526547
527548 var detachedScores = realmAccess . Run ( r =>
528549 {
@@ -534,6 +555,8 @@ private void convertLegacyTotalScoreToStandardised()
534555
535556 if ( score != null )
536557 scores . Add ( score . Detach ( ) ) ;
558+ else
559+ missingCount ++ ;
537560 }
538561
539562 return scores ;
@@ -564,7 +587,9 @@ private void convertLegacyTotalScoreToStandardised()
564587 foreach ( var update in updates )
565588 {
566589 var s = r . Find < ScoreInfo > ( update . id ) ;
567- if ( s == null ) continue ;
590+
591+ if ( s == null )
592+ continue ;
568593
569594 s . TotalScore = update . totalScore ;
570595 s . TotalScoreWithoutMods = update . totalScoreWithoutMods ;
@@ -576,6 +601,7 @@ private void convertLegacyTotalScoreToStandardised()
576601 foreach ( var id in failedIds )
577602 {
578603 var s = r . Find < ScoreInfo > ( id ) ;
604+
579605 if ( s != null )
580606 s . BackgroundReprocessingFailed = true ;
581607 }
@@ -591,8 +617,11 @@ private void convertLegacyTotalScoreToStandardised()
591617 catch ( Exception e )
592618 {
593619 Logger . Log ( $ "Fatal error writing batch in score conversion: { e } ") ;
620+ failedCount += updates . Count + failedIds . Count ;
594621 }
595622 }
623+
624+ processedCount += missingCount ;
596625 }
597626
598627 completeNotification ( notification , processedCount , scoreIds . Count , failedCount ) ;
@@ -606,16 +635,17 @@ private void upgradeScoreRanks()
606635 r . All < ScoreInfo > ( )
607636 . Where ( s => s . TotalScoreVersion < 30000013 && ! s . BackgroundReprocessingFailed ) // last total score version with a significant change to ranks
608637 . AsEnumerable ( )
638+
609639 // must be done after materialisation, as realm doesn't support
610640 // filtering on nested property predicates or projection via `.Select()`
611641 . Where ( s => s . Ruleset . IsLegacyRuleset ( ) )
612642 . Select ( s => s . ID ) ) ) ;
613643
614- Logger . Log ( $ "Found { scoreIds . Count } scores which require rank upgrades.") ;
615-
616644 if ( scoreIds . Count == 0 )
617645 return ;
618646
647+ Logger . Log ( $ "Found { scoreIds . Count } scores which require rank upgrades.") ;
648+
619649 var notification = showProgressNotification ( scoreIds . Count , "Adjusting ranks of scores" , "scores now have more correct ranks." ) ;
620650
621651 int processedCount = 0 ;
@@ -627,11 +657,11 @@ private void upgradeScoreRanks()
627657 break ;
628658
629659 updateNotificationProgress ( notification , processedCount , scoreIds . Count ) ;
630-
631660 sleepIfRequired ( ) ;
632661
633662 var updates = new List < ( Guid id , ScoreRank rank ) > ( ) ;
634663 var failedIds = new List < Guid > ( ) ;
664+ int missingCount = 0 ;
635665
636666 var detachedScores = realmAccess . Run ( r =>
637667 {
@@ -643,6 +673,8 @@ private void upgradeScoreRanks()
643673
644674 if ( s != null )
645675 scores . Add ( s . Detach ( ) ) ;
676+ else
677+ missingCount ++ ;
646678 }
647679
648680 return scores ;
@@ -672,6 +704,7 @@ private void upgradeScoreRanks()
672704 foreach ( var update in updates )
673705 {
674706 var s = r . Find < ScoreInfo > ( update . id ) ;
707+
675708 if ( s != null )
676709 {
677710 s . Rank = update . rank ;
@@ -682,6 +715,7 @@ private void upgradeScoreRanks()
682715 foreach ( var id in failedIds )
683716 {
684717 var s = r . Find < ScoreInfo > ( id ) ;
718+
685719 if ( s != null )
686720 s . BackgroundReprocessingFailed = true ;
687721 }
@@ -697,20 +731,25 @@ private void upgradeScoreRanks()
697731 catch ( Exception e )
698732 {
699733 Logger . Log ( $ "Fatal error writing batch in score rank upgrade: { e } ") ;
734+ failedCount += updates . Count + failedIds . Count ;
700735 }
701736 }
737+
738+ processedCount += missingCount ;
702739 }
703740
704741 completeNotification ( notification , processedCount , scoreIds . Count , failedCount ) ;
705742 }
706743
707744 private void backpopulateMissingSubmissionAndRankDates ( )
708745 {
709- if ( DebugUtils . IsNUnitRunning ) return ;
746+ if ( DebugUtils . IsNUnitRunning )
747+ return ;
710748
711749 if ( ! localMetadataSource . Available )
712750 {
713751 Logger . Log ( "Cannot backpopulate missing submission/rank dates because the local metadata cache is missing." ) ;
752+
714753 return ;
715754 }
716755
@@ -719,12 +758,14 @@ private void backpopulateMissingSubmissionAndRankDates()
719758 if ( ! localMetadataSource . IsAtLeastVersion ( 2 ) )
720759 {
721760 Logger . Log ( "Cannot backpopulate missing submission/rank dates because the local metadata cache is too old." ) ;
761+
722762 return ;
723763 }
724764 }
725765 catch ( Exception ex )
726766 {
727767 Logger . Log ( $ "Error when trying to query version of local metadata cache: { ex } ") ;
768+
728769 return ;
729770 }
730771
@@ -778,10 +819,12 @@ private void backpopulateMissingSubmissionAndRankDates()
778819 Debug . Assert ( result != null ) ;
779820 beatmapSet . DateRanked = result . DateRanked ;
780821 beatmapSet . DateSubmitted = result . DateSubmitted ;
822+
781823 return true ;
782824 }
783825
784826 Logger . Log ( $ "Could not find { beatmapSet . GetDisplayString ( ) } in local cache while backpopulating missing submission/rank date") ;
827+
785828 return false ;
786829 } ) ;
787830
@@ -813,19 +856,22 @@ protected virtual void BackpopulateUserTags()
813856
814857 if ( ! localMetadataSource . Available || ! localMetadataSource . IsAtLeastVersion ( 3 ) )
815858 {
816- if ( DebugUtils . IsNUnitRunning ) return ;
859+ if ( DebugUtils . IsNUnitRunning )
860+ return ;
817861
818862 Logger . Log ( @"Local metadata cache has too low version to backpopulate user tags, attempting refetch..." ) ;
819863 localMetadataSource . FetchCache ( ) . WaitSafely ( ) ;
820864
821865 if ( ! localMetadataSource . Available || ! localMetadataSource . IsAtLeastVersion ( 3 ) )
822866 {
823867 Logger . Log ( @"Local metadata cache refetch failed. Aborting user tags backpopulation." ) ;
868+
824869 return ;
825870 }
826871 }
827872
828873 var lastPopulation = config . Get < DateTime ? > ( OsuSetting . LastOnlineTagsPopulation ) ;
874+
829875 // dropping time data here completely is intentional, because storing the date to config is a lossy operation
830876 // (truncates some ticks off of the date when it's being converted to string and back).
831877 // therefore, if precision isn't explicitly constrained, the condition below would always fail just because the date stored to config
@@ -835,6 +881,7 @@ protected virtual void BackpopulateUserTags()
835881 if ( metadataSourceFetchDate <= lastPopulation )
836882 {
837883 Logger . Log ( $@ "Skipping user tag population because the local metadata source hasn't been updated since the last time user tags were checked ({ lastPopulation . Value : d} )") ;
884+
838885 return ;
839886 }
840887
@@ -888,13 +935,15 @@ protected virtual void BackpopulateUserTags()
888935 {
889936 beatmap . Metadata . UserTags . Clear ( ) ;
890937 beatmap . Metadata . UserTags . AddRange ( userTags ) ;
938+
891939 return true ;
892940 }
893941
894942 return false ;
895943 }
896944
897945 Logger . Log ( @$ "Could not find { beatmap . GetDisplayString ( ) } in local cache while backpopulating missing user tags") ;
946+
898947 return false ;
899948 } ) ;
900949
0 commit comments