3939import org .apache .amoro .resource .ResourceType ;
4040import org .apache .amoro .server .catalog .CatalogManager ;
4141import org .apache .amoro .server .dashboard .model .OptimizerResourceInfo ;
42+ import org .apache .amoro .server .ha .HighAvailabilityContainer ;
4243import org .apache .amoro .server .manager .AbstractOptimizerContainer ;
4344import org .apache .amoro .server .optimizing .OptimizingProcess ;
4445import org .apache .amoro .server .optimizing .OptimizingQueue ;
5657import org .apache .amoro .server .resource .QuotaProvider ;
5758import org .apache .amoro .server .table .DefaultTableRuntime ;
5859import org .apache .amoro .server .table .RuntimeHandlerChain ;
59- import org .apache .amoro .server .BucketAssignStore ;
60- import org .apache .amoro .server .ha .HighAvailabilityContainer ;
6160import org .apache .amoro .server .table .TableService ;
6261import org .apache .amoro .shade .guava32 .com .google .common .base .Preconditions ;
6362import org .apache .amoro .shade .guava32 .com .google .common .collect .Sets ;
@@ -126,15 +125,6 @@ public class DefaultOptimizingService extends StatedPersistentBase
126125 private final HighAvailabilityContainer haContainer ;
127126 private final boolean isMasterSlaveMode ;
128127
129- public DefaultOptimizingService (
130- Configurations serviceConfig ,
131- CatalogManager catalogManager ,
132- OptimizerManager optimizerManager ,
133- TableService tableService ,
134- BucketAssignStore bucketAssignStore ) {
135- this (serviceConfig , catalogManager , optimizerManager , tableService , bucketAssignStore , null );
136- }
137-
138128 public DefaultOptimizingService (
139129 Configurations serviceConfig ,
140130 CatalogManager catalogManager ,
@@ -579,14 +569,23 @@ public void run() {
579569 // Use 1/4 of optimizerTouchTimeout as sync interval (default ~30 seconds), used for
580570 // master-slave follower sync.
581571 long syncInterval = Math .max (5000 , optimizerTouchTimeout / 4 );
572+ // In non-master-slave mode, this node is always the leader.
573+ boolean wasLeader = !isMasterSlaveMode ;
582574 while (!stopped ) {
583575 try {
584- if (isMasterSlaveMode && (haContainer == null || !haContainer .hasLeadership ())) {
585- // Not leader: let subclass handle follower state (e.g. sync optimizer list from DB)
586- onFollowerTick (syncInterval );
587- } else {
576+ boolean isLeader = !isMasterSlaveMode || haContainer .hasLeadership ();
577+ if (!wasLeader && isLeader ) {
578+ // Follower → Leader transition: subclass takes over monitoring of inherited optimizers.
579+ onBecomeLeader ();
580+ }
581+ wasLeader = isLeader ;
582+
583+ if (isLeader ) {
588584 T keepingTask = suspendingQueue .take ();
589585 this .processTask (keepingTask );
586+ } else {
587+ // Not leader: let subclass handle follower state (e.g. sync optimizer list from DB)
588+ onFollowerTick (syncInterval );
590589 }
591590 } catch (InterruptedException ignored ) {
592591 } catch (Throwable t ) {
@@ -600,6 +599,8 @@ public void run() {
600599 protected void onFollowerTick (long syncInterval ) throws InterruptedException {
601600 Thread .sleep (syncInterval );
602601 }
602+
603+ protected void onBecomeLeader () {}
603604 }
604605
605606 private class OptimizerKeeper extends AbstractKeeper <OptimizerKeepingTask > {
@@ -639,6 +640,17 @@ protected void onFollowerTick(long syncInterval) throws InterruptedException {
639640 Thread .sleep (syncInterval );
640641 }
641642
643+ @ Override
644+ protected void onBecomeLeader () {
645+ LOG .info (
646+ "Became leader, starting heartbeat monitoring for {} inherited optimizers" ,
647+ authOptimizers .size ());
648+ // All optimizers in authOptimizers were loaded from DB by the follower sync loop.
649+ // Their touchTime reflects the latest DB-persisted heartbeat, which is the correct
650+ // baseline for the new leader's expiry detection.
651+ authOptimizers .values ().forEach (this ::keepInTouch );
652+ }
653+
642654 /**
643655 * Load optimizer information from database. This is used in master-slave mode for follower
644656 * nodes to sync optimizer state from database. This method performs incremental updates by
0 commit comments