add AdminDisputesHandler

This commit is contained in:
Anatoly Karlov 2024-08-29 00:27:07 +07:00
parent 3625778fd0
commit 92f0755021
10 changed files with 108 additions and 5 deletions

View File

@ -47,7 +47,7 @@
<dependency>
<groupId>dev.vality</groupId>
<artifactId>provider-disputes-proto</artifactId>
<version>1.8-b7ce1ec</version>
<version>1.9-bd07d18</version>
</dependency>
<dependency>
<groupId>dev.vality</groupId>

View File

@ -25,7 +25,7 @@ public class Status200ResponseConverter {
return switch (dispute.getStatus()) {
case created, pending -> Status200Response.StatusEnum.PENDING;
case succeeded -> Status200Response.StatusEnum.SUCCEEDED;
case failed -> Status200Response.StatusEnum.FAILED;
case cancelled, failed -> Status200Response.StatusEnum.FAILED;
};
}
}

View File

@ -62,6 +62,17 @@ public class DisputeDao extends AbstractGenericDao {
.orElse(List.of());
}
public Dispute getForUpdateSkipLocked(long disputeId) {
var query = getDslContext().selectFrom(DISPUTE)
.where(DISPUTE.ID.eq(disputeId))
.forUpdate()
.skipLocked();
return Optional.ofNullable(fetchOne(query, disputeRowMapper))
.orElseThrow(
() -> new NotFoundException(
String.format("Dispute not found, disputeId='%s'", disputeId)));
}
public List<Dispute> getDisputesForUpdateSkipLocked(int limit, DisputeStatus disputeStatus) {
var query = getDslContext().selectFrom(DISPUTE)
.where(DISPUTE.STATUS.eq(disputeStatus))

View File

@ -0,0 +1,22 @@
package dev.vality.disputes.handler;
import dev.vality.disputes.AdminDisputesServiceSrv;
import dev.vality.disputes.service.DisputesService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings({"ParameterName", "LineLength"})
public class AdminDisputesHandler implements AdminDisputesServiceSrv.Iface {
private final DisputesService disputesService;
@Override
public void cancelPending(String disputeId) throws TException {
disputesService.cancelPendingDispute(disputeId, null);
}
}

View File

@ -52,7 +52,7 @@ public class RemoteClient {
public DisputeStatusResult checkDisputeStatus(Dispute dispute, ProviderDispute providerDispute) {
var terminal = getTerminal(dispute.getTerminalId());
var proxy = getProxy(dispute.getProviderId());
var disputeContext = disputeContextConverter.convert(providerDispute, terminal.get().getOptions());
var disputeContext = disputeContextConverter.convert(dispute, providerDispute, terminal.get().getOptions());
var remoteClient = providerRouting.getConnection(terminal.get().getOptions(), proxy.get().getUrl());
log.info("Trying to routed remote provider's checkDisputeStatus() call {}", dispute);
var result = remoteClient.checkDisputeStatus(disputeContext);

View File

@ -1,6 +1,8 @@
package dev.vality.disputes.schedule.converter;
import dev.vality.damsel.domain.Currency;
import dev.vality.disputes.DisputeContext;
import dev.vality.disputes.domain.tables.pojos.Dispute;
import dev.vality.disputes.domain.tables.pojos.ProviderDispute;
import org.springframework.stereotype.Component;
@ -9,9 +11,15 @@ import java.util.Map;
@Component
public class DisputeContextConverter {
public DisputeContext convert(ProviderDispute providerDispute, Map<String, String> options) {
public DisputeContext convert(Dispute dispute, ProviderDispute providerDispute, Map<String, String> options) {
var disputeContext = new DisputeContext();
disputeContext.setDisputeId(providerDispute.getProviderDisputeId());
var currency = new Currency();
currency.setName(dispute.getCurrencyName());
currency.setSymbolicCode(dispute.getCurrencySymbolicCode());
currency.setNumericCode(dispute.getCurrencyNumericCode().shortValue());
currency.setExponent(dispute.getCurrencyExponent().shortValue());
disputeContext.setCurrency(currency);
disputeContext.setTerminalOptions(options);
return disputeContext;
}

View File

@ -126,7 +126,7 @@ public class PendingDisputesService {
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage);
log.debug("Dispute status has been set to failed {}", dispute);
}
case PENDING_SUCCESS -> {
case STATUS_PENDING -> {
// дергаем update() чтоб обновить время вызова next_check_after,
// чтобы шедулатор далее доставал пачку самых древних диспутов и смещал
// и этим вызовом мы финализируем состояние диспута, что он был обновлен недавно

View File

@ -0,0 +1,32 @@
package dev.vality.disputes.service;
import dev.vality.disputes.dao.DisputeDao;
import dev.vality.disputes.domain.enums.DisputeStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
public class DisputesService {
private final DisputeDao disputeDao;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public void cancelPendingDispute(String disputeId, String cancelReason) {
log.debug("Trying to getForUpdateSkipLocked {}", disputeId);
var dispute = disputeDao.getForUpdateSkipLocked(Long.parseLong(disputeId));
log.debug("GetForUpdateSkipLocked has been found {}", dispute);
if (dispute.getStatus() == DisputeStatus.pending
|| dispute.getStatus() == DisputeStatus.created) {
log.error("Trying to set cancelled Dispute status with '{}' error reason {}", cancelReason, dispute);
disputeDao.update(dispute.getId(), DisputeStatus.cancelled, cancelReason);
log.debug("Dispute status has been set to cancelled {}", dispute);
}
}
}

View File

@ -0,0 +1,29 @@
package dev.vality.disputes.servlet;
import dev.vality.disputes.AdminDisputesServiceSrv;
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/admin")
public class AdminDisputesServlet extends GenericServlet {
@Autowired
private AdminDisputesServiceSrv.Iface adminDisputesHandler;
private Servlet servlet;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
servlet = new THServiceBuilder().build(AdminDisputesServiceSrv.Iface.class, adminDisputesHandler);
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
servlet.service(request, response);
}
}

View File

@ -0,0 +1 @@
alter type dspt.dispute_status add value 'cancelled';