Search in sources :

Example 11 with Tree

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

the class DefaultServiceRegistry method ping.

// --- PING / PONG HANDLING ---
@Override
public Promise ping(long timeoutMillis, String nodeID) {
    // Create new promise
    Promise promise = new Promise();
    // Set timeout
    long timeoutAt;
    if (timeoutMillis > 0) {
        timeoutAt = System.currentTimeMillis() + timeoutMillis;
    } else {
        timeoutAt = 0;
    }
    // Register promise (timeout and response handling)
    String id = uid.nextUID();
    register(id, promise, timeoutAt);
    // Send request via transporter
    Tree message = transporter.createPingPacket(id);
    transporter.publish(Transporter.PACKET_PING, nodeID, message);
    // Return promise
    return promise;
}
Also used : Promise(services.moleculer.Promise) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 12 with Tree

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

the class DefaultServiceRegistry method receiveResponse.

// --- RECEIVE RESPONSE FROM REMOTE SERVICE ---
@Override
public void receiveResponse(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 response's unique ID
    String id = message.get("id", (String) null);
    if (id == null || id.isEmpty()) {
        logger.warn("Missing \"id\" property!", message);
        return;
    }
    // Get stored promise
    PendingPromise pending = promises.remove(id);
    if (pending == null) {
        logger.warn("Unknown (maybe timeouted) response received!", message);
        return;
    }
    try {
        // Get response status (successed or not?)
        boolean success = message.get("success", true);
        if (success) {
            // Ok -> resolve
            pending.promise.complete(message.get("data"));
        } else {
            // Failed -> reject
            Tree error = message.get("error");
            String errorMessage = null;
            String trace = null;
            if (error != null) {
                errorMessage = error.get("message", (String) null);
                trace = error.get("trace", (String) null);
                if (trace != null && !trace.isEmpty()) {
                    logger.error("Remote invaction failed!\r\n" + trace);
                }
            }
            if (errorMessage == null || errorMessage.isEmpty()) {
                errorMessage = "Unknow error!";
            }
            if (trace == null || trace.isEmpty()) {
                logger.error("Remote invoction failed (unknown error occured)!");
            }
            pending.promise.complete(new RemoteException(errorMessage));
            return;
        }
    } catch (Throwable cause) {
        logger.error("Unable to pass on incoming response!", cause);
    }
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree) RemoteException(java.rmi.RemoteException)

Example 13 with Tree

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

the class DefaultServiceRegistry method addOnlineActions.

protected void addOnlineActions(String serviceName, Service service) {
    // Service name with version
    if (serviceName == null || serviceName.isEmpty()) {
        serviceName = service.getName();
    }
    serviceName = serviceName.replace(' ', '-');
    Class<? extends Service> clazz = service.getClass();
    Field[] fields = clazz.getFields();
    int actionCounter = 0;
    writeLock.lock();
    try {
        // Initialize actions in service
        for (Field field : fields) {
            if (!Action.class.isAssignableFrom(field.getType())) {
                continue;
            }
            field.setAccessible(true);
            Action action = (Action) field.get(service);
            // Name of the action (eg. "service.action")
            String actionName = nameOf(serviceName, field);
            Tree actionConfig = new Tree();
            actionConfig.put("name", actionName);
            Annotation[] annotations = field.getAnnotations();
            convertAnnotations(actionConfig, annotations);
            // Register action
            LocalActionEndpoint endpoint = new LocalActionEndpoint(nodeID, actionConfig, action);
            Strategy<ActionEndpoint> actionStrategy = strategies.get(actionName);
            if (actionStrategy == null) {
                // Create strategy
                actionStrategy = strategyFactory.create();
                strategies.put(actionName, actionStrategy);
            }
            actionStrategy.addEndpoint(endpoint);
            // Apply middlewares
            for (Middleware middleware : middlewares) {
                endpoint.use(middleware);
            }
            // Write log about this action
            logger.info("Action \"" + actionName + "\" registered.");
            actionCounter++;
        }
        services.put(serviceName, service);
        service.started(broker);
    } catch (Exception cause) {
        logger.error("Unable to register local service!", cause);
        return;
    } finally {
        // Delete cached node descriptor
        clearDescriptorCache();
        writeLock.unlock();
    }
    // Notify local listeners about the new LOCAL service
    broadcastServicesChanged(true);
    // Write log about this service
    StringBuilder msg = new StringBuilder(64);
    msg.append("Service \"");
    msg.append(serviceName);
    msg.append("\" started ");
    if (actionCounter == 0) {
        msg.append("without any actions.");
    } else if (actionCounter == 1) {
        msg.append("with 1 action.");
    } else {
        msg.append("with ");
        msg.append(actionCounter);
        msg.append(" actions.");
    }
    logger.info(msg.toString());
}
Also used : Annotation(java.lang.annotation.Annotation) TimeoutException(java.util.concurrent.TimeoutException) NoSuchElementException(java.util.NoSuchElementException) RemoteException(java.rmi.RemoteException) Field(java.lang.reflect.Field) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 14 with Tree

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

the class DefaultServiceRegistry method broadcastServicesChanged.

// --- NOTIFY OTHER SERVICES ---
protected void broadcastServicesChanged(boolean local) {
    Tree message = new Tree();
    message.put("localService", true);
    eventbus.broadcast("$services.changed", message, null, true);
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

Example 15 with Tree

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

the class TcpTransporter method processGossipRequest.

// --- GOSSIP REQUEST MESSAGE RECEIVED ---
protected Tree processGossipRequest(Tree data) throws Exception {
    // Debug
    String sender = data.get("sender", (String) null);
    if (debug) {
        logger.info("Gossip request received from \"" + sender + "\" node:\r\n" + data);
    }
    // Add "online" and "offline" response blocks
    LinkedList<NodeDescriptor> allNodes = new LinkedList<>(nodes.values());
    NodeDescriptor descriptor = getDescriptor();
    allNodes.add(descriptor);
    int size = allNodes.size() + 1;
    FastBuildTree onlineRsp = new FastBuildTree(size);
    FastBuildTree offlineRsp = new FastBuildTree(size);
    // Online / offline nodes in request
    Tree onlineReq = data.get("online");
    Tree offlineReq = data.get("offline");
    // Loop in nodes
    LinkedList<NodeDescriptor> disconnectedNodes = new LinkedList<>();
    for (NodeDescriptor node : allNodes) {
        node.writeLock.lock();
        try {
            Tree online = onlineReq == null ? null : onlineReq.get(node.nodeID);
            Tree offline = offlineReq == null ? null : offlineReq.get(node.nodeID);
            // Online or offline sequence number
            long seq = 0;
            // CPU data
            long cpuSeq = 0;
            int cpu = 0;
            if (offline != null) {
                if (!offline.isPrimitive()) {
                    logger.warn("Invalid \"offline\" block: " + offline.toString(false));
                    continue;
                }
                seq = offline.asLong();
            } else if (online != null) {
                if (!online.isEnumeration() || online.size() != 3) {
                    logger.warn("Invalid \"online\" block: " + online.toString(false));
                    continue;
                }
                seq = online.get(0).asLong();
                cpuSeq = online.get(1).asLong();
                cpu = online.get(2).asInteger();
            }
            if ((seq == 0 || seq < node.seq) && node.seq > 0) {
                // We have newer info or requester doesn't know it
                if (node.offlineSince == 0) {
                    if (!node.info.isEmpty()) {
                        if ((cpuSeq == 0 || cpuSeq < node.cpuSeq) && node.cpuSeq > 0) {
                            ArrayList<Object> array = new ArrayList<>(3);
                            array.add(node.info.asObject());
                            array.add(node.cpuSeq);
                            array.add(node.cpu);
                            onlineRsp.putUnsafe(node.nodeID, array);
                        } else {
                            onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                        }
                    }
                } else {
                    offlineRsp.putUnsafe(node.nodeID, node.seq);
                }
            }
            if (offline != null) {
                // Requester said it is OFFLINE
                if (node.offlineSince > 0) {
                    // We also knew it as offline
                    node.markAsOffline(seq);
                    continue;
                }
                if (!node.local) {
                    if (node.offlineSince == 0) {
                        // We know it is online, so we change it to offline
                        if (node.markAsOffline(seq)) {
                            // Remove remote actions and listeners
                            registry.removeActions(node.nodeID);
                            eventbus.removeListeners(node.nodeID);
                            writer.close(node.nodeID);
                            disconnectedNodes.add(node);
                        } else if (seq == node.seq) {
                            // We send back that this node is online
                            node.seq = seq + 1;
                            node.info.put("seq", node.seq);
                            if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                                ArrayList<Object> array = new ArrayList<>(3);
                                array.add(node.info.asObject());
                                array.add(node.cpuSeq);
                                array.add(node.cpu);
                                onlineRsp.putUnsafe(node.nodeID, array);
                            } else {
                                onlineRsp.putUnsafe(node.nodeID, Collections.singletonList(node.info.asObject()));
                            }
                        }
                    }
                    continue;
                }
            } else if (online != null) {
                // Requester said it is ONLINE
                if (node.offlineSince == 0) {
                    if (cpuSeq > node.cpuSeq) {
                        // We update our CPU info
                        node.updateCpu(cpuSeq, cpu);
                    } else if (cpuSeq < node.cpuSeq && node.cpuSeq > 0) {
                        // We have newer CPU value, send back
                        ArrayList<Object> array = new ArrayList<>(2);
                        array.add(node.cpuSeq);
                        array.add(node.cpu);
                        onlineRsp.putUnsafe(node.nodeID, array);
                    }
                } else {
                    // request it and we'll receive its INFO
                    continue;
                }
            }
        } finally {
            node.writeLock.unlock();
        }
    }
    // Create gossip response
    FastBuildTree root = new FastBuildTree(4);
    root.putUnsafe("ver", ServiceBroker.PROTOCOL_VERSION);
    root.putUnsafe("sender", nodeID);
    // Remove empty blocks
    boolean emptyOnlineBlock = onlineRsp.isEmpty();
    boolean emptyOfflineBlock = offlineRsp.isEmpty();
    if (emptyOnlineBlock && emptyOfflineBlock) {
        // Message is empty
        return root;
    }
    if (!emptyOnlineBlock) {
        root.putUnsafe("online", onlineRsp.asObject());
    }
    if (!emptyOfflineBlock) {
        root.putUnsafe("offline", offlineRsp.asObject());
    }
    // Debug
    if (debug) {
        logger.info("Gossip response submitting to \"" + sender + "\" node:\r\n" + root);
    }
    // Serialize response
    byte[] packet = serialize(PACKET_GOSSIP_RSP_ID, root);
    // Send response
    writer.send(sender, packet);
    // Notify listeners (unexpected disconnection)
    for (NodeDescriptor node : disconnectedNodes) {
        logger.info("Node \"" + node.nodeID + "\" disconnected.");
        broadcastNodeDisconnected(node.info, true);
    }
    // For unit testing
    return root;
}
Also used : FastBuildTree(services.moleculer.util.FastBuildTree) NodeDescriptor(services.moleculer.transporter.tcp.NodeDescriptor) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) CommonUtils.readTree(services.moleculer.util.CommonUtils.readTree) FastBuildTree(services.moleculer.util.FastBuildTree) Tree(io.datatree.Tree)

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