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

io.zeebe.transport.ClientTransportBuilder 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.dispatcher.FragmentHandler;
import io.zeebe.transport.impl.ClientOutputImpl;
import io.zeebe.transport.impl.ClientReceiveHandler;
import io.zeebe.transport.impl.DefaultChannelFactory;
import io.zeebe.transport.impl.EndpointRegistryImpl;
import io.zeebe.transport.impl.RemoteAddressListImpl;
import io.zeebe.transport.impl.TransportChannelFactory;
import io.zeebe.transport.impl.TransportContext;
import io.zeebe.transport.impl.actor.ClientActorContext;
import io.zeebe.transport.impl.actor.ClientConductor;
import io.zeebe.transport.impl.actor.Receiver;
import io.zeebe.transport.impl.memory.NonBlockingMemoryPool;
import io.zeebe.transport.impl.memory.TransportMemoryPool;
import io.zeebe.transport.impl.sender.Sender;
import io.zeebe.util.ByteValue;
import io.zeebe.util.sched.ActorScheduler;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class ClientTransportBuilder {
  /** In the same order of magnitude of what apache and nginx use. */
  protected static final Duration DEFAULT_CHANNEL_KEEP_ALIVE_PERIOD = Duration.ofSeconds(5);

  protected static final long DEFAULT_CHANNEL_CONNECT_TIMEOUT = 500;
  private final String name;

  private int messageMaxLength = 1024 * 512;
  protected Duration keepAlivePeriod = DEFAULT_CHANNEL_KEEP_ALIVE_PERIOD;

  protected Dispatcher receiveBuffer;
  private ActorScheduler scheduler;
  protected List listeners;
  protected TransportChannelFactory channelFactory;

  private TransportMemoryPool requestMemoryPool =
      new NonBlockingMemoryPool(ByteValue.ofMegabytes(4));
  private TransportMemoryPool messageMemoryPool =
      new NonBlockingMemoryPool(ByteValue.ofMegabytes(4));

  protected Duration defaultRequestRetryTimeout = Duration.ofSeconds(15);
  protected Duration defaultMessageRetryTimeout = Duration.ofSeconds(1);

  public ClientTransportBuilder(final String name) {
    this.name = name;
  }

  public ClientTransportBuilder scheduler(ActorScheduler scheduler) {
    this.scheduler = scheduler;
    return this;
  }

  /**
   * Optional. If set, all incoming messages (single-message protocol) are put onto the provided
   * buffer. {@link ClientTransport#openSubscription(String, ClientMessageHandler)} can be used to
   * consume from this buffer.
   */
  public ClientTransportBuilder messageReceiveBuffer(Dispatcher receiveBuffer) {
    this.receiveBuffer = receiveBuffer;
    return this;
  }

  public ClientTransportBuilder requestMemoryPool(TransportMemoryPool requestMemoryPool) {
    this.requestMemoryPool = requestMemoryPool;
    return this;
  }

  public ClientTransportBuilder messageMemoryPool(TransportMemoryPool messageMemoryPool) {
    this.messageMemoryPool = messageMemoryPool;
    return this;
  }

  public ClientTransportBuilder inputListener(ClientInputListener listener) {
    if (listeners == null) {
      listeners = new ArrayList<>();
    }
    this.listeners.add(listener);
    return this;
  }

  public ClientTransportBuilder messageMaxLength(int messageMaxLength) {
    this.messageMaxLength = messageMaxLength;
    return this;
  }

  /** The period in which a dummy message is sent to keep the underlying TCP connection open. */
  public ClientTransportBuilder keepAlivePeriod(Duration keepAlivePeriod) {
    if (keepAlivePeriod.getSeconds() < 1) {
      throw new RuntimeException("Min value for keepalive period is 1s.");
    }
    this.keepAlivePeriod = keepAlivePeriod;
    return this;
  }

  public ClientTransportBuilder channelFactory(TransportChannelFactory channelFactory) {
    this.channelFactory = channelFactory;
    return this;
  }

  public ClientTransportBuilder defaultRequestRetryTimeout(Duration duration) {
    this.defaultRequestRetryTimeout = duration;
    return this;
  }

  public ClientTransportBuilder defaultMessageRetryTimeout(Duration duration) {
    this.defaultMessageRetryTimeout = duration;
    return this;
  }

  public ClientTransport build() {
    validate();

    final ClientActorContext actorContext = new ClientActorContext();

    final Sender sender =
        new Sender(actorContext, messageMemoryPool, requestMemoryPool, keepAlivePeriod);

    final RemoteAddressListImpl remoteAddressList = new RemoteAddressListImpl();
    final EndpointRegistry endpointRegistry = new EndpointRegistryImpl(name, remoteAddressList);

    final TransportContext transportContext =
        buildTransportContext(
            remoteAddressList,
            endpointRegistry,
            new ClientReceiveHandler(sender, receiveBuffer, listeners),
            receiveBuffer);

    return build(actorContext, transportContext);
  }

  protected TransportContext buildTransportContext(
      RemoteAddressListImpl addressList,
      EndpointRegistry endpointRegistry,
      FragmentHandler receiveHandler,
      Dispatcher receiveBuffer) {
    final TransportContext context = new TransportContext();
    context.setName("client");
    context.setReceiveBuffer(receiveBuffer);
    context.setMessageMaxLength(messageMaxLength);
    context.setRemoteAddressList(addressList);
    context.setEndpointRegistry(endpointRegistry);
    context.setReceiveHandler(receiveHandler);
    context.setChannelKeepAlivePeriod(keepAlivePeriod);

    if (channelFactory != null) {
      context.setChannelFactory(channelFactory);
    } else {
      context.setChannelFactory(
          new DefaultChannelFactory(scheduler.getMetricsManager(), context.getName()));
    }

    return context;
  }

  protected ClientTransport build(ClientActorContext actorContext, TransportContext context) {
    actorContext.setMetricsManager(scheduler.getMetricsManager());

    final ClientConductor conductor = new ClientConductor(actorContext, context);
    final Receiver receiver = new Receiver(actorContext, context);
    final Sender sender = actorContext.getSender();

    final ClientOutput output =
        new ClientOutputImpl(
            context.getEndpointRegistry(),
            sender,
            defaultRequestRetryTimeout,
            defaultMessageRetryTimeout);

    context.setClientOutput(output);

    scheduler.submitActor(conductor, true);
    scheduler.submitActor(receiver, true);
    scheduler.submitActor(sender, true);

    return new ClientTransport(actorContext, context);
  }

  private void validate() {
    Objects.requireNonNull(scheduler, "Scheduler must be provided");
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy