`GatewayService` implements logic for delaying state recovery in the cluster until enough data nodes have joined and/or some timeout has occurred. The implementation is pretty old and doesn't make use of much modern infrastructure for doing this kind of thing, making it pretty hard to follow and to improve (see e.g. #86588). We should clean it up and simplify it.
server/src/main/java/org/elasticsearch/gateway/GatewayService.java
public void clusterStateProcessed(final ClusterState oldState, final ClusterState newState) {
            logger.info("recovered [{}] indices into cluster_state", newState.metadata().indices().size());
            
            
            resetRecoveredFlags();
            rerouteService.reroute("state recovered", Priority.NORMAL, ActionListener.noop());
        }
        @Override
        public void onFailure(final Exception e) {
            logger.log(
                MasterService.isPublishFailureException(e) ? Level.DEBUG : Level.INFO,
                () -> "unexpected failure during [" + TASK_SOURCE + "]",
                e
            );
            resetRecoveredFlags();
        }
    }
    
    TimeValue recoverAfterTime() {
        return recoverAfterTime;
    }
    private void runRecovery() {
        submitUnbatchedTask(TASK_SOURCE, new RecoverStateUpdateTask());
    }
    @SuppressForbidden(reason = "legacy usage of unbatched task") 
    private void submitUnbatchedTask(@SuppressWarnings("SameParameterValue") String source, ClusterStateUpdateTask task) {
        clusterService.submitUnbatchedStateUpdateTask(source, task);
    }
}