Search in sources :

Example 41 with Tree

use of io.datatree.Tree in project moleculer-java by moleculer-java.

the class TcpTransporter method processGossipResponse.

// --- GOSSIP RESPONSE MESSAGE RECEIVED ---
protected void processGossipResponse(Tree data) throws Exception {
    // Debug
    if (debug) {
        String sender = data.get("sender", (String) null);
        logger.info("Gossip response received from \"" + sender + "\" node:\r\n" + data);
    }
    // Online / offline nodes in responnse
    Tree online = data.get("online");
    Tree offline = data.get("offline");
    // Process "online" block
    if (online != null) {
        for (Tree row : online) {
            // Get nodeID
            String nodeID = row.getName();
            if (this.nodeID.equals(nodeID)) {
                continue;
            }
            int size = row.size();
            if (!row.isEnumeration() || size < 1 || size > 3) {
                logger.warn("Invalid \"offline\" block: " + row);
                continue;
            }
            // Get parameters from input
            Tree info = null;
            long cpuSeq = 0;
            int cpu = 0;
            if (row.size() == 1) {
                info = row.get(0);
            } else if (row.size() == 2) {
                cpuSeq = row.get(0).asLong();
                cpu = row.get(1).asInteger();
            } else if (row.size() == 3) {
                info = row.get(0);
                cpuSeq = row.get(1).asLong();
                cpu = row.get(2).asInteger();
            } else {
                logger.warn("Invalid \"online\" block: " + row.toString(false));
                continue;
            }
            if (info != null) {
                // Update "info" block,
                // send updated, connected or reconnected event
                updateNodeInfo(nodeID, info);
            }
            if (cpuSeq > 0) {
                // We update our CPU info
                NodeDescriptor node = nodes.get(nodeID);
                if (node != null) {
                    node.writeLock.lock();
                    try {
                        node.updateCpu(cpuSeq, cpu);
                    } finally {
                        node.writeLock.unlock();
                    }
                }
            }
        }
    }
    // Process "offline" block
    if (offline != null) {
        for (Tree row : offline) {
            String nodeID = row.getName();
            NodeDescriptor node;
            if (this.nodeID.equals(nodeID)) {
                long seq = row.asLong();
                node = getDescriptor();
                node.writeLock.lock();
                try {
                    long newSeq = Math.max(node.seq, seq + 1);
                    if (node.seq < newSeq) {
                        node.seq = newSeq;
                        node.info.put("seq", newSeq);
                    }
                } finally {
                    node.writeLock.unlock();
                }
                continue;
            }
            node = nodes.get(nodeID);
            if (node == null) {
                return;
            }
            if (!row.isPrimitive()) {
                logger.warn("Invalid \"offline\" block: " + row);
                continue;
            }
            // Get parameters from input
            boolean disconnected = false;
            node.writeLock.lock();
            try {
                long seq = row.asLong();
                if (node.seq < seq && node.markAsOffline(seq)) {
                    // We know it is online, so we change it to offline
                    // Remove remote actions and listeners
                    registry.removeActions(node.nodeID);
                    eventbus.removeListeners(node.nodeID);
                    writer.close(node.nodeID);
                    disconnected = true;
                }
            } finally {
                node.writeLock.unlock();
            }
            if (node != null && disconnected) {
                // Notify listeners (not unexpected disconnection)
                logger.info("Node \"" + node.nodeID + "\" disconnected.");
                broadcastNodeDisconnected(node.info, false);
            }
        }
    }
}
Also used : NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 42 with Tree

use of io.datatree.Tree in project moleculer-java by moleculer-java.

the class TcpTransporter method registerAsNewNode.

protected void registerAsNewNode(String sender, String host, int port) {
    // Check node
    if (sender == null || sender.isEmpty()) {
        throw new IllegalArgumentException("Empty sender field!");
    }
    if (host == null || host.isEmpty()) {
        throw new IllegalArgumentException("Empty host field!");
    }
    if (port < 1) {
        throw new IllegalArgumentException("Invalid port value (" + port + ")!");
    }
    if (nodeID.equalsIgnoreCase(sender)) {
        return;
    }
    NodeDescriptor node = nodes.get(sender);
    if (node == null) {
        // Add as new, offline node
        try {
            nodes.put(sender, new NodeDescriptor(sender, useHostname, host, port));
            logger.info("Node \"" + sender + "\" registered.");
        } catch (Exception cause) {
            logger.warn("Unable to register new node!", cause);
        }
    } else {
        node.writeLock.lock();
        try {
            // Host or port number changed
            if (!node.host.equalsIgnoreCase(host) || node.port != port) {
                node.host = host;
                node.port = port;
                if (node.info != null) {
                    if (useHostname) {
                        node.info.put("hostname", host);
                    } else {
                        Tree ipList = node.info.get("ipList");
                        if (ipList == null) {
                            ipList = node.info.putList("ipList");
                        } else {
                            ipList.clear();
                        }
                        ipList.add(host);
                    }
                    node.info.put("port", port);
                }
                writer.close(sender);
            }
        } finally {
            node.writeLock.unlock();
        }
    }
}
Also used : NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 43 with Tree

use of io.datatree.Tree in project moleculer-java by moleculer-java.

the class DefaultServiceRegistry method addActions.

// --- ADD A REMOTE SERVICE ---
@Override
public void addActions(Tree config) {
    Tree actions = config.get("actions");
    if (actions != null && actions.isMap()) {
        String nodeID = Objects.requireNonNull(config.get("nodeID", (String) null));
        writeLock.lock();
        try {
            for (Tree actionConfig : actions) {
                actionConfig.putObject("nodeID", nodeID, true);
                String actionName = actionConfig.get("name", "");
                // Register remote action
                RemoteActionEndpoint endpoint = new RemoteActionEndpoint(this, transporter, nodeID, actionConfig);
                Strategy<ActionEndpoint> actionStrategy = strategies.get(actionName);
                if (actionStrategy == null) {
                    actionStrategy = strategyFactory.create();
                    strategies.put(actionName, actionStrategy);
                }
                actionStrategy.addEndpoint(endpoint);
            }
        } finally {
            writeLock.unlock();
        }
        // Notify local listeners about the new REMOTE service
        broadcastServicesChanged(false);
    }
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 44 with Tree

use of io.datatree.Tree in project moleculer-java by moleculer-java.

the class DefaultServiceRegistry method receiveRequest.

// --- RECEIVE REQUEST FROM REMOTE SERVICE ---
@Override
public void receiveRequest(Tree message) {
    // Verify protocol version
    if (checkVersion) {
        String ver = message.get("ver", "unknown");
        if (!ServiceBroker.PROTOCOL_VERSION.equals(ver)) {
            logger.warn("Invalid protocol version (" + ver + ")!");
            return;
        }
    }
    // Get action property
    String action = message.get("action", (String) null);
    if (action == null || action.isEmpty()) {
        logger.warn("Missing \"action\" property!");
        return;
    }
    // Get strategy (action endpoint array) by action name
    Strategy<ActionEndpoint> strategy;
    readLock.lock();
    try {
        strategy = strategies.get(action);
    } finally {
        readLock.unlock();
    }
    if (strategy == null) {
        logger.warn("Invalid action name (" + action + ")!");
        return;
    }
    // Get local action endpoint (with cache handling)
    ActionEndpoint endpoint = strategy.getEndpoint(nodeID);
    if (endpoint == null) {
        logger.warn("Not a local action (" + action + ")!");
        return;
    }
    // Get request's unique ID
    String id = message.get("id", (String) null);
    if (id == null || id.isEmpty()) {
        logger.warn("Missing \"id\" property!");
        return;
    }
    // Get sender's nodeID
    String sender = message.get("sender", (String) null);
    if (sender == null || sender.isEmpty()) {
        logger.warn("Missing \"sender\" property!");
        return;
    }
    // Create CallOptions
    int timeout = message.get("timeout", 0);
    Tree params = message.get("params");
    // TODO Process other properties:
    // Tree meta = message.get("meta");
    // int level = message.get("level", 1);
    // boolean metrics = message.get("metrics", false);
    // String parentID = message.get("parentID", (String) null);
    // String requestID = message.get("requestID", (String) null);
    CallOptions.Options opts = CallOptions.nodeID(nodeID).timeout(timeout);
    Context ctx = contextFactory.create(action, params, opts, null);
    // Invoke action
    try {
        new Promise(endpoint.handler(ctx)).then(data -> {
            // Send response
            FastBuildTree msg = new FastBuildTree(5);
            msg.putUnsafe("sender", nodeID);
            msg.putUnsafe("id", id);
            msg.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
            msg.putUnsafe("success", true);
            msg.putUnsafe("data", data);
            transporter.publish(Transporter.PACKET_RESPONSE, sender, msg);
        }).catchError(error -> {
            // Send error
            transporter.publish(Transporter.PACKET_RESPONSE, sender, throwableToTree(id, sender, error));
        });
    } catch (Throwable error) {
        // Send error
        transporter.publish(Transporter.PACKET_RESPONSE, sender, throwableToTree(id, sender, error));
    }
}
Also used : Context(services.moleculer.context.Context) CallOptions(services.moleculer.context.CallOptions) Arrays(java.util.Arrays) ScheduledFuture(java.util.concurrent.ScheduledFuture) Enumeration(java.util.Enumeration) FastBuildTree(services.moleculer.util.FastBuildTree) CommonUtils.convertAnnotations(services.moleculer.util.CommonUtils.convertAnnotations) TimeoutException(java.util.concurrent.TimeoutException) HashMap(java.util.HashMap) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) AtomicReference(java.util.concurrent.atomic.AtomicReference) ServiceBroker(services.moleculer.ServiceBroker) InetAddress(java.net.InetAddress) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ContextFactory(services.moleculer.context.ContextFactory) LinkedList(java.util.LinkedList) NoSuchElementException(java.util.NoSuchElementException) ServiceBrokerConfig(services.moleculer.config.ServiceBrokerConfig) CommonUtils.getHostName(services.moleculer.util.CommonUtils.getHostName) LinkedHashSet(java.util.LinkedHashSet) PrintWriter(java.io.PrintWriter) Eventbus(services.moleculer.eventbus.Eventbus) Iterator(java.util.Iterator) StringWriter(java.io.StringWriter) Collection(java.util.Collection) NetworkInterface(java.net.NetworkInterface) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) UIDGenerator(services.moleculer.uid.UIDGenerator) Field(java.lang.reflect.Field) RemoteException(java.rmi.RemoteException) Promise(services.moleculer.Promise) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) Lock(java.util.concurrent.locks.Lock) Strategy(services.moleculer.strategy.Strategy) Tree(io.datatree.Tree) Transporter(services.moleculer.transporter.Transporter) Annotation(java.lang.annotation.Annotation) Context(services.moleculer.context.Context) StrategyFactory(services.moleculer.strategy.StrategyFactory) CommonUtils.nameOf(services.moleculer.util.CommonUtils.nameOf) Collections(java.util.Collections) Promise(services.moleculer.Promise) FastBuildTree(services.moleculer.util.FastBuildTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree) CallOptions(services.moleculer.context.CallOptions)

Example 45 with Tree

use of io.datatree.Tree in project moleculer-java by moleculer-java.

the class DefaultServiceRegistry method currentDescriptor.

protected synchronized Tree currentDescriptor() {
    if (descriptor == null) {
        // Create new descriptor block
        descriptor = new Tree();
        // Services array
        Tree services = descriptor.putList("services");
        Tree servicesMap = new Tree();
        readLock.lock();
        try {
            for (Map.Entry<String, Strategy<ActionEndpoint>> entry : strategies.entrySet()) {
                // Split into parts ("math.add" -> "math" and "add")
                String name = entry.getKey();
                int i = name.lastIndexOf('.');
                String service = name.substring(0, i);
                // Get endpoint
                ActionEndpoint endpoint = entry.getValue().getEndpoint(nodeID);
                if (endpoint == null) {
                    continue;
                }
                // Service block
                Tree serviceMap = servicesMap.putMap(service, true);
                serviceMap.put("name", service);
                // Node ID
                serviceMap.put("nodeID", nodeID);
                // Action block
                @SuppressWarnings("unchecked") Map<String, Object> actionBlock = (Map<String, Object>) serviceMap.putMap("actions", true).asObject();
                actionBlock.put(name, endpoint.getConfig().asObject());
                // Listener block
                Tree listeners = eventbus.generateListenerDescriptor(service);
                if (listeners != null && !listeners.isEmpty()) {
                    serviceMap.putObject("events", listeners);
                }
            }
        } finally {
            readLock.unlock();
        }
        for (Tree service : servicesMap) {
            services.addObject(service);
        }
        // Host name
        descriptor.put("hostname", getHostName());
        // IP array
        Tree ipList = descriptor.putList("ipList");
        HashSet<String> ips = new HashSet<>();
        try {
            InetAddress local = InetAddress.getLocalHost();
            String defaultAddress = local.getHostAddress();
            if (!defaultAddress.startsWith("127.")) {
                ips.add(defaultAddress);
                ipList.add(defaultAddress);
            }
        } catch (Exception ignored) {
        }
        try {
            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
            while (e.hasMoreElements()) {
                NetworkInterface n = (NetworkInterface) e.nextElement();
                Enumeration<InetAddress> ee = n.getInetAddresses();
                while (ee.hasMoreElements()) {
                    InetAddress i = (InetAddress) ee.nextElement();
                    if (!i.isLoopbackAddress()) {
                        String test = i.getHostAddress();
                        if (ips.add(test)) {
                            ipList.add(test);
                        }
                    }
                }
            }
        } catch (Exception ignored) {
        }
        // Client descriptor
        Tree client = descriptor.putMap("client");
        client.put("type", "java");
        client.put("version", ServiceBroker.SOFTWARE_VERSION);
        client.put("langVersion", System.getProperty("java.version", "1.8"));
        // Config (not used in this version)
        // root.putMap("config");
        // Set timestamp
        timestamp.set(System.currentTimeMillis());
    }
    return descriptor;
}
Also used : NetworkInterface(java.net.NetworkInterface) TimeoutException(java.util.concurrent.TimeoutException) NoSuchElementException(java.util.NoSuchElementException) RemoteException(java.rmi.RemoteException) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree) Strategy(services.moleculer.strategy.Strategy) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) InetAddress(java.net.InetAddress) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Aggregations

Tree (io.datatree.Tree)60 FastBuildTree (services.moleculer.util.FastBuildTree)26 Test (org.junit.Test)12 NodeDescriptor (services.moleculer.transporter.tcp.NodeDescriptor)12 CheckedTree (services.moleculer.util.CheckedTree)9 TimeoutException (java.util.concurrent.TimeoutException)6 Promise (services.moleculer.Promise)6 CommonUtils.readTree (services.moleculer.util.CommonUtils.readTree)6 RemoteException (java.rmi.RemoteException)4 LinkedHashMap (java.util.LinkedHashMap)4 CallOptions (services.moleculer.context.CallOptions)4 Context (services.moleculer.context.Context)4 Annotation (java.lang.annotation.Annotation)3 HashSet (java.util.HashSet)3 LinkedHashSet (java.util.LinkedHashSet)3 Map (java.util.Map)3 NoSuchElementException (java.util.NoSuchElementException)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 ServiceBrokerConfig (services.moleculer.config.ServiceBrokerConfig)3 Action (services.moleculer.service.Action)3