Today submitting an unbatched `ClusterStateUpdateTask` to the `MasterService` is deprecated, and devs are encouraged to write their own batching executor instead. In principle this makes it possible to combine updates without incurring the costs of building a whole new `ClusterState` on each iteration, but in practice most implementations don't work at a lower level and just iteratively update a `ClusterState`. Moreover creating new `ClusterState` instances is nothing like as expensive as once it was.

We should accept this and provide some friendlier utilities for writing batched cluster state updates, ideally leaving the developer to express the desired per-task update as a `ClusterState -> ClusterState` operator.
server/src/main/java/org/elasticsearch/reservedstate/service/ReservedStateUpdateTaskExecutor.java
* Reserved cluster state update task executor
 *
 * @param rerouteService instance of {@link RerouteService}, so that we can execute reroute after cluster state is published
 */
public record ReservedStateUpdateTaskExecutor(RerouteService rerouteService) implements ClusterStateTaskExecutor<ReservedStateUpdateTask> {
    private static final Logger logger = LogManager.getLogger(ReservedStateUpdateTaskExecutor.class);
    @Override
    public ClusterState execute(BatchExecutionContext<ReservedStateUpdateTask> batchExecutionContext) throws Exception {
        var updatedState = batchExecutionContext.initialState();
        for (final var taskContext : batchExecutionContext.taskContexts()) {
            try (var ignored = taskContext.captureResponseHeaders()) {
                updatedState = taskContext.getTask().execute(updatedState);
            }
            taskContext.success(() -> taskContext.getTask().listener().onResponse(ActionResponse.Empty.INSTANCE));
        }
        return updatedState;
    }
    @Override
    public void clusterStatePublished(ClusterState newClusterState) {
        rerouteService.reroute(
            "reroute after saving and reserving part of the cluster state",
            Priority.NORMAL,
            ActionListener.wrap(
                r -> logger.trace("reroute after applying and reserving part of the cluster state succeeded"),
                e -> logger.debug("reroute after applying and reserving part of the cluster state failed", e)
            )
        );
    }
}