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

com.firefly.net.tcp.flex.client.MultiplexingClient Maven / Gradle / Ivy

There is a newer version: 5.0.0-dev6
Show newest version
package com.firefly.net.tcp.flex.client;

import com.firefly.net.tcp.SimpleTcpClient;
import com.firefly.net.tcp.codec.flex.decode.FrameParser;
import com.firefly.net.tcp.codec.flex.protocol.PingFrame;
import com.firefly.net.tcp.codec.flex.stream.FlexConnection;
import com.firefly.net.tcp.codec.flex.stream.impl.FlexConnectionImpl;
import com.firefly.net.tcp.codec.flex.stream.impl.FlexSession;
import com.firefly.net.tcp.flex.metric.FlexMetric;
import com.firefly.utils.CollectionUtils;
import com.firefly.utils.concurrent.Scheduler;
import com.firefly.utils.concurrent.Schedulers;
import com.firefly.utils.function.Action1;
import com.firefly.utils.io.IO;
import com.firefly.utils.lang.AbstractLifeCycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author Pengtao Qiu
 */
public class MultiplexingClient extends AbstractLifeCycle {

    protected static final Logger log = LoggerFactory.getLogger("firefly-system");
    public static final String HEARTBEAT_KEY = "_heartbeat";

    private MultiplexingClientConfiguration configuration = new MultiplexingClientConfiguration();
    private SimpleTcpClient client;
    private Action1 accept;
    private Scheduler scheduler = Schedulers.createScheduler();
    private FlexConnectionManager flexConnectionManager;
    private FlexMetric flexMetric;

    public MultiplexingClient() {
    }

    public MultiplexingClient(MultiplexingClientConfiguration configuration) {
        this.configuration = configuration;
    }

    public MultiplexingClientConfiguration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(MultiplexingClientConfiguration configuration) {
        this.configuration = configuration;
    }

    public MultiplexingClient accept(Action1 accept) {
        this.accept = accept;
        return this;
    }

    public CompletableFuture connect(String host, int port) {
        if (!useConnectionManager()) {
            start();
        }
        return client.connect(host, port).thenApply(connection -> {
            // create flex connection
            FlexSession session = new FlexSession(1, connection, flexMetric, configuration.getStreamMaxIdleTime(), scheduler);
            FlexConnectionImpl flexConnection = new FlexConnectionImpl(configuration, connection, session);
            connection.setAttachment(flexConnection);

            Optional.ofNullable(accept).ifPresent(a -> a.call(flexConnection));

            // set frame parser
            FrameParser frameParser = new FrameParser();
            frameParser.complete(session::notifyFrame);
            connection.receive(frameParser::receive).onException(ex -> {
                log.error("Connection " + connection.getSessionId() + " exception.", ex);
                IO.close(connection);
            });

            if (configuration.getHeartbeatInterval() > 0) {
                session.setAttribute(HEARTBEAT_KEY, scheduler.scheduleAtFixedRate(
                        () -> flexConnection.getSession().ping(new PingFrame(false)),
                        configuration.getHeartbeatInterval(),
                        configuration.getHeartbeatInterval(),
                        TimeUnit.MILLISECONDS));
                connection.onClose(session::clear)
                          .onClose(() -> Optional.ofNullable(session.getAttribute(HEARTBEAT_KEY))
                                                 .map(o -> (Scheduler.Future) o)
                                                 .ifPresent(Scheduler.Future::cancel));
            }
            return flexConnection;
        });
    }

    public FlexConnectionManager getFlexConnectionManager() {
        return flexConnectionManager;
    }

    public FlexConnection getConnection() {
        return flexConnectionManager.getConnection();
    }

    public boolean useConnectionManager() {
        return configuration.getAddressProvider() != null || !CollectionUtils.isEmpty(configuration.getServerUrlSet());
    }

    @Override
    protected void init() {
        flexMetric = new FlexMetric(configuration.getTcpConfiguration().getMetricReporterFactory().getMetricRegistry(),
                "flex.client");
        client = new SimpleTcpClient(configuration.getTcpConfiguration());
        if (configuration.getHeartbeatInterval() <= 0) {
            configuration.setHeartbeatInterval(15 * 1000);
        }
        if (useConnectionManager()) {
            if (configuration.getAddressProvider() != null) {
                flexConnectionManager = new FlexConnectionManager(this, configuration.getAddressProvider());
            } else {
                flexConnectionManager = new FlexConnectionManager(this, () -> configuration.getServerUrlSet());
            }
        }
    }

    @Override
    protected void destroy() {
        client.stop();
        if (configuration.getHeartbeatInterval() > 0) {
            scheduler.stop();
        }
        Optional.ofNullable(flexConnectionManager).ifPresent(FlexConnectionManager::stop);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy