`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/cluster/ClusterStateTaskExecutor.java
* Callback invoked after new cluster state is published. Note that this method is not invoked if the cluster state was not updated.
     *
     * Note that this method will be executed using system context.
     *
     * @param newClusterState The new state which was published.
     */
    default void clusterStatePublished(ClusterState newClusterState) {}
    /**
     * Builds a concise description of a list of tasks (to be used in logging etc.).
     *
     * Note that the tasks given are not necessarily the same as those that will be passed to {@link #execute} but are guaranteed to be a
     * subset of them. This method can be called multiple times with different lists before execution.
     *
     * @param tasks the tasks to describe.
     * @return A string which describes the batch of tasks.
     */
    default String describeTasks(List<T> tasks) {
        final StringBuilder output = new StringBuilder();
        Strings.collectionToDelimitedStringWithLimit(
            (Iterable<String>) () -> tasks.stream().map(Object::toString).filter(s -> s.isEmpty() == false).iterator(),
            ", ",
            "",
            "",
            1024,
            output
        );
        return output.toString();
    }
    /**
     * A task to be executed, along with callbacks for the executor to record the outcome of this task's execution. The executor must