@@ -130,6 +130,11 @@ public sealed class StoreWrapper
130130 /// </summary>
131131 internal readonly LuaTimeoutManager luaTimeoutManager ;
132132
133+ /// <summary>
134+ /// Background task manager instance
135+ /// </summary>
136+ internal readonly TaskManager taskManager ;
137+
133138 private IDatabaseManager databaseManager ;
134139 SingleWriterMultiReaderLock databaseManagerLock ;
135140
@@ -151,7 +156,9 @@ public sealed class StoreWrapper
151156
152157 internal readonly CancellationTokenSource ctsCommit ;
153158
154- // True if StoreWrapper instance is disposed
159+ /// <summary>
160+ /// True if StoreWrapper instance is disposed
161+ /// </summary>
155162 bool disposed ;
156163
157164 /// <summary>
@@ -197,6 +204,7 @@ public StoreWrapper(
197204 this . sessionLogger = loggerFactory ? . CreateLogger ( "Session" ) ;
198205 this . accessControlList = accessControlList ;
199206 this . GarnetObjectSerializer = new GarnetObjectSerializer ( this . customCommandManager ) ;
207+ this . taskManager = new TaskManager ( loggerFactory ? . CreateLogger ( "TaskManager" ) ) ;
200208 this . loggingFrequency = TimeSpan . FromSeconds ( serverOptions . LoggingFrequency ) ;
201209
202210 logger ? . LogTrace ( "StoreWrapper logging frequency: {loggingFrequency} seconds." , this . loggingFrequency ) ;
@@ -654,7 +662,7 @@ async Task AutoCheckpointBasedOnAofSizeLimit(long aofSizeLimit, CancellationToke
654662 }
655663 }
656664
657- async Task CommitTask ( int commitFrequencyMs , ILogger logger = null , CancellationToken token = default )
665+ async Task CommitTask ( int commitFrequencyMs , CancellationToken token = default , ILogger logger = null )
658666 {
659667 try
660668 {
@@ -768,9 +776,12 @@ async Task ExpiredKeyDeletionScanTask(int expiredKeyDeletionScanFrequencySecs, C
768776 public ( long numExpiredKeysFound , long totalRecordsScanned ) ExpiredKeyDeletionScan ( int dbId )
769777 => databaseManager . ExpiredKeyDeletionScan ( dbId ) ;
770778
771- /// <summary>Grows indexes of both main store and object store if current size is too small.</summary>
779+ /// <summary>
780+ /// Grows indexes of both main store and object store if current size is too small.
781+ /// </summary>
772782 /// <param name="token"></param>
773- private async void IndexAutoGrowTask ( CancellationToken token )
783+ /// <returns></returns>
784+ private async Task IndexAutoGrowTask ( CancellationToken token )
774785 {
775786 try
776787 {
@@ -799,37 +810,16 @@ internal void Start()
799810 clusterProvider ? . Start ( ) ;
800811 luaTimeoutManager ? . Start ( ) ;
801812
802- if ( serverOptions . AofSizeLimit . Length > 0 )
803- {
804- var aofSizeLimitBytes = 1L << serverOptions . AofSizeLimitSizeBits ( ) ;
805- Task . Run ( async ( ) => await AutoCheckpointBasedOnAofSizeLimit ( aofSizeLimitBytes , ctsCommit . Token , logger ) ) ;
806- }
807-
808- if ( serverOptions . CommitFrequencyMs > 0 && serverOptions . EnableAOF )
813+ // Start background maintenance tasks that should run only on the primary
814+ if ( clusterProvider == null || clusterProvider . IsPrimary ( ) )
809815 {
810- Task . Run ( async ( ) => await CommitTask ( serverOptions . CommitFrequencyMs , logger , ctsCommit . Token ) ) ;
816+ StartPrimaryTasks ( ) ;
811817 }
812818
813- if ( serverOptions . CompactionFrequencySecs > 0 && serverOptions . CompactionType != LogCompactionType . None )
814- {
815- Task . Run ( async ( ) => await CompactionTask ( serverOptions . CompactionFrequencySecs , ctsCommit . Token ) ) ;
816- }
817-
818- if ( serverOptions . ExpiredObjectCollectionFrequencySecs > 0 )
819- {
820- Task . Run ( async ( ) => await ObjectCollectTask ( serverOptions . ExpiredObjectCollectionFrequencySecs , ctsCommit . Token ) ) ;
821- }
822-
823- if ( serverOptions . ExpiredKeyDeletionScanFrequencySecs > 0 )
824- {
825- Task . Run ( async ( ) => await ExpiredKeyDeletionScanTask ( serverOptions . ExpiredKeyDeletionScanFrequencySecs , ctsCommit . Token ) ) ;
826- }
827-
828- if ( serverOptions . AdjustedIndexMaxCacheLines > 0 || serverOptions . AdjustedObjectStoreIndexMaxCacheLines > 0 )
829- {
830- Task . Run ( ( ) => IndexAutoGrowTask ( ctsCommit . Token ) ) ;
831- }
819+ // Start generic node tasks
820+ StartGenericNodeTasks ( ) ;
832821
822+ // Start object size trackers
833823 databaseManager . StartObjectSizeTrackers ( ctsCommit . Token ) ;
834824 }
835825
@@ -914,9 +904,63 @@ public void Dispose()
914904 monitor ? . Dispose ( ) ;
915905 luaTimeoutManager ? . Dispose ( ) ;
916906 ctsCommit ? . Cancel ( ) ;
907+ taskManager . Dispose ( ) ;
917908 databaseManager . Dispose ( ) ;
918909
919910 ctsCommit ? . Dispose ( ) ;
920911 }
912+
913+ /// <summary>
914+ /// Suspend background task that may interfere with the replicas AOF
915+ /// </summary>
916+ /// <returns></returns>
917+ public async Task SuspendPrimaryOnlyTasks ( )
918+ {
919+ await taskManager . Cancel ( TaskPlacementCategory . Primary ) ;
920+ }
921+
922+ /// <summary>
923+ /// Start background maintenance tasks that should only run when this node is a primary
924+ /// </summary>
925+ /// <returns></returns>
926+ public void StartPrimaryTasks ( )
927+ {
928+ if ( serverOptions . AofSizeLimit . Length > 0 )
929+ {
930+ var aofSizeLimitBytes = 1L << serverOptions . AofSizeLimitSizeBits ( ) ;
931+ taskManager . RegisterAndRun ( TaskType . AofSizeLimitTask , ( token ) => AutoCheckpointBasedOnAofSizeLimit ( aofSizeLimitBytes , token , logger ) ) ;
932+ }
933+
934+ if ( serverOptions . CommitFrequencyMs > 0 && serverOptions . EnableAOF )
935+ {
936+ taskManager . RegisterAndRun ( TaskType . CommitTask , ( token ) => CommitTask ( serverOptions . CommitFrequencyMs , token , logger ) ) ;
937+ }
938+
939+ if ( serverOptions . CompactionFrequencySecs > 0 && serverOptions . CompactionType != LogCompactionType . None )
940+ {
941+ taskManager . RegisterAndRun ( TaskType . CompactionTask , ( token ) => CompactionTask ( serverOptions . CompactionFrequencySecs , token ) ) ;
942+ }
943+
944+ if ( serverOptions . ExpiredObjectCollectionFrequencySecs > 0 )
945+ {
946+ taskManager . RegisterAndRun ( TaskType . ObjectCollectTask , ( token ) => ObjectCollectTask ( serverOptions . ExpiredObjectCollectionFrequencySecs , token ) ) ;
947+ }
948+
949+ if ( serverOptions . ExpiredKeyDeletionScanFrequencySecs > 0 )
950+ {
951+ taskManager . RegisterAndRun ( TaskType . ExpiredKeyDeletionTask , ( token ) => ExpiredKeyDeletionScanTask ( serverOptions . ExpiredKeyDeletionScanFrequencySecs , token ) ) ;
952+ }
953+ }
954+
955+ /// <summary>
956+ /// Start background maintenance generic tasks
957+ /// </summary>
958+ public void StartGenericNodeTasks ( )
959+ {
960+ if ( serverOptions . AdjustedIndexMaxCacheLines > 0 || serverOptions . AdjustedObjectStoreIndexMaxCacheLines > 0 )
961+ {
962+ taskManager . RegisterAndRun ( TaskType . IndexAutoGrowTask , ( token ) => IndexAutoGrowTask ( token ) ) ;
963+ }
964+ }
921965 }
922966}
0 commit comments