- Better error handling during calculation

- Bugfixes in calculation (error in getByMappingIdAndCountryId)
This commit is contained in:
Jan 2025-10-18 22:20:51 +02:00
parent 78bd0ad6d6
commit d7bc62c713
6 changed files with 41 additions and 18 deletions

View file

@ -98,7 +98,8 @@ function handleErrorResponse(data, requestingStore, request) {
const error = new Error('Internal backend error');
error.errorObj = errorObj;
if (request.expectedException === null || data.error.title !== request.expectedException) {
if (request.expectedException === null || Array.isArray(request.expectResponse) && !request.expectedException.includes(data.error.title) || (typeof request.expectedException === 'string' && !data.error.title !== request.expectedException)) {
logger.error(errorObj);
const errorStore = useErrorStore();
void errorStore.addError(errorObj, {store: requestingStore, request: request});

View file

@ -320,8 +320,8 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
const url = `${config.backendUrl}/calculation/start/`;
let error = null;
await performRequest(this, 'PUT', url, body, false, 'Premiss validation error').catch(e => {
console.log("startCalculation exception", e.errorObj);
await performRequest(this, 'PUT', url, body, false, ['Premiss validation error', 'Internal Server Error']).catch(e => {
logger.log("startCalculation exception", e.errorObj);
error = e.errorObj;
})
@ -533,7 +533,7 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
const idx = this.destinations.destinations.findIndex(d => d.id === id);
if (idx === -1) {
console.info("Destination not found in mass edit: , id)");
logger.info("Destination not found in mass edit: , id)");
return;
}
@ -575,7 +575,7 @@ export const usePremiseEditStore = defineStore('premiseEdit', {
logger.info(existing)
if ((existing ?? null) !== null) {
console.info("Destination already exists", node.id);
logger.info("Destination already exists", node.id);
return [existing.id];
}

View file

@ -111,8 +111,8 @@ public class CountryPropertyRepository {
type.description as description,
type.property_group as propertyGroup,
type.sequence_number as sequenceNumber,
valid.property_value as draftValue,
valid.property_value as validValue
FROM country_property_type AS type
LEFT JOIN (
SELECT cp.property_value, cp.country_property_type_id
@ -123,7 +123,7 @@ public class CountryPropertyRepository {
WHERE type.external_mapping_id = ?
""";
var property = jdbcTemplate.query(query, new PropertyMapper(), countryId, countryId, setId, mappingId);
var property = jdbcTemplate.query(query, new PropertyMapper(), countryId, setId, mappingId);
if (property.isEmpty())
return Optional.empty();

View file

@ -149,7 +149,7 @@ public class PremisesService {
var jobResult = future.get();
if (jobResult.getState().equals(CalculationJobState.EXCEPTION)) {
calculationJobRepository.setStateTo(jobResult.getJobId(), CalculationJobState.EXCEPTION);
throw new InternalErrorException("Execution of calculation was not successful. Please contact Administrator.", jobResult.getException().getMessage(), new Exception(jobResult.getException()));
throw new InternalErrorException("Calculation failed", "Calculation was not successful. Please contact Administrator.", new Exception(jobResult.getException()));
} else {
postCalculationCheckService.doPostcheck(jobResult);
@ -171,7 +171,7 @@ public class PremisesService {
}
} catch (CompletionException | InterruptedException | ExecutionException e) {
throw new InternalErrorException("Calculation execution failed.", e);
throw new InternalErrorException("Task execution of calculation failed", "Task execution of calculation was not successful. Please contact Administrator.", e);
}
}

View file

@ -4,6 +4,8 @@ import de.avatic.lcc.calculationmodel.*;
import de.avatic.lcc.dto.generic.ContainerType;
import de.avatic.lcc.dto.generic.RateType;
import de.avatic.lcc.model.calculations.*;
import de.avatic.lcc.model.error.SysError;
import de.avatic.lcc.model.error.SysErrorType;
import de.avatic.lcc.model.packaging.LoadCarrierType;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.premises.Premise;
@ -13,12 +15,14 @@ import de.avatic.lcc.model.properties.SystemPropertyMappingId;
import de.avatic.lcc.repositories.calculation.CalculationJobDestinationRepository;
import de.avatic.lcc.repositories.calculation.CalculationJobRepository;
import de.avatic.lcc.repositories.calculation.CalculationJobRouteSectionRepository;
import de.avatic.lcc.repositories.error.SysErrorRepository;
import de.avatic.lcc.repositories.premise.DestinationRepository;
import de.avatic.lcc.repositories.premise.PremiseRepository;
import de.avatic.lcc.repositories.premise.RouteRepository;
import de.avatic.lcc.repositories.premise.RouteSectionRepository;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.service.calculation.execution.steps.*;
import de.avatic.lcc.service.transformer.error.SysErrorTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
@ -49,9 +53,11 @@ public class CalculationExecutionService {
private final ContainerCalculationService containerCalculationService;
private final ShippingFrequencyCalculationService shippingFrequencyCalculationService;
private final CalculationJobRepository calculationJobRepository;
private final SysErrorRepository sysErrorRepository;
private final SysErrorTransformer sysErrorTransformer;
public CalculationExecutionService(PremiseRepository premiseRepository, DestinationRepository destinationRepository, RouteRepository routeRepository, RouteSectionRepository routeSectionRepository, CustomCostCalculationService customCostCalculationService, RouteSectionCostCalculationService routeSectionCostCalculationService, HandlingCostCalculationService handlingCostCalculationService, InventoryCostCalculationService inventoryCostCalculationService, PropertyRepository propertyRepository, AirfreightCalculationService airfreightCalculationService, PremiseToHuService premiseToHuService, ContainerCalculationService containerCalculationService, ShippingFrequencyCalculationService shippingFrequencyCalculationService, CalculationJobRepository calculationJobRepository) {
public CalculationExecutionService(PremiseRepository premiseRepository, DestinationRepository destinationRepository, RouteRepository routeRepository, RouteSectionRepository routeSectionRepository, CustomCostCalculationService customCostCalculationService, RouteSectionCostCalculationService routeSectionCostCalculationService, HandlingCostCalculationService handlingCostCalculationService, InventoryCostCalculationService inventoryCostCalculationService, PropertyRepository propertyRepository, AirfreightCalculationService airfreightCalculationService, PremiseToHuService premiseToHuService, ContainerCalculationService containerCalculationService, ShippingFrequencyCalculationService shippingFrequencyCalculationService, CalculationJobRepository calculationJobRepository, SysErrorRepository sysErrorRepository, SysErrorTransformer sysErrorTransformer) {
this.premiseRepository = premiseRepository;
this.destinationRepository = destinationRepository;
this.routeRepository = routeRepository;
@ -66,7 +72,8 @@ public class CalculationExecutionService {
this.containerCalculationService = containerCalculationService;
this.shippingFrequencyCalculationService = shippingFrequencyCalculationService;
this.calculationJobRepository = calculationJobRepository;
this.sysErrorRepository = sysErrorRepository;
this.sysErrorTransformer = sysErrorTransformer;
}
private static ContainerType getBestContainerType(Map<ContainerType, List<SectionInfo>> sectionResults) {
@ -80,19 +87,34 @@ public class CalculationExecutionService {
.orElse(null);
}
@Transactional
@Async("calculationExecutor")
public CompletableFuture<CalculationResult> launchJobCalculation(Integer calculationId) {
var optCalc = calculationJobRepository.getCalculationJob(calculationId);
try {
return CompletableFuture.completedFuture(new CalculationResult(calculationId, calculateJob(calculationId)));
return CompletableFuture.completedFuture(new CalculationResult(calculationId, calculateJob(optCalc.orElseThrow())));
} catch (Throwable e) {
var calc = optCalc.orElse(null);
var error = new SysError();
error.setType(SysErrorType.CALCULATION);
error.setCode(e.getClass().getSimpleName().substring(0, Math.min(e.getClass().getSimpleName().length(), 253)));
error.setTitle("Calculation operation execution " + calculationId + " failed");
error.setMessage(e.getMessage().substring(0, Math.min(e.getMessage().length(), 1000)));
error.setUserId(calc == null ? null : calc.getUserId());
error.setCalculationJobId(calculationId);
error.setTrace(Arrays.stream(e.getStackTrace()).map(sysErrorTransformer::toSysErrorTraceItem).toList());
sysErrorRepository.insert(error);
return CompletableFuture.completedFuture(new CalculationResult(calculationId, e));
}
}
public List<DestinationInfo> calculateJob(Integer calculationId) {
CalculationJob calculation = calculationJobRepository.getCalculationJob(calculationId).orElseThrow();
public List<DestinationInfo> calculateJob(CalculationJob calculation) {
if (CalculationJobState.SCHEDULED.equals(calculation.getJobState())) {
Premise premise = premiseRepository.getPremiseById(calculation.getPremiseId()).orElseThrow();

View file

@ -601,7 +601,7 @@ CREATE TABLE IF NOT EXISTS sys_error
user_id INT DEFAULT NULL,
title VARCHAR(255) NOT NULL,
code VARCHAR(255) NOT NULL,
message VARCHAR(512) NOT NULL,
message VARCHAR(1024) NOT NULL,
pinia TEXT,
calculation_job_id INT DEFAULT NULL,
bulk_operation_id INT DEFAULT NULL,
@ -622,7 +622,7 @@ CREATE TABLE IF NOT EXISTS sys_error_trace_item
line INT,
file VARCHAR(255) NOT NULL,
method VARCHAR(255) NOT NULL,
fullPath VARCHAR(512) NOT NULL,
fullPath VARCHAR(1024) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (error_id) REFERENCES sys_error (id)
);