如果对支付处理器的API调用花费了60秒以上,则会中断

时间:2019-04-09 17:59:49

标签: java multithreading jersey thread-safety

我正在与付款处理器集成,并试图处理以下情况:

  • 用户点击付款并向我们的服务器发出请求
  • 我们的服务器向付款处理器发出请求
  • 付款处理方存在重大延迟
  • 在某个阈值之后,例如60秒后,我们提醒用户他们的付款失败
  • 70秒后,付款处理器将返回成功的响应。

因此,我需要从用户界面的HTTP调用中开始对支付处理器的API调用,然后,如果花费超过60秒,请结束HTTP调用并将错误返回给用户,然后,如果API调用付款处理程序最终成功(例如70秒后),请向管理团队发送电子邮件。

我在想这样的事情:

    import javax.ws.rs.client.*;
    import java.util.Timer;
    import java.util.TimerTask;

    ...

    boolean overThreshold = false;
    int timeout = 60; // seconds
    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            overThreshold = true;
            // return a message to user here saying their payment could not be processed
        }
    };

    new Timer(true).schedule(task, timeout * 1000);

    Client client = ClientBuilder.newClient();
    WebTarget webTarget
            = client.target({url of payment processor});
    Invocation.Builder builder = webTarget.request()
            .header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON);

    final Response response = builder.post(Entity.json(new Gson().toJson(request)));

    if (overThreshold) {
        // send alert email here
    }

存在一些问题,例如run()方法的返回值无效,overThreshold从内部类访问时出错。有更优雅的方法吗?

1 个答案:

答案 0 :(得分:4)

使用Future.get(timeout)中的ExecutorService应该很干净。

例如:

    ExecutorService executor = Executors.newCachedThreadPool();

    // ... set up builder as before ...
    Future<Response> responseFuture = executor.submit(
            () -> builder.post(Entity.json(new Gson().toJson(request))));
    try {
        Response response = responseFuture.get(timeout, TimeUnit.SECONDS);
        // return normal response here
    } catch (TimeoutException ex) {
        executor.submit( () -> {
            Response lateResponse = responseFuture.get();
            // send overThreshold alert email here
            // Dummy return - prefer Callable to Runnable here for exception handling
            return null;
        } );
        // return a message to user here saying their payment could not be processed
    }

ExecutorService的选择可以调整为适合,或者同样可以是应用程序中其他位置的共享线程池。