All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.scalecube.cluster.transport.api.Transport Maven / Gradle / Ivy

The newest version!
package io.scalecube.cluster.transport.api;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * Transport is responsible for maintaining existing p2p connections to/from other transports. It
 * allows to send messages to other transports and listen for incoming messages.
 */
public interface Transport {

  Pattern ADDRESS_FORMAT = Pattern.compile("(?^.*):(?\\d+$)");

  /**
   * Returns local address on which current instance of transport listens for incoming messages.
   *
   * @return address
   */
  String address();

  /**
   * Start transport. After this call method {@link #address()} shall be eligible for calling.
   *
   * @return started {@code Transport}
   */
  Mono start();

  /**
   * Stop transport, disconnect all connections and release all resources which belong to this
   * transport. After transport is stopped it can't be used again. Observable returned from method
   * {@link #listen()} will immediately emit onComplete event for all subscribers.
   */
  Mono stop();

  /**
   * Return transport's stopped state.
   *
   * @return true if transport was stopped; false otherwise
   */
  boolean isStopped();

  /**
   * Sends message to the given address. It will issue connect in case if no transport channel by
   * given transport {@code address} exists already. Send is an async operation.
   *
   * @param address address where message will be sent
   * @param message message to send
   * @return promise which will be completed with result of sending (void or exception)
   * @throws IllegalArgumentException if {@code message} or {@code address} is null
   */
  Mono send(String address, Message message);

  /**
   * Sends message to the given address. It will issue connect in case if no transport channel by
   * given transport {@code address} exists already. Send is an async operation and expecting a
   * response by a provided correlationId and sender address of the caller.
   *
   * @param address address where message will be sent
   * @param request to send message must contain correlctionId and sender to handle reply.
   * @return promise which will be completed with result of sending (message or exception)
   * @throws IllegalArgumentException if {@code message} or {@code address} is null
   */
  Mono requestResponse(String address, Message request);

  /**
   * Returns stream of received messages. For each observers subscribed to the returned observable:
   *
   * 
    *
  • {@code rx.Observer#onNext(Object)} will be invoked when some message arrived to current * transport *
  • {@code rx.Observer#onCompleted()} will be invoked when there is no possibility that * server will receive new message observable for already closed transport *
  • {@code rx.Observer#onError(Throwable)} will not be invoked *
* * @return Observable which emit received messages or complete event when transport is closed */ Flux listen(); /** * Init transport with the default configuration synchronously. Starts to accept connections on * local address. * * @return transport */ static Transport bindAwait() { return bindAwait(TransportConfig.defaultConfig()); } /** * Init transport with the given configuration synchronously. Starts to accept connections on * local address. * * @return transport */ static Transport bindAwait(TransportConfig config) { try { return bind(config).block(); } catch (Exception e) { throw Exceptions.propagate(e.getCause() != null ? e.getCause() : e); } } /** * Init transport with the default configuration asynchronously. Starts to accept connections on * local address. * * @return promise for bind operation */ static Mono bind() { return bind(TransportConfig.defaultConfig()); } /** * Init transport with the given configuration asynchronously. Starts to accept connections on * local address. * * @param config transport config * @return promise for bind operation */ static Mono bind(TransportConfig config) { Objects.requireNonNull(config.transportFactory(), "[bind] transportFactory"); return config.transportFactory().createTransport(config).start(); } /** * Parses string in format {@code host:port} and returns host part. * * @param address address, must be string in format {@code host:port} * @return address host, or throwing exception */ static String parseHost(String address) { if (address == null || address.isEmpty()) { throw new IllegalArgumentException("Cannot parse address host from: " + address); } Matcher matcher = ADDRESS_FORMAT.matcher(address); if (!matcher.find()) { throw new IllegalArgumentException("Cannot parse address host from: " + address); } String host = matcher.group(1); if (host == null || host.isEmpty()) { throw new IllegalArgumentException("Cannot parse address host from: " + address); } return host; } /** * Parses string in format {@code host:port} and returns port part. * * @param address address, must be string in format {@code host:port} * @return address port, or throwing exception */ static int parsePort(String address) { if (address == null || address.isEmpty()) { throw new IllegalArgumentException("Cannot parse address port from: " + address); } Matcher matcher = ADDRESS_FORMAT.matcher(address); if (!matcher.find()) { throw new IllegalArgumentException("Cannot parse address port from: " + address); } int port; try { port = Integer.parseInt(matcher.group(2)); } catch (NumberFormatException ex) { throw new IllegalArgumentException("Cannot parse address port from: " + address, ex); } return port; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy