In https://github.com/elastic/elasticsearch/pull/78547 we introduced batching for the ILM master tasks that occur on the happy path. However if a high-shard-count cluster encounters problems while doing ILM-related things—perhaps some nodes are temporarily unavailable for taking a snapshot—then we process the resulting `ilm-retry-failed-step` and `ilm-move-to-error-step` tasks one-by-one which can significantly delay the cluster's recovery from its problems.

We should batch these things together too.

It looks like we also enqueue duplicate `ilm-retry-failed-step` on each poll interval too, although we do appear to treat the duplicates as no-ops at execution time.

Relates https://github.com/elastic/elasticsearch/issues/77466
x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/IndexLifecycleRunner.java
registerFailedOperation(indexMetadata, e);
            }),
            newExecutor()
        );
    }
    /**
     * Set step info for the given index inside of its {@link LifecycleExecutionState} without
     * changing other execution state.
     */
    private void setStepInfo(Index index, String policy, @Nullable Step.StepKey currentStepKey, ToXContentObject stepInfo) {
        submitUnlessAlreadyQueued(
            String.format(
                Locale.ROOT,
                "ilm-set-step-info {policy [%s], index [%s], currentStep [%s]}",
                policy,
                index.getName(),
                currentStepKey
            ),
            new SetStepInfoUpdateTask(index, policy, currentStepKey, stepInfo)
        );
    }
    /**
     * Mark the index with step info explaining that the policy doesn't exist.
     */
    private void markPolicyDoesNotExist(String policyName, Index index, LifecycleExecutionState executionState) {
        markPolicyRetrievalError(
            policyName,
            index,
            executionState,
            new IllegalArgumentException("policy [" + policyName + "] does not exist")