I have a method where I expect the following sequence of calls:
- sendUpdateCallback
- sendSuccessCallback
Here's the place I'm calling from:
@Override
public String onPaymentInitiationAuthorizationSuccess(
@NotEmpty String userId,
@NotEmpty String paymentExtra,
@NotEmpty String paymentProduct
) {
log.error("onPaymentInitiationAuthorizationSuccess tag");
Map<String, String> paymentExtraMap = parseExtra(paymentExtra);
String sessionSecret = paymentExtraMap.get(SDKConstants.KEY_SESSION_SECRET);
String status = getStatusOfPaymentProduct(paymentProduct);
SessionSuccessCallbackRequest params = new SessionSuccessCallbackRequest(userId, status);
sessionsCallbackService.sendUpdateCallback(sessionSecret, params);
if (!StringUtils.isEmpty(sessionSecret)) sessionsCallbackService.sendSuccessCallback(sessionSecret, params);
return paymentExtraMap.getOrDefault(SDKConstants.KEY_RETURN_TO_URL, "");
}
Here is the code of my methods:
@Service
public class SessionsCallbackService extends CallbackRestClient {
private static final Logger log = LoggerFactory.getLogger(SessionsCallbackService.class);
@Async
public void sendUpdateCallback(String sessionSecret, BaseCallbackRequest params) {
log.error("sendUpdateCallback");
String url = createCallbackRequestUrl(createSessionPath(sessionSecret) "/update");
sendSessionCallback(url, sessionSecret, params);
}
@Async
public void sendSuccessCallback(String sessionSecret, BaseCallbackRequest params) {
log.error("sendSuccessCallback");
String url = createCallbackRequestUrl(createSessionPath(sessionSecret) "/success");
sendSessionCallback(url, sessionSecret, params);
}
As you can see from the screenshot, it is clear that I first call the sendUpdateCallback
method and after sendSuccessCallback
, but we see on requests that sendSuccessCallback
is implemented faster, how can this be fixed?
CodePudding user response:
To fix the problem (make asynchronous (void) "service" (methods) synchronous), you could (if the effort is worth/not too big), refactor your void
(semi-blocking) method to (Completable)Future<Void>
like:
@Async
public CompletableFuture<Void> sendUpdateCallback(String sessionSecret, BaseCallbackRequest params) {
log.error("sendUpdateCallback");
String url = createCallbackRequestUrl(createSessionPath(sessionSecret) "/update");
sendSessionCallback(url, sessionSecret, params);
return CompletableFuture.completedFuture(null);
}
... then to "block" it, you would:
CompletableFuture<Void> updateResult = sessionsCallbackService.sendUpdateCallback(sessionSecret, params);
if (!StringUtils.isEmpty(sessionSecret)) {
updateResult.get(); // also possible: get(long timeout, TimeUnit unit)
if (updateResult.isCancelled()) {
// ...will not happen in my answer, but for completeness..
} else if (updateResult.isCompletedExceptionally()) {
// handle/throw exception?
} else if (updateResult.isDone()) {
// finally send success
sessionsCallbackService.sendSuccessCallback(sessionSecret, params);
}
}
But easiest (& convincing) is: Ervin's comment