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

io.zeebe.transport.ClientTransport Maven / Gradle / Ivy

There is a newer version: 0.16.4
Show newest version
/*
 * Copyright © 2017 camunda services GmbH ([email protected])
 *
 * 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 io.zeebe.transport;

import io.zeebe.dispatcher.Dispatcher;
import io.zeebe.transport.impl.TransportContext;
import io.zeebe.transport.impl.actor.ActorContext;
import io.zeebe.util.sched.future.ActorFuture;
import java.time.Duration;

public class ClientTransport implements AutoCloseable {

  public static final int UNKNOWN_NODE_ID = -1;

  private final ClientOutput output;
  private final RemoteAddressList remoteAddressList;
  private final EndpointRegistry endpointRegistry;
  private final ActorContext transportActorContext;
  private final Dispatcher receiveBuffer;
  private final TransportContext transportContext;

  public ClientTransport(ActorContext transportActorContext, TransportContext transportContext) {
    this.transportActorContext = transportActorContext;
    this.transportContext = transportContext;
    this.output = transportContext.getClientOutput();
    this.remoteAddressList = transportContext.getRemoteAddressList();
    this.endpointRegistry = transportContext.getEndpointRegistry();
    this.receiveBuffer = transportContext.getReceiveBuffer();
  }

  /** @return interface to stage outbound data */
  public ClientOutput getOutput() {
    return output;
  }

  /**
   * Register an endpoint address for node id. Transport will make sure to keep an open channel to
   * this endpoint until it is deactivated or retired.
   */
  public void registerEndpoint(int nodeId, SocketAddress socketAddress) {
    endpointRegistry.setEndpoint(nodeId, socketAddress);
  }

  public RemoteAddress getEndpoint(int nodeId) {
    return endpointRegistry.getEndpoint(nodeId);
  }

  /**
   * Signals that the endpoint of the node is no longer in use for the time being. A transport
   * channel will no longer be managed. A endpoint is reactivated when the endpoint is registered
   * again.
   */
  public void deactivateEndpoint(int nodeId) {
    endpointRegistry.removeEndpoint(nodeId);
  }

  /**
   * Signals that the endpoint is no longer used and that the stream should not be reused on
   * reactivation. That means, when the endpoint is registered again, it is assigned a different
   * stream id.
   */
  public void retireEndpoint(int nodeId) {
    endpointRegistry.retire(nodeId);
  }

  /**
   * DO NOT USE in production code as it involves blocking the current thread.
   *
   * 

Not thread-safe * *

Like {@link #registerEndpoint(int, SocketAddress)} but blockingly waits for the * corresponding channel to be opened such that it is probable that subsequent requests/messages * can be sent. This saves test code the need to retry sending. */ public void registerEndpointAndAwaitChannel(final int nodeId, SocketAddress addr) { final RemoteAddress remoteAddress = getRemoteAddress(addr); if (remoteAddress == null) { final Object monitor = new Object(); synchronized (monitor) { final TransportListener listener = new TransportListener() { @Override public void onConnectionEstablished(RemoteAddress remoteAddress) { synchronized (monitor) { if (remoteAddress.getAddress().equals(addr)) { monitor.notifyAll(); removeChannelListener(this); } } } @Override public void onConnectionClosed(RemoteAddress remoteAddress) {} }; transportActorContext.registerListener(listener).join(); registerEndpoint(nodeId, addr); try { monitor.wait(Duration.ofSeconds(10).toMillis()); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } private RemoteAddress getRemoteAddress(SocketAddress addr) { return remoteAddressList.getByAddress(addr); } /** * Creates a subscription on the receive buffer for single messages. * * @throws RuntimeException if this client was not created with a receive buffer for * single-messages */ public ActorFuture openSubscription( String subscriptionName, ClientMessageHandler messageHandler) { if (receiveBuffer == null) { throw new RuntimeException("Cannot throw exception. No receive buffer in use"); } return transportActorContext .getClientConductor() .openClientInputMessageSubscription( subscriptionName, messageHandler, output, remoteAddressList); } /** * Registers a listener with callbacks for whenever a connection to a remote gets established or * closed. */ public ActorFuture registerChannelListener(TransportListener channelListener) { return transportActorContext.registerListener(channelListener); } public void removeChannelListener(TransportListener listener) { transportActorContext.removeListener(listener); } public ActorFuture closeAsync() { return transportActorContext.onClose(); } @Override public void close() { closeAsync().join(); } public void interruptAllChannels() { transportActorContext.interruptAllChannels(); } public ActorFuture closeAllChannels() { return transportActorContext.closeAllOpenChannels(); } public Duration getChannelKeepAlivePeriod() { return transportContext.getChannelKeepAlivePeriod(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy