class AbstractRestInvocation {

  protected void scheduleInvocation() {
    try {
      createInvocation();
    } catch (Throwable e) {
      sendFailResponse(e);
      return;
    }

    invocation.onStart(requestEx, start);
    invocation.getInvocationStageTrace().startSchedule();
    OperationMeta operationMeta = restOperationMeta.getOperationMeta();

    try {
      this.setContext();
    } catch (Exception e) {
      LOGGER.error("failed to set invocation context", e);
      sendFailResponse(e);
      return;
    }

    Holder<Boolean> qpsFlowControlReject = checkQpsFlowControl(operationMeta);
    if (qpsFlowControlReject.value) {
      return;
    }

    try {
      operationMeta.getExecutor().execute(() -> {
        synchronized (this.requestEx) {
          try {
            if (isInQueueTimeout()) {
              throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "Timeout when processing the request.");
            }
            if (requestEx.getAttribute(RestConst.REST_REQUEST) != requestEx) {
              // already timeout
              // in this time, request maybe recycled and reused by web container, do not use requestEx
              LOGGER.error("Rest request already timeout, abandon execute, method {}, operation {}.",
                  operationMeta.getHttpMethod(),
                  operationMeta.getMicroserviceQualifiedName());
              return;
            }

            runOnExecutor();
          } catch (Throwable e) {
            LOGGER.error("rest server onRequest error", e);
            sendFailResponse(e);
          }
        }
      });
    } catch (Throwable e) {
      LOGGER.error("failed to schedule invocation, message={}, executor={}.", e.getMessage(), e.getClass().getName());
      sendFailResponse(e);
    }
  }

  public  AbstractRestInvocation();

}