如果 API 调用支付处理器超过 60 秒则中断
Interrupt if API call to payment processor takes over 60 seconds
我正在与支付处理器集成并尝试处理以下场景:
- 用户点击付款并向我们的服务器发出请求
- 我们的服务器向支付处理器发出请求
- 支付处理方存在严重延迟
- 在某个阈值之后,例如60 秒,我们提醒用户支付失败
- 70 秒后,支付处理器 return 成功响应。
所以我需要从 UI 的 HTTP 调用中启动对支付处理器的 API 调用,然后如果花费的时间超过 60 秒,则结束 HTTP 调用并 return 给用户一个错误,然后如果 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()
方法有 void return 值,错误 overThreshold
是从内部 class 访问的。有更优雅的方法吗?
使用 Future.get(timeout) from an 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
的选择以适应,或者同样是应用程序其他地方的共享线程池。
我正在与支付处理器集成并尝试处理以下场景:
- 用户点击付款并向我们的服务器发出请求
- 我们的服务器向支付处理器发出请求
- 支付处理方存在严重延迟
- 在某个阈值之后,例如60 秒,我们提醒用户支付失败
- 70 秒后,支付处理器 return 成功响应。
所以我需要从 UI 的 HTTP 调用中启动对支付处理器的 API 调用,然后如果花费的时间超过 60 秒,则结束 HTTP 调用并 return 给用户一个错误,然后如果 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()
方法有 void return 值,错误 overThreshold
是从内部 class 访问的。有更优雅的方法吗?
使用 Future.get(timeout) from an 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
的选择以适应,或者同样是应用程序其他地方的共享线程池。