@@ -418,7 +418,7 @@ private void processScoresWithMissingStatistics()
418418 int processedCount = 0 ;
419419 int failedCount = 0 ;
420420
421- foreach ( var id in scoreIds )
421+ foreach ( var chunk in scoreIds . Chunk ( 100 ) )
422422 {
423423 if ( notification ? . State == ProgressNotificationState . Cancelled )
424424 break ;
@@ -427,33 +427,62 @@ private void processScoresWithMissingStatistics()
427427
428428 sleepIfRequired ( ) ;
429429
430- try
430+ var updates = new List < ( Guid id , string json ) > ( ) ;
431+ var failedIds = new List < Guid > ( ) ;
432+
433+ foreach ( var id in chunk )
431434 {
432- var score = scoreManager . Query ( s => s . ID == id ) ;
435+ try
436+ {
437+ var score = scoreManager . Query ( s => s . ID == id ) ;
433438
434- if ( score != null )
439+ if ( score != null )
440+ {
441+ scoreManager . PopulateMaximumStatistics ( score ) ;
442+ updates . Add ( ( id , JsonConvert . SerializeObject ( score . MaximumStatistics ) ) ) ;
443+ }
444+ }
445+ catch ( Exception e )
435446 {
436- scoreManager . PopulateMaximumStatistics ( score ) ;
447+ Logger . Log ( @$ "Failed to populate maximum statistics for { id } : { e } ") ;
448+ failedIds . Add ( id ) ;
449+ }
450+ }
437451
452+ if ( updates . Count > 0 || failedIds . Count > 0 )
453+ {
454+ try
455+ {
438456 // Can't use async overload because we're not on the update thread.
439457 // ReSharper disable once MethodHasAsyncOverload
440458 realmAccess . Write ( r =>
441459 {
442- r . Find < ScoreInfo > ( id ) ! . MaximumStatisticsJson = JsonConvert . SerializeObject ( score . MaximumStatistics ) ;
460+ foreach ( var update in updates )
461+ {
462+ var s = r . Find < ScoreInfo > ( update . id ) ;
463+ if ( s != null )
464+ s . MaximumStatisticsJson = update . json ;
465+ }
466+
467+ foreach ( var id in failedIds )
468+ {
469+ var s = r . Find < ScoreInfo > ( id ) ;
470+ if ( s != null )
471+ s . BackgroundReprocessingFailed = true ;
472+ }
443473 } ) ;
444- }
445474
446- ++ processedCount ;
447- }
448- catch ( ObjectDisposedException )
449- {
450- throw ;
451- }
452- catch ( Exception e )
453- {
454- Logger . Log ( @$ "Failed to populate maximum statistics for { id } : { e } " ) ;
455- realmAccess . Write ( r => r . Find < ScoreInfo > ( id ) ! . BackgroundReprocessingFailed = true ) ;
456- ++ failedCount ;
475+ processedCount += updates . Count ;
476+ failedCount += failedIds . Count ;
477+ }
478+ catch ( ObjectDisposedException )
479+ {
480+ throw ;
481+ }
482+ catch ( Exception e )
483+ {
484+ Logger . Log ( $ "Fatal error writing batch in score statistics population: { e } " ) ;
485+ }
457486 }
458487 }
459488
@@ -592,7 +621,7 @@ private void upgradeScoreRanks()
592621 int processedCount = 0 ;
593622 int failedCount = 0 ;
594623
595- foreach ( var id in scoreIds )
624+ foreach ( var chunk in scoreIds . Chunk ( 100 ) )
596625 {
597626 if ( notification ? . State == ProgressNotificationState . Cancelled )
598627 break ;
@@ -601,28 +630,74 @@ private void upgradeScoreRanks()
601630
602631 sleepIfRequired ( ) ;
603632
604- try
633+ var updates = new List < ( Guid id , ScoreRank rank ) > ( ) ;
634+ var failedIds = new List < Guid > ( ) ;
635+
636+ var detachedScores = realmAccess . Run ( r =>
605637 {
606- // Can't use async overload because we're not on the update thread.
607- // ReSharper disable once MethodHasAsyncOverload
608- realmAccess . Write ( r =>
638+ var scores = new List < ScoreInfo > ( ) ;
639+
640+ foreach ( var id in chunk )
609641 {
610- ScoreInfo s = r . Find < ScoreInfo > ( id ) ! ;
611- s . Rank = StandardisedScoreMigrationTools . ComputeRank ( s ) ;
612- s . TotalScoreVersion = LegacyScoreEncoder . LATEST_VERSION ;
613- } ) ;
642+ var s = r . Find < ScoreInfo > ( id ) ;
614643
615- ++ processedCount ;
616- }
617- catch ( ObjectDisposedException )
644+ if ( s != null )
645+ scores . Add ( s . Detach ( ) ) ;
646+ }
647+
648+ return scores ;
649+ } ) ;
650+
651+ foreach ( var detachedScore in detachedScores )
618652 {
619- throw ;
653+ try
654+ {
655+ updates . Add ( ( detachedScore . ID , StandardisedScoreMigrationTools . ComputeRank ( detachedScore ) ) ) ;
656+ }
657+ catch ( Exception e )
658+ {
659+ Logger . Log ( $ "Failed to update rank score { detachedScore . ID } : { e } ") ;
660+ failedIds . Add ( detachedScore . ID ) ;
661+ }
620662 }
621- catch ( Exception e )
663+
664+ if ( updates . Count > 0 || failedIds . Count > 0 )
622665 {
623- Logger . Log ( $ "Failed to update rank score { id } : { e } ") ;
624- realmAccess . Write ( r => r . Find < ScoreInfo > ( id ) ! . BackgroundReprocessingFailed = true ) ;
625- ++ failedCount ;
666+ try
667+ {
668+ // Can't use async overload because we're not on the update thread.
669+ // ReSharper disable once MethodHasAsyncOverload
670+ realmAccess . Write ( r =>
671+ {
672+ foreach ( var update in updates )
673+ {
674+ var s = r . Find < ScoreInfo > ( update . id ) ;
675+ if ( s != null )
676+ {
677+ s . Rank = update . rank ;
678+ s . TotalScoreVersion = LegacyScoreEncoder . LATEST_VERSION ;
679+ }
680+ }
681+
682+ foreach ( var id in failedIds )
683+ {
684+ var s = r . Find < ScoreInfo > ( id ) ;
685+ if ( s != null )
686+ s . BackgroundReprocessingFailed = true ;
687+ }
688+ } ) ;
689+
690+ processedCount += updates . Count ;
691+ failedCount += failedIds . Count ;
692+ }
693+ catch ( ObjectDisposedException )
694+ {
695+ throw ;
696+ }
697+ catch ( Exception e )
698+ {
699+ Logger . Log ( $ "Fatal error writing batch in score rank upgrade: { e } ") ;
700+ }
626701 }
627702 }
628703
0 commit comments