use of io.datatree.Tree in project moleculer-java by moleculer-java.
the class TcpTransporter method received.
// --- MESSAGE RECEIVED ---
public void received(byte packetID, byte[] packet) {
executor.execute(() -> {
// Parse message
Tree data;
try {
data = serializer.read(packet);
} catch (Exception cause) {
logger.warn("Unable to parse incoming message!", cause);
return;
}
// Send message to proper component
try {
switch(packetID) {
case PACKET_EVENT_ID:
// Incoming event
if (debug) {
logger.info("Event message received:\r\n" + data);
}
eventbus.receiveEvent(data);
return;
case PACKET_REQUEST_ID:
// Incoming request
if (debug) {
logger.info("Request message received:\r\n" + data);
}
registry.receiveRequest(data);
return;
case PACKET_RESPONSE_ID:
// Incoming response
if (debug) {
logger.info("Response message received:\r\n" + data);
}
registry.receiveResponse(data);
return;
case PACKET_PING_ID:
// Send pong
if (debug) {
logger.info("Ping message received:\r\n" + data);
}
String id = data.get("id", "");
if (id == null || id.isEmpty()) {
logger.warn("Missing \"id\" property:\r\n" + data);
return;
}
String sender = data.get("sender", "");
if (sender == null || sender.isEmpty()) {
logger.warn("Missing \"sender\" property:\r\n" + data);
return;
}
long time = data.get("time", 0L);
FastBuildTree msg = new FastBuildTree(5);
msg.putUnsafe("ver", PROTOCOL_VERSION);
msg.putUnsafe("sender", this.nodeID);
msg.putUnsafe("id", id);
msg.putUnsafe("received", time);
msg.putUnsafe("time", System.currentTimeMillis());
writer.send(sender, serialize(PACKET_PONG_ID, msg));
return;
case PACKET_PONG_ID:
// Pong received
if (debug) {
logger.info("Pong message received:\r\n" + data);
}
registry.receiveResponse(data);
return;
case PACKET_GOSSIP_REQ_ID:
// Incoming gossip request
processGossipRequest(data);
return;
case PACKET_GOSSIP_RSP_ID:
// Incoming gossip request
processGossipResponse(data);
return;
case PACKET_GOSSIP_HELLO_ID:
// Incoming "hello" message
processGossipHello(data);
return;
default:
logger.warn("Unsupported message ID (" + packetID + ")!");
}
} catch (Exception cause) {
logger.warn("Unable to process incoming message!", cause);
}
});
}
use of io.datatree.Tree in project moleculer-java by moleculer-java.
the class TcpWriter method run.
// --- WRITER LOOP ---
@Override
public void run() {
try {
// Loop
while (true) {
// Waiting for sockets
int n;
try {
n = selector.select(3000);
} catch (NullPointerException nullPointer) {
continue;
} catch (Exception cause) {
break;
}
// Open new connections
SendBuffer buffer = opened.poll();
SelectionKey key = null;
while (buffer != null) {
try {
InetSocketAddress address;
try {
address = new InetSocketAddress(buffer.host, buffer.port);
} catch (UnresolvedAddressException dnsError) {
// Workaround: unable to resolve host name
Tree info = transporter.getDescriptor(buffer.nodeID);
if (info == null) {
throw dnsError;
}
String ip = getHostOrIP(false, info);
if (ip == null || buffer.host.equalsIgnoreCase(ip)) {
throw dnsError;
}
if (debug) {
logger.info("Unable to resolve hostname \"" + buffer.host + "\", trying with \"" + ip + "\"...");
}
address = new InetSocketAddress(ip, buffer.port);
}
SocketChannel channel = SocketChannel.open(address);
channel.configureBlocking(false);
channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
channel.setOption(StandardSocketOptions.SO_LINGER, -1);
key = channel.register(selector, SelectionKey.OP_WRITE);
key.attach(buffer);
buffer.connected(key, channel);
if (debug) {
logger.info("Client channel opened to \"" + buffer.nodeID + "\".");
}
} catch (Throwable cause) {
if (buffer != null) {
synchronized (buffers) {
buffers.remove(buffer.nodeID);
}
transporter.unableToSend(buffer.nodeID, buffer.getUnsentPackets(), cause);
}
}
buffer = opened.poll();
}
if (n < 1) {
continue;
}
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
key = keys.next();
if (key == null) {
continue;
}
if (!key.isValid()) {
keys.remove();
continue;
}
if (key.isWritable()) {
// Write data
buffer = null;
try {
buffer = (SendBuffer) key.attachment();
if (buffer != null) {
buffer.write();
}
} catch (Exception cause) {
if (buffer != null) {
synchronized (buffers) {
buffers.remove(buffer.nodeID);
}
transporter.unableToSend(buffer.nodeID, buffer.getUnsentPackets(), cause);
}
close(key, cause);
}
}
keys.remove();
}
}
} catch (Exception fatal) {
logger.error("TCP writer closed!", fatal);
}
}
use of io.datatree.Tree in project moleculer-java by moleculer-java.
the class CommonUtils method parseURLs.
// --- PARSE URL LIST OR URL ARRAY ---
public static final String[] parseURLs(Tree config, String name, String[] defaultURLs) {
Tree urlNode = config.get(name);
List<String> urlList;
if (urlNode == null) {
return defaultURLs;
} else if (urlNode.isPrimitive()) {
urlList = new ArrayList<>();
String[] urls = urlNode.asString().split(",");
for (String url : urls) {
url = url.trim();
if (!url.isEmpty()) {
urlList.add(url);
}
}
} else if (urlNode.isEnumeration()) {
urlList = urlNode.asList(String.class);
} else {
return defaultURLs;
}
if (urlList.isEmpty()) {
return defaultURLs;
}
String[] urls = new String[urlList.size()];
urlList.toArray(urls);
return urls;
}
use of io.datatree.Tree in project moleculer-java by moleculer-java.
the class CommonUtils method parseParams.
// --- PARSE CALL / BROADCAST PARAMS ---
public static final ParseResult parseParams(Object[] params) {
Tree data = null;
CallOptions.Options opts = null;
Groups groups = null;
if (params != null) {
if (params.length == 1) {
if (params[0] instanceof Tree) {
data = (Tree) params[0];
} else {
data = new CheckedTree(params[0]);
}
} else {
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
String prev = null;
Object value;
for (int i = 0; i < params.length; i++) {
value = params[i];
if (prev == null) {
if (!(value instanceof String)) {
if (value instanceof CallOptions.Options) {
opts = (CallOptions.Options) value;
continue;
}
if (value instanceof Groups) {
groups = (Groups) value;
continue;
}
i++;
throw new IllegalArgumentException("Parameter #" + i + " (\"" + value + "\") must be String, Context, Groups, or CallOptions!");
}
prev = (String) value;
continue;
}
map.put(prev, value);
prev = null;
}
data = new Tree(map);
}
}
return new ParseResult(data, opts, groups);
}
use of io.datatree.Tree in project moleculer-java by moleculer-java.
the class CircuitBreakerTest method testRoundRobin.
@Test
public void testRoundRobin() throws Exception {
// Simple round-robin test
currentID = 1;
for (int i = 0; i < 20; i++) {
Promise p = br.call("test.test", (Tree) null);
assertTrue(tr.hasMessage(getCurrentID()));
assertEquals(1, tr.getMessageCount());
createResponse(true);
boolean ok = false;
try {
p.waitFor();
ok = true;
} catch (Exception e) {
}
assertTrue(ok);
}
// Create fault
Promise p = br.call("test.test", (Tree) null);
String nodeID = createResponse(false);
boolean ok = true;
try {
p.waitFor();
} catch (Exception e) {
ok = e.toString().contains("unknown error");
}
assertFalse(ok);
ErrorCounter ec = cb.errorCounters.get(new EndpointKey(nodeID, "test.test"));
assertNotNull(ec);
assertEquals(1, ec.pointer);
long now = ec.timestamps[0];
assertTrue(ec.isAvailable(now));
// Create faults2
p = br.call("test.test", (Tree) null);
nodeID = createResponse(false);
try {
p.waitFor();
ok = true;
} catch (Exception e) {
ok = e.toString().contains("unknown error");
}
assertFalse(ok);
ec = cb.errorCounters.get(new EndpointKey(nodeID, "test.test"));
assertNotNull(ec);
assertEquals(1, ec.pointer);
// Create fault
int node1Count = 0;
for (int i = 0; i < 30; i++) {
p = br.call("test.test", (Tree) null);
nodeID = createResponse(false);
now = System.currentTimeMillis();
try {
p.waitFor();
ok = true;
} catch (Exception e) {
ok = e.toString().contains("unknown error");
}
assertFalse(ok);
if (nodeID.equals("node0")) {
node1Count++;
ec = cb.errorCounters.get(new EndpointKey(nodeID, "test.test"));
assertNotNull(ec);
if (node1Count < 3) {
if (node1Count == 1) {
assertTrue(ec.timestamps[0] == 0);
assertTrue(ec.timestamps[1] > 0);
assertTrue(ec.timestamps[2] == 0);
} else if (node1Count == 2) {
assertTrue(ec.timestamps[0] == 0);
assertTrue(ec.timestamps[1] > 0);
assertTrue(ec.timestamps[2] > 0);
}
assertTrue(ec.isAvailable(now));
} else {
assertTrue(ec.timestamps[0] > 0);
assertTrue(ec.timestamps[1] > 0);
assertTrue(ec.timestamps[2] > 0);
assertFalse(ec.isAvailable(now));
}
}
}
// All endpoint is locked
for (EndpointKey key : cb.errorCounters.keySet()) {
ec = cb.errorCounters.get(key);
boolean avail = ec.isAvailable(now);
assertFalse(avail);
}
// Retrying once
now += 10001;
assertTrue(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
// + 5 sec
now += 5000;
assertFalse(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
// + 10 sec (5000 + 5001)
now += 5001;
assertTrue(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
assertFalse(ec.isAvailable(now));
}
Aggregations