in src/main/java/com/twitter/nodes/Node.java [715:799]
public final Future<Resp> apply() {
if (!createdFuture.compareAndSet(false, true)) {
return promise;
}
// Capture when the node started waiting on dependencies
startTimeMs = System.currentTimeMillis();
Future<Resp> response = futureFromDependencies().flatMap(
new com.twitter.util.Function<Object, Future<Resp>>() {
@Override
public Future<Resp> apply(Object value) {
Future<Resp> result;
if (!isOptional()) {
logStart();
}
try {
evaluateStartTimeMs = System.currentTimeMillis();
if (deciderSupplier.isPresent()
&& !deciderSupplier.get().isFeatureAvailable()) {
debugVerbose("is decidered off for this request, decider key: %s",
deciderSupplier.get().getDeciderKey());
result = isOptional() ? FUTURE_ABSENT : Future.value(null);
} else {
result = evaluate();
if (result == null) {
result = Future.exception(new RuntimeException(
String.format("evaluate() returned null Future object!")));
}
}
} catch (Exception e) {
String message = String.format("evaluate threw an exception");
debugDetailed("%s\n%s", message, Throwables.getStackTraceAsString(e));
LOG.error(e, message);
result = Future.exception(e);
}
evaluateStopTimeMs = System.currentTimeMillis();
return result;
}
}
).flatMap(
new com.twitter.util.Function<Resp, Future<Resp>>() {
@Override
public Future<Resp> apply(Resp value) {
if (value == null && !canEmitNull) {
return Future.exception(new RuntimeException(
String.format("evaluate() returned Future.value(null) "
+ "but the node is not marked as Nullable.")));
} else {
return Future.value(value);
}
}
}).transformedBy(
new FutureTransformer<Resp, Resp>() {
@Override
public Future<Resp> flatMap(Resp value) {
stopTimeMs = System.currentTimeMillis();
if (!isOptional()) {
logResponse(value);
logEnd();
}
return Future.value(value);
}
@Override
public Future<Resp> rescue(Throwable throwable) {
stopTimeMs = System.currentTimeMillis();
if (!isOptional()) {
logError(throwable);
}
return isOptional()
? (Future<Resp>) FUTURE_ABSENT : Future.exception(throwable);
}
});
applySinkNodes();
promise.become(response);
return promise;
}