public Cluster start() throws IOException {
Objects.requireNonNull(listenAddress);
sharedResources = new SharedResources(listenAddress);
messagingServer = messagingServer != null
? messagingServer
: new GrpcServer(listenAddress, sharedResources, settings.getUseInProcessTransport());
messagingClient = messagingClient != null
? messagingClient
: new GrpcClient(listenAddress, sharedResources, settings);
final NodeId currentIdentifier = Utils.nodeIdFromUUID(UUID.randomUUID());
final MembershipView membershipView = new MembershipView(K, Collections.singletonList(currentIdentifier),
Collections.singletonList(listenAddress));
final MultiNodeCutDetector cutDetector = new MultiNodeCutDetector(K, H, L);
edgeFailureDetector = edgeFailureDetector != null ? edgeFailureDetector
: new PingPongFailureDetector.Factory(listenAddress, messagingClient);
final Map<Endpoint, Metadata> metadataMap = metadata.getMetadataCount() > 0
? Collections.singletonMap(listenAddress, metadata)
: Collections.emptyMap();
final MembershipService membershipService = new MembershipService(listenAddress,
cutDetector, membershipView, sharedResources, settings,
messagingClient, edgeFailureDetector, metadataMap, subscriptions);
messagingServer.setMembershipService(membershipService);
messagingServer.start();
return new Cluster(messagingServer, membershipService, sharedResources, listenAddress);
}