Actions `cluster:admin/repository/analyze/blob` and `cluster:admin/repository/analyze/register` and so on are only invoked via the transport service, they do not need to register as client actions so we can drop the `ActionType` instance. Instead the root `RepositoryAnalyzeAction` should create and register all these transport actions itself. But even the root `RepositoryAnalyzeAction` should not be an `ActionType` derivative, we should just declare an `ActionType` instance directly. Moreover we can use `ActionType#localOnly` since the client action does not run on remote clusters.
x-pack/plugin/snapshot-repo-test-kit/src/main/java/org/elasticsearch/repositories/blobstore/testkit/ContendedRegisterAnalyzeAction.java
final BlobContainer blobContainer = blobStoreRepository.blobStore().blobContainer(path);
            logger.trace("handling [{}]", request);
            assert task instanceof CancellableTask;
            final String registerName = request.getRegisterName();
            final ActionListener<OptionalBytesReference> initialValueListener = new ActionListener<>() {
                @Override
                public void onResponse(OptionalBytesReference maybeInitialBytes) {
                    final long initialValue = maybeInitialBytes.isPresent() ? longFromBytes(maybeInitialBytes.bytesReference()) : 0L;
                    ActionListener.run(outerListener.<Void>map(ignored -> ActionResponse.Empty.INSTANCE), l -> {
                        if (initialValue < 0 || initialValue >= request.getRequestCount()) {
                            throw new IllegalStateException("register holds unexpected value [" + initialValue + "]");
                        }
                        class Execution extends ActionRunnable<Void> {
                            private long currentValue;
                            private final ActionListener<OptionalBytesReference> witnessListener;
                            Execution(long currentValue) {
                                super(l);
                                this.currentValue = currentValue;
                                this.witnessListener = listener.delegateFailure(this::handleWitness);
                            }
                            @Override
                            protected void doRun() {
                                if (((CancellableTask) task).notifyIfCancelled(listener) == false) {
                                    blobContainer.compareAndExchangeRegister(
                                        OperationPurpose.REPOSITORY_ANALYSIS,
                                        registerName,
                                        bytesFromLong(currentValue),
                                        bytesFromLong(currentValue + 1L),
                                        witnessListener
                                    );