创建一系列Vertx处理程序执行

时间:2018-07-17 22:22:24

标签: java future vert.x chain

从一开始,抱歉英语不好,我正在努力。

我的目标是在vert.x中创建http方法。每种方法都包含一些步骤,这些步骤可以被其他步骤阻止。为了简化,一个步骤可以被另一个步骤完全阻止。

我决定创建一个AsyncMethodHandler,它在handle方法调用内,创建AsyncStepHandlers的示例。方法处理程序还会创建一个步骤期货映射,并尝试创建一个组合处理程序以供他们加入。

这是代码AsyncMethodHandler

public abstract class AsyncMethodHandler<T extends BaseChannelResponse> implements Handler<RoutingContext> {

    private static final String CONTENT_TYPE_JSON = "application/json; charset=utf-8";

    private final List<Class<? extends AsyncStepHandler>> steplist;
    private final HttpMethod methodType;
    private final String endpointName;
    private final HttpEndpointName endpoint;
    private String responseEndpoint;

    public AsyncMethodHandler(HttpEndpointName endpoint, String endpointName, HttpMethod methodType, List<Class<? extends AsyncStepHandler>> steplist) {
        this.steplist = steplist;
        this.endpoint = endpoint;
        this.endpointName = endpointName;
        this.methodType = methodType;
    }

    @Override
    public void handle(RoutingContext event) {
        try {
            Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution = new ConcurrentHashMap<>(steplist.size());
            List<AsyncStepHandler> handlers = new ArrayList<>(steplist.size());

            for (Class<? extends AsyncStepHandler> stepClass : this.steplist) {
                AsyncStepHandler stepHandler = stepClass.getConstructor(RoutingContext.class).newInstance(event);
                mapOfExecution.put(stepClass, stepHandler.getStepFuture());
                handlers.add(stepHandler);
            }
            for (AsyncStepHandler stepHandler : handlers) {
                stepHandler.before(mapOfExecution).setHandler(stepHandler.makeHandler(mapOfExecution));
            }

            CompositeFuture.join(new ArrayList<>(mapOfExecution.values())).setHandler(handleResult(event, mapOfExecution));

        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private Handler<AsyncResult<CompositeFuture>> handleResult(RoutingContext event, Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
        return result -> {
            if (result.succeeded()) {
                succeeded(event.response(), generateResponse(mapOfExecution));
            } else {
                ChannelAPIException error = ChannelAPIException.createFrom(result.cause());
                errored(event.response(), error.getCode(), error.getMessage());
            }
        };
    }

    protected abstract T generateResponse(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution);

    private void errored(HttpServerResponse response, int code, String message) {
        response.putHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON)
                .setStatusCode(code)
                .end(message);
        CAPIMetricFactory.incBotResponseError(this.responseEndpoint, code);
    }

    private void succeeded(HttpServerResponse response, T result) {
        response.putHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON)
                .setStatusCode(200)
                .end(Serializer.toPrettyJson(result));
        CAPIMetricFactory.incBotResponse(this.responseEndpoint);
    }

    public String getEndpointName() {
        return endpointName;
    }

    public HttpMethod getMethodType() {
        return methodType;
    }

    public HttpEndpointName getEndpoint() {
        return endpoint;
    }

    public void setResponseEndpoint(String responseEndpoint) {
        this.responseEndpoint = responseEndpoint;
    }
}

这是代码AsyncStepHandlers

public abstract class AsyncStepHandler<T> {

    private final Future stepFuture;
    private final RoutingContext context;
    private final Class<? extends AsyncStepHandler> before;

    public AsyncStepHandler(RoutingContext context) {
        this(Future.future(), context, null);
    }

    public AsyncStepHandler(RoutingContext context, Class<? extends AsyncStepHandler> before) {
        this(Future.future(), context, before);
    }

    private AsyncStepHandler(Future stepFuture, RoutingContext context, Class<? extends AsyncStepHandler> before) {
        this.stepFuture = stepFuture;
        this.context = context;
        this.before = before;
    }

    public static <T> T getResultFromMap(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution, Class<? extends AsyncStepHandler> key) {
        return (T) mapOfExecution.get(key).result();
    }

    public final Future getStepFuture() {
        return stepFuture;
    }

    public RoutingContext getContext() {
        return context;
    }

    public Buffer getContextBody() {
        return context.getBody();
    }

    public String getContextBodyAsString() {
        return context.getBodyAsString();
    }

    public Future before(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
        if (before != null) {
            return mapOfExecution.get(before);
        } else {
            return Future.succeededFuture();
        }
    }

    public abstract Future<T> execute(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution);

    public Handler<AsyncResult> makeHandler(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
        return result -> {
            if (result.succeeded()) {
                this.execute(mapOfExecution).setHandler(this.finish());
            } else {
                stepFuture.fail(result.cause());
            }
        };
    }

    private Handler<AsyncResult<T>> finish() {
        return result -> {
            if (result.succeeded()) {
                stepFuture.complete(result.result());
            } else {
                stepFuture.fail(result.cause());
            }
        };
    }
}

因此,我尝试创建一些实际的方法和步骤。例如:

  1. 从请求正文创建参数对象
  2. 从先前创建的参数中获取令牌并尝试进行授权
  3. 从上一步的授权对象中考虑,验证请求的状态。

所以这是代码:

public class SimpleTestMethod extends AsyncMethodHandler<TestData> {

public SimpleTestMethod(String endpoint) {
    super(
            CHANNEL_API_SEND_TEXT,
            endpoint,
            POST,
            new ArrayList<Class<? extends AsyncStepHandler>>(){{
                add(ParametersStep.class);
            }{
                add(AuthorizationStep.class);
            }{
                add(ValidateStep.class);
            }}
    );
}

@Override
protected TestData generateResponse(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
    System.out.println("End");
    SendMessageParameters response = (SendMessageParameters) mapOfExecution.get(ParametersStep.class).result();
    ValidationResult validationResult = (ValidationResult) mapOfExecution.get(ValidateStep.class).result();
    return new TestData(response.toString(),0l);
}

}

首先,例如步骤如下:

public class ParametersStep extends AsyncStepHandler<SendMessageParameters> {

public ParametersStep(RoutingContext context) {
    super(context);
}

@Override
public Future<SendMessageParameters> execute(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
    System.out.println("ParametersStep");
    SendMessageParameters parameters = parseJson(this.getContextBodyAsString(), SendMessageParameters.class);
    return Future.succeededFuture(parameters);
}

}

可以执行。但是,如果我要添加一些等待步骤,那么该步骤之后的下一个将永远不会开始。

例如:

public class AuthorizationStep extends AsyncStepHandler<AuthResponse> {

public AuthorizationStep(RoutingContext context) {
    super(context, ParametersStep.class);
}

@Override
public Future<AuthResponse> execute(Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution) {
    System.out.println("AuthorizationStep");
    final Future<AuthResponse> authorization = Future.future();
    SendMessageParameters parameters = getResultFromMap(mapOfExecution, ParametersStep.class);
    AuthResponse response = new AuthResponse(new ChannelTokenData(0l,parameters.getToken(),true,0l,0l,null));

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            authorization.complete(response);
        }
    });
    t.start();

    return authorization;
}

}

然后将不会调用等待授权步骤结束的任何步骤。我阅读了官方文档,并试图找到有关此案的一些信息,但未成功。我尝试了不同的技术setHandlercompose,但得到的结果相同。

有人可以帮助我理解为什么下一步不会开始并解决此问题,因为下一部分是使用CompositeFuture =)

P.S .: 最有趣的是,例如,如果AuthorizationStep是3步方法中的第二步-执行将在第二步停止。但是如果我这样做:

@Override
    public void handle(RoutingContext event) {
        try {
            Map<Class<? extends AsyncStepHandler>, Future> mapOfExecution = new ConcurrentHashMap<>(steplist.size());
            List<AsyncStepHandler> handlers = new ArrayList<>(steplist.size());
            CountDownLatch latch = new CountDownLatch(steplist.size());

            for (Class<? extends AsyncStepHandler> stepClass : this.steplist) {
                AsyncStepHandler stepHandler = stepClass.getConstructor(RoutingContext.class).newInstance(event);
                mapOfExecution.put(stepClass, stepHandler.getStepFuture());
                handlers.add(stepHandler);
                stepHandler.setLatch(latch);
            }
            for (AsyncStepHandler stepHandler : handlers) {
                stepHandler.before(mapOfExecution).setHandler(stepHandler.makeHandler(mapOfExecution));
            }

            latch.await();
            CompositeFuture.join(new ArrayList<>(mapOfExecution.values())).setHandler(handleResult(event, mapOfExecution));

        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

这在AsyncStepHandler中:

private Handler<AsyncResult<T>> finish() {
        return result -> {
            System.out.println("finish");
            if (result.succeeded()) {
                latch.countDown();
                stepFuture.complete(result.result());
            } else {
                stepFuture.fail(result.cause());
            }
        };
    }

一切都开始起作用。如果我添加倒计时闩锁,并在Composite将来加入之前添加await,那么一切都会好起来的。

0 个答案:

没有答案