use of services.moleculer.Promise in project moleculer-java by moleculer-java.
the class DefaultServiceRegistry method waitForServices.
@Override
public Promise waitForServices(long timeoutMillis, Collection<String> services) {
if (services == null || services.isEmpty() || isServicesOnline(services)) {
return Promise.resolve();
}
Promise promise = new Promise();
long timeoutAt;
if (timeoutMillis > 0) {
timeoutAt = System.currentTimeMillis() + timeoutMillis;
} else {
timeoutAt = 0;
}
ServiceListener listener = new ServiceListener(promise, timeoutAt, services);
synchronized (serviceListeners) {
serviceListeners.addLast(listener);
if (servicesOnlineTimer == null) {
servicesOnlineTimer = scheduler.scheduleWithFixedDelay(this::checkServicesOnline, 1, 1, TimeUnit.SECONDS);
}
}
return promise;
}
use of services.moleculer.Promise 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.Promise in project moleculer-java by moleculer-java.
the class RedisPubSubClient method disconnect.
// --- DISCONNECT ---
public final Promise disconnect() {
if (commands != null) {
commands.close();
commands = null;
}
LinkedList<Promise> threads = new LinkedList<>();
if (group != null) {
threads.add(new Promise(group.shutdownGracefully(1, 1, TimeUnit.SECONDS)));
}
if (resources != null) {
threads.add(new Promise(resources.shutdown()));
}
return Promise.all(threads).then(ok -> {
if (acceptor != null) {
acceptor.shutdownNow();
acceptor = null;
}
resources = null;
});
}
use of services.moleculer.Promise 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