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

io.vertx.up.uca.micro.center.ZeroRegistry Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.up.uca.micro.center;

import io.reactivex.Observable;
import io.vertx.core.ServidorOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.tp.plugin.etcd.center.EtcdData;
import io.vertx.up.eon.Values;
import io.vertx.up.eon.em.Etat;
import io.vertx.up.eon.em.EtcdPath;
import io.vertx.up.extension.pointer.PluginExtension;
import io.vertx.up.fn.Fn;
import io.vertx.up.log.Annal;
import io.vertx.up.util.Ut;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiFunction;

/**
 * Zero registry center to write/read data with Etcd for zero micro service
 * This will be called by ZeroRpcAgent class to write service meta.
 * 1. Status RUNNING/STOPPED/FAILED
 * /zero/ipc/status/{name}/{host}:{port}
 * 2. Services for discovery
 * /zero/ipc/services/{name}/{host}/{port}
 */
public class ZeroRegistry {

    private static final String PATH_STATUS = "/zero/{0}/{1}/services/{2}:{3}:{4}";

    private static final String PATH_CATALOG = "/zero/{0}/{1}/services";

    private static final String ROUTE_TREE = "/zero/{0}/{1}/routes/{2}";
    /*
     * The default path that should not be registry to etcd.
     */
    private static final Set DEFAULTS = new HashSet() {
        {
            add("/");
            add("/api/");
        }
    };

    private static final ConcurrentMap
            REGISTRY_MAP = new ConcurrentHashMap<>();

    private final transient Annal logger;
    private final transient EtcdData etcd;

    private ZeroRegistry(final Class useCls) {
        etcd = EtcdData.create(useCls);
        logger = Annal.get(useCls);
    }

    public static ZeroRegistry create(final Class useCls) {
        return Fn.poolThread(REGISTRY_MAP, () -> new ZeroRegistry(useCls));
    }

    /**
     * Get current etcd configuration information that initialized
     * in zero system.
     *
     * @return Return zero configuration in etcd
     */
    public JsonArray getConfig() {
        return etcd.getConfig();
    }

    public Set getData(
            final EtcdPath etcdPath,
            final String key,
            final BiFunction> convert
    ) {
        final String path = MessageFormat.format(ROUTE_TREE, etcd.getApplication(),
                etcdPath.toString().toLowerCase(), key);
        logger.debug(Info.ETCD_READ, path);
        final String node = etcd.readData(path);
        final Set sets = new HashSet<>();
        if (!Ut.isNil(node)) {
            final JsonArray value = new JsonArray(node);
            sets.addAll(convert.apply(key, value));
        }
        return sets;
    }

    public Set getServices(
            final EtcdPath etcdPath) {
        final String path = MessageFormat.format(PATH_CATALOG, etcd.getApplication(),
                etcdPath.toString().toLowerCase());
        logger.debug(Info.ETCD_READ, path);
        final ConcurrentMap nodes = etcd.readDir(path, true);
        final Set sets = new HashSet<>();

        Observable.fromIterable(nodes.entrySet())
                .filter(Objects::nonNull)
                .filter(item -> Objects.nonNull(item.getKey()) && Objects.nonNull(item.getValue()))
                .filter(item -> Etat.RUNNING == Ut.toEnum(Etat.class, item.getValue()))
                .map(Map.Entry::getKey)
                .subscribe(sets::add).dispose();
        return sets;
    }

    public void erasingStatus(final String name,
                              final String host,
                              final Integer port,
                              final EtcdPath path) {
        final String target = MessageFormat.format(PATH_STATUS, etcd.getApplication(),
                path.toString().toLowerCase(), name,
                host, String.valueOf(port));
        logger.info(Info.ETCD_CLEAN, name, path);
        etcd.write(target, Etat.STOPPED, Values.ZERO);
    }

    public void registryHttp(final String service,
                             final HttpServerOptions options, final Etat etat) {
        final String path = MessageFormat.format(PATH_STATUS, etcd.getApplication(),
                EtcdPath.ENDPOINT.toString().toLowerCase(), service,
                Ut.netIPv4(), String.valueOf(options.getPort()));
        logger.info(Info.ETCD_STATUS, service, etat, path);
        etcd.write(path, etat, Values.ZERO);
    }

    public void registryRpc(final ServidorOptions options, final Etat etat) {
        final String path = MessageFormat.format(PATH_STATUS, etcd.getApplication(),
                EtcdPath.IPC.toString().toLowerCase(), options.getName(),
                Ut.netIPv4(), String.valueOf(options.getPort()));
        logger.info(Info.ETCD_STATUS, options.getName(), etat, path);
        etcd.write(path, etat, Values.ZERO);
    }

    public void registryIpcs(final ServidorOptions options, final Set ipcs) {
        final String path = MessageFormat.format(ROUTE_TREE, etcd.getApplication(),
                EtcdPath.IPC.toString().toLowerCase(),
                MessageFormat.format("{0}:{1}:{2}", options.getName(),
                        Ut.netIPv4(), String.valueOf(options.getPort())));
        final String host = Ut.netIPv4();
        final String endpoint = MessageFormat.format("grpc://{0}:{1}",
                host,
                String.valueOf(options.getPort()));
        // Screen Information
        final StringBuilder builder = new StringBuilder();
        for (final String ipc : ipcs) {
            builder.append("\n\t[ Up Rpc √ ] \t").append(ipc);
        }
        logger.info(Info.ETCD_IPCS, etcd.getApplication(),
                path, options.getName(), endpoint, builder.toString());
        // Build Data
        final JsonArray routeData = new JsonArray();
        Observable.fromIterable(ipcs)
                .subscribe(routeData::add).dispose();
        etcd.write(path, routeData, Values.ZERO);
    }

    public void registryRoute(final String name,
                              final HttpServerOptions options, final Set routes) {
        /*
         * Console information for report micro service.
         */
        final String path = MessageFormat.format(ROUTE_TREE, etcd.getApplication(),
                EtcdPath.ENDPOINT.toString().toLowerCase(),
                MessageFormat.format("{0}:{1}:{2}", name,
                        Ut.netIPv4(), String.valueOf(options.getPort())));
        final String host = Ut.netIPv4();
        final String endpoint = MessageFormat.format("http://{0}:{1}",
                host,
                String.valueOf(options.getPort()));
        /*
         * Sort naturally
         */
        final Set processed = new TreeSet<>();
        routes.stream().filter(route -> !DEFAULTS.contains(route))
                .forEach(processed::add);
        /*
         * Scan configuration file and capture plug-in data
         */
        PluginExtension.ZeroRegistry.registryRoute(processed);

        // Screen Information
        final StringBuilder builder = new StringBuilder();
        for (final String route : processed) {
            builder.append("\n\t[ Up Micro ] \t").append(route);
        }
        logger.info(Info.ETCD_ROUTE, etcd.getApplication(),
                path, name, endpoint, builder.toString());

        // Build Data
        final JsonArray routeData = new JsonArray();
        Observable.fromIterable(processed)
                .subscribe(routeData::add).dispose();
        etcd.write(path, routeData, Values.ZERO);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy