class TransportAction extends TransportMasterNodeReadAction<Request, Response> {

        private final Roles roles;

        @Inject
        public TransportAction(TransportService transportService,
                               ClusterService clusterService,
                               ThreadPool threadPool,
                               Roles roles) {
            super(Settings.EMPTY,
                  NAME,
                  false,
                  transportService,
                  clusterService,
                  threadPool,
                  Request::new);
            this.roles = roles;

            TransportActionProxy.registerProxyAction(transportService, NAME, Response::new);
        }

        @Override
        protected String executor() {
            return ThreadPool.Names.SAME;
        }

        @Override
        protected Response read(StreamInput in) throws IOException {
            return new Response(in);
        }

        @Override
        protected void masterOperation(Request request,
                                       ClusterState state,
                                       ActionListener<Response> listener) throws Exception {<FILL_FUNCTION_BODY>}

        @Override
        protected ClusterBlockException checkBlock(Request request,
                                                   ClusterState state) {
            return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
        }
    }

            // Ensure subscribing user was not dropped after remote connection was established on another side.
            // Subscribing users must be checked on a publisher side as they belong to the publishing cluster.
            Role subscriber = roles.findUser(request.subscribingUserName());
            if (subscriber == null) {
                throw new IllegalStateException(
                    String.format(
                        Locale.ENGLISH, "Cannot build publication state, subscribing user '%s' was not found.",
                        request.subscribingUserName()
                    )
                );
            }

            PublicationsMetadata publicationsMetadata = state.metadata().custom(PublicationsMetadata.TYPE);
            if (publicationsMetadata == null) {
                LOGGER.trace("No publications found on remote cluster.");
                throw new IllegalStateException("Cannot build publication state, no publications found");
            }

            Map<RelationName, RelationMetadata> allRelationsInPublications = new HashMap<>();
            List<String> unknownPublications = new ArrayList<>();
            for (var publicationName : request.publications()) {
                var publication = publicationsMetadata.publications().get(publicationName);
                if (publication == null) {
                    unknownPublications.add(publicationName);
                    continue;
                }

                // Publication owner cannot be null as we ensure that users who owns publication cannot be dropped.
                // Also, before creating publication or subscription we check that owner was not dropped right before creation.
                Role publicationOwner = roles.findUser(publication.owner());
                allRelationsInPublications.putAll(
                    publication.resolveCurrentRelations(state, roles, publicationOwner, subscriber, publicationName));
            }
            listener.onResponse(new Response(allRelationsInPublications, unknownPublications));
        
<methods>public void <init>(java.lang.String) ,public boolean equals(java.lang.Object) ,public Reader<io.crate.replication.logical.action.PublicationsStateAction.Response> getResponseReader() ,public int hashCode() ,public java.lang.String name() ,public org.elasticsearch.transport.TransportRequestOptions transportOptions(org.elasticsearch.common.settings.Settings) <variables>private final non-sealed java.lang.String name