public final Future apply()

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;
  }