use of services.moleculer.context.Context in project moleculer-java by moleculer-java.
the class DefaultCircuitBreaker method callWithoutBreaker.
// --- CALL SERVICE WITHOUT BREAKER FUNCTION ---
protected Promise callWithoutBreaker(String name, Tree params, CallOptions.Options opts, int remaining, Context parent) {
try {
String targetID = opts == null ? null : opts.nodeID;
Action action = serviceRegistry.getAction(name, targetID);
Context ctx = contextFactory.create(name, params, opts, parent);
if (remaining < 1) {
return Promise.resolve(action.handler(ctx));
}
return Promise.resolve(action.handler(ctx)).catchError(cause -> {
return retryWithoutBreaker(cause, name, params, opts, remaining, parent);
});
} catch (Throwable cause) {
if (remaining < 1) {
return Promise.reject(cause);
}
return retryWithoutBreaker(cause, name, params, opts, remaining, parent);
}
}
use of services.moleculer.context.Context in project moleculer-java by moleculer-java.
the class Cacher method install.
// --- ADD MIDDLEWARE TO ACTION ---
@Override
public Action install(Action action, Tree config) {
// Is caching enabled?
Tree cacheNode = config.get("cache");
if (cacheNode == null) {
return null;
}
// Get cache keys
Tree keyNode = cacheNode.get("keys");
final String[] keys;
if (keyNode == null) {
keys = null;
} else {
List<String> list = keyNode.asList(String.class);
if (list.isEmpty()) {
keys = null;
} else {
keys = new String[list.size()];
list.toArray(keys);
}
}
// Get TTL (0 = use default TTL)
final int ttl = cacheNode.get("ttl", 0);
return new Action() {
@Override
public Object handler(Context ctx) throws Exception {
String key = getCacheKey(ctx.name, ctx.params, keys);
return new Promise(resolver -> {
get(key).then(in -> {
if (in == null || in.isNull()) {
new Promise(action.handler(ctx)).then(tree -> {
set(key, tree, ttl);
resolver.resolve(tree);
}).catchError(err -> {
resolver.reject(err);
});
} else {
resolver.resolve(in);
}
}).catchError(err -> {
resolver.reject(err);
});
});
}
};
}
use of services.moleculer.context.Context in project moleculer-java by moleculer-java.
the class Sample method main.
public static void main(String[] args) throws Exception {
System.out.println("START");
try {
ServiceBrokerConfig cfg = new ServiceBrokerConfig();
// RedisTransporter t = new RedisTransporter();
// t.setDebug(false);
// cfg.setTransporter(t);
ServiceBroker broker = new ServiceBroker(cfg);
MathService math = new MathService();
broker.createService(math);
broker.start();
broker.use(new Middleware() {
@Override
public Action install(Action action, Tree config) {
if (config.get("name", "?").equals("v1.math.test")) {
return new Action() {
@Override
public Object handler(Context ctx) throws Exception {
Object original = action.handler(ctx);
Object replaced = System.currentTimeMillis();
broker.getLogger().info("Middleware invoked! Replacing " + original + " to " + replaced);
return replaced;
}
};
}
return null;
}
});
broker.waitForServices("v1.math").then(ok -> {
for (int i = 0; i < 2; i++) {
broker.call("v1.math.add", "a", 3, "b", 5).then(in -> {
broker.getLogger(Sample.class).info("Result: " + in);
}).catchError(err -> {
broker.getLogger(Sample.class).error("Error: " + err);
});
}
System.out.println("FIRST CALL ->3");
broker.call("service2.test", new Tree(), CallOptions.retryCount(3)).catchError(cause -> {
cause.printStackTrace();
});
});
((DefaultContextFactory) broker.getConfig().getContextFactory()).setMaxCallLevel(3);
Thread.sleep(1000);
broker.createService(new Service2Service());
Thread.sleep(1000);
broker.createService(new Service3Service());
Thread.sleep(60000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("STOP");
}
use of services.moleculer.context.Context 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));
}
}
use of services.moleculer.context.Context in project moleculer-java by moleculer-java.
the class DefaultCircuitBreaker method callWithBreaker.
// --- CALL SERVICE WITH BREAKER FUNCTION ---
protected Promise callWithBreaker(String name, Tree params, CallOptions.Options opts, int remaining, Context parent) {
EndpointKey endpointKey = null;
ErrorCounter errorCounter = null;
try {
// Get the first recommended Endpoint and Error Counter
String targetID = opts == null ? null : opts.nodeID;
ActionEndpoint action = (ActionEndpoint) serviceRegistry.getAction(name, targetID);
String nodeID = action.getNodeID();
endpointKey = new EndpointKey(nodeID, name);
errorCounter = errorCounters.get(endpointKey);
// Check availability of the Endpoint (if endpoint isn't targetted)
if (targetID == null) {
LinkedHashSet<String> nodeIDs = new LinkedHashSet<>(maxSameNodes * 2);
int sameNodeCounter = 0;
long now;
if (errorCounter == null) {
now = 0;
} else {
now = System.currentTimeMillis();
}
for (int i = 0; i < maxTries; i++) {
if (errorCounter == null || errorCounter.isAvailable(now)) {
// Endpoint is available
break;
}
// Store nodeID
if (!nodeIDs.add(nodeID)) {
sameNodeCounter++;
if (sameNodeCounter >= maxSameNodes) {
// The "maxSameNodes" limit is reached
break;
}
}
// Try to choose another endpoint
action = (ActionEndpoint) serviceRegistry.getAction(name, targetID);
nodeID = action.getNodeID();
endpointKey = new EndpointKey(nodeID, name);
errorCounter = errorCounters.get(endpointKey);
}
}
// Create new Context
Context ctx = contextFactory.create(name, params, opts, parent);
// Invoke Endpoint
final ErrorCounter currentCounter = errorCounter;
final EndpointKey currentKey = endpointKey;
return Promise.resolve(action.handler(ctx)).then(rsp -> {
// Reset error counter
if (currentCounter != null) {
currentCounter.reset();
}
// Return response
return rsp;
}).catchError(cause -> {
// Increment error counter
increment(currentCounter, currentKey, cause, System.currentTimeMillis());
// Return with error
if (remaining < 1) {
return cause;
}
// Retry
return retryWithBreaker(cause, name, params, opts, remaining, parent);
});
} catch (Throwable cause) {
// Increment error counter
increment(errorCounter, endpointKey, cause, System.currentTimeMillis());
// Reject
if (remaining < 1) {
return Promise.reject(cause);
}
// Retry
return retryWithBreaker(cause, name, params, opts, remaining, parent);
}
}
Aggregations