* Copyright © 2016 - 2020 VMware, Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an “AS IS” BASIS, without warranties or conditions of any kind,
 * EITHER EXPRESS OR IMPLIED. See the License for the specific language governing
 * permissions and limitations under the License.

package com.vrg.standalone;

import com.google.common.net.HostAndPort;
import com.google.protobuf.ByteString;
import com.vrg.rapid.Cluster;
import com.vrg.rapid.messaging.impl.NettyClientServer;
import com.vrg.rapid.pb.Endpoint;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.IOException;

 * An example to demonstrate how to plugin a custom messaging implementation to Rapid.
public class AgentWithNettyMessaging extends StandaloneAgent {
    private static final Logger LOG = LoggerFactory.getLogger(AgentWithNettyMessaging.class);
    private static final int SLEEP_INTERVAL_MS = 1000;
    private static final int MAX_TRIES = 400;
    @Nullable private Cluster cluster = null;

    private AgentWithNettyMessaging(final HostAndPort listenAddress, final HostAndPort seedAddress) {
        super(listenAddress, seedAddress);

    public void startCluster() throws IOException, InterruptedException {
        final Endpoint endpoint = Endpoint.newBuilder()

        // To use your own messaging implementation with Rapid, supply an instance each of IMessagingClient
        // and IMessagingServer to Cluster.Builder.setMessagingClientServer().
        // In this example, we use an object NettyClientServer which implements both the IMessagingClient
        // and IMessagingServer interfaces.
        final NettyClientServer nettyMessaging = new NettyClientServer(endpoint);
        if (listenAddress.equals(seedAddress)) {
            cluster = new Cluster.Builder(listenAddress)
                    .setMessagingClientAndServer(nettyMessaging, nettyMessaging)

        } else {
            cluster = new Cluster.Builder(listenAddress)
                    .setMessagingClientAndServer(nettyMessaging, nettyMessaging)

     * Prints the current membership
    private void printClusterMembership() {
        LOG.info("Node {} -- cluster size {}", listenAddress, cluster.getMembershipSize());

    public static void main(final String[] args) throws ParseException {
        final Options options = new Options();
        options.addRequiredOption("l", "listenAddress", true, "The listening addresses Rapid Cluster instances");
        options.addRequiredOption("s", "seedAddress", true, "The seed node's address for the bootstrap protocol");
        final CommandLineParser parser = new DefaultParser();
        final CommandLine cmd = parser.parse(options, args);

        // Get CLI options
        final HostAndPort listenAddress = HostAndPort.fromString(cmd.getOptionValue("listenAddress"));
        final HostAndPort seedAddress = HostAndPort.fromString(cmd.getOptionValue("seedAddress"));

        // Bring up Rapid node
        try {
            final AgentWithNettyMessaging agent = new AgentWithNettyMessaging(listenAddress, seedAddress);
            for (int i = 0; i < MAX_TRIES; i++) {
        } catch (final IOException | InterruptedException e) {
            LOG.error("Exception thrown by StandaloneAgent {}", e);