IMP-327: add callback handler (#11)
Some checks failed
Deploy Docker Image / build-and-deploy (push) Has been cancelled

This commit is contained in:
Anatolii Karlov 2024-09-20 20:37:38 +07:00 committed by GitHub
parent 3950e053f8
commit e10acfeec1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 133 additions and 23 deletions

View File

@ -0,0 +1,47 @@
package dev.vality.disputes.callback;
import dev.vality.disputes.dao.DisputeDao;
import dev.vality.disputes.dao.ProviderDisputeDao;
import dev.vality.disputes.schedule.handler.DisputeStatusResultHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Service;
import java.util.Objects;
import static dev.vality.disputes.api.service.ApiDisputesService.DISPUTE_PENDING;
@Service
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
public class ProviderDisputesCallbackHandler implements ProviderDisputesCallbackServiceSrv.Iface {
private final DisputeDao disputeDao;
private final ProviderDisputeDao providerDisputeDao;
private final DisputeStatusResultHandler disputeStatusResultHandler;
@Override
public void changeStatus(DisputeCallbackParams disputeCallbackParams) throws TException {
var transactionContext = disputeCallbackParams.getTransactionContext();
var disputes = disputeDao.get(transactionContext.getInvoiceId(), transactionContext.getPaymentId());
var optionalDispute = disputes.stream()
.filter(d -> DISPUTE_PENDING.contains(d.getStatus()))
.findFirst();
if (optionalDispute.isEmpty()) {
return;
}
var dispute = optionalDispute.get();
var providerDispute = providerDisputeDao.get(dispute.getId());
if (providerDispute == null
|| !Objects.equals(providerDispute.getProviderDisputeId(), disputeCallbackParams.getProviderDisputeId())) {
return;
}
var result = disputeCallbackParams.getDisputeStatusResult();
switch (result.getSetField()) {
case STATUS_SUCCESS -> disputeStatusResultHandler.handleStatusSuccess(dispute, result);
case STATUS_FAIL -> disputeStatusResultHandler.handleStatusFail(dispute, result);
}
}
}

View File

@ -0,0 +1,50 @@
package dev.vality.disputes.schedule.handler;
import dev.vality.disputes.DisputeStatusResult;
import dev.vality.disputes.dao.DisputeDao;
import dev.vality.disputes.domain.enums.DisputeStatus;
import dev.vality.disputes.domain.tables.pojos.Dispute;
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
import dev.vality.geck.serializer.kit.tbase.TErrorUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
public class DisputeStatusResultHandler {
private final DisputeDao disputeDao;
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
@Transactional(propagation = Propagation.REQUIRED)
public void handleStatusPending(Dispute dispute, DisputeStatusResult result) {
// дергаем update() чтоб обновить время вызова next_check_after,
// чтобы шедулатор далее доставал пачку самых древних диспутов и смещал
// и этим вызовом мы финализируем состояние диспута, что он был обновлен недавно
var nextCheckAfter = exponentialBackOffPollingService.prepareNextPollingInterval(dispute);
log.info("Trying to set pending Dispute status {}, {}", dispute, result);
disputeDao.update(dispute.getId(), DisputeStatus.pending, nextCheckAfter);
log.debug("Dispute status has been set to pending {}", dispute.getId());
}
@Transactional(propagation = Propagation.REQUIRED)
public void handleStatusFail(Dispute dispute, DisputeStatusResult result) {
var errorMessage = TErrorUtil.toStringVal(result.getStatusFail().getFailure());
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage);
log.debug("Dispute status has been set to failed {}", dispute.getId());
}
@Transactional(propagation = Propagation.REQUIRED)
public void handleStatusSuccess(Dispute dispute, DisputeStatusResult result) {
var changedAmount = result.getStatusSuccess().getChangedAmount().orElse(null);
log.info("Trying to set create_adjustment Dispute status {}, {}", dispute, result);
disputeDao.update(dispute.getId(), DisputeStatus.create_adjustment, changedAmount);
log.debug("Dispute status has been set to create_adjustment {}", dispute.getId());
}
}

View File

@ -9,7 +9,7 @@ import dev.vality.disputes.domain.tables.pojos.Dispute;
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
import dev.vality.disputes.polling.PollingInfoService;
import dev.vality.disputes.schedule.client.RemoteClient;
import dev.vality.geck.serializer.kit.tbase.TErrorUtil;
import dev.vality.disputes.schedule.handler.DisputeStatusResultHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -30,6 +30,7 @@ public class PendingDisputesService {
private final ProviderDisputeDao providerDisputeDao;
private final PollingInfoService pollingInfoService;
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
private final DisputeStatusResultHandler disputeStatusResultHandler;
@Transactional(propagation = Propagation.REQUIRED)
public List<Dispute> getPendingDisputesForUpdateSkipLocked(int batchSize) {
@ -72,27 +73,9 @@ public class PendingDisputesService {
@Transactional(propagation = Propagation.REQUIRED)
void finishTask(Dispute dispute, DisputeStatusResult result) {
switch (result.getSetField()) {
case STATUS_SUCCESS -> {
var changedAmount = result.getStatusSuccess().getChangedAmount().orElse(null);
log.info("Trying to set create_adjustment Dispute status {}, {}", dispute, result);
disputeDao.update(dispute.getId(), DisputeStatus.create_adjustment, changedAmount);
log.debug("Dispute status has been set to create_adjustment {}", dispute.getId());
}
case STATUS_FAIL -> {
var errorMessage = TErrorUtil.toStringVal(result.getStatusFail().getFailure());
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage);
log.debug("Dispute status has been set to failed {}", dispute.getId());
}
case STATUS_PENDING -> {
// дергаем update() чтоб обновить время вызова next_check_after,
// чтобы шедулатор далее доставал пачку самых древних диспутов и смещал
// и этим вызовом мы финализируем состояние диспута, что он был обновлен недавно
var nextCheckAfter = exponentialBackOffPollingService.prepareNextPollingInterval(dispute);
log.info("Trying to set pending Dispute status {}, {}", dispute, result);
disputeDao.update(dispute.getId(), DisputeStatus.pending, nextCheckAfter);
log.debug("Dispute status has been set to pending {}", dispute.getId());
}
case STATUS_SUCCESS -> disputeStatusResultHandler.handleStatusSuccess(dispute, result);
case STATUS_FAIL -> disputeStatusResultHandler.handleStatusFail(dispute, result);
case STATUS_PENDING -> disputeStatusResultHandler.handleStatusPending(dispute, result);
}
}
}

View File

@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
@WebServlet("/disputes-api/manual-parsing")
@WebServlet("/disputes-api/v1/manual-parsing")
public class ManualParsingServlet extends GenericServlet {
@Autowired

View File

@ -0,0 +1,30 @@
package dev.vality.disputes.servlet;
import dev.vality.disputes.callback.ProviderDisputesCallbackServiceSrv;
import dev.vality.woody.thrift.impl.http.THServiceBuilder;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebServlet;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
@WebServlet("/disputes-api/v1/callback")
public class ProviderDisputesCallbackServlet extends GenericServlet {
@Autowired
private ProviderDisputesCallbackServiceSrv.Iface providerDisputesCallbackHandler;
private Servlet servlet;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
servlet = new THServiceBuilder()
.build(ProviderDisputesCallbackServiceSrv.Iface.class, providerDisputesCallbackHandler);
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
servlet.service(request, response);
}
}