Skip to content

Commit 6c1b46f

Browse files
Custom message if no extension data + fix bug (#47)
* Resolve ClassCastException in repository `insert()` with better support of unknown implementations * Add custom message for missing extension and fix wrong condition
1 parent 0b4f545 commit 6c1b46f

File tree

3 files changed

+94
-66
lines changed

3 files changed

+94
-66
lines changed

src/main/java/org/gridsuite/shortcircuit/server/entities/FaultResultEntity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@
66
*/
77
package org.gridsuite.shortcircuit.server.entities;
88

9+
import jakarta.persistence.*;
910
import lombok.Getter;
1011
import lombok.NoArgsConstructor;
1112
import lombok.Setter;
1213

13-
import jakarta.persistence.*;
1414
import java.util.List;
1515
import java.util.UUID;
1616

1717
/**
1818
* @author Nicolas Noir <nicolas.noir at rte-france.com>
1919
*/
2020
@Getter
21+
@Setter
2122
@NoArgsConstructor
2223
@Entity
2324
@Table(indexes = @Index(name = "result_uuid_nbLimitViolations_idx", columnList = "result_result_uuid, nbLimitViolations"))

src/main/java/org/gridsuite/shortcircuit/server/repositories/ShortCircuitAnalysisResultRepository.java

Lines changed: 81 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
package org.gridsuite.shortcircuit.server.repositories;
88

99
import com.powsybl.shortcircuit.*;
10+
import lombok.extern.slf4j.Slf4j;
1011
import org.gridsuite.shortcircuit.server.dto.ShortCircuitLimits;
1112
import org.gridsuite.shortcircuit.server.entities.*;
1213
import org.gridsuite.shortcircuit.server.utils.ShortcircuitUtils;
14+
import org.springframework.beans.factory.annotation.Autowired;
1315
import org.springframework.data.domain.Page;
1416
import org.springframework.data.domain.Pageable;
1517
import org.springframework.stereotype.Repository;
@@ -24,15 +26,14 @@
2426
/**
2527
* @author Etienne Homer <etienne.homer at rte-france.com
2628
*/
29+
@Slf4j
2730
@Repository
2831
public class ShortCircuitAnalysisResultRepository {
32+
private final GlobalStatusRepository globalStatusRepository;
33+
private final ResultRepository resultRepository;
34+
private final FaultResultRepository faultResultRepository;
2935

30-
private GlobalStatusRepository globalStatusRepository;
31-
32-
private ResultRepository resultRepository;
33-
34-
private FaultResultRepository faultResultRepository;
35-
36+
@Autowired
3637
public ShortCircuitAnalysisResultRepository(GlobalStatusRepository globalStatusRepository,
3738
ResultRepository resultRepository,
3839
FaultResultRepository faultResultRepository) {
@@ -49,69 +50,91 @@ private static List<LimitViolationEmbeddable> extractLimitViolations(FaultResult
4950
.collect(Collectors.toList());
5051
}
5152

52-
private static ShortCircuitAnalysisResultEntity toResultEntity(UUID resultUuid, ShortCircuitAnalysisResult result, Map<String, ShortCircuitLimits> allShortCircuitLimits, boolean isWithFortescueResult) {
53-
Set<FaultResultEntity> faultResults = result.getFaultResults().stream().map(faultResult -> isWithFortescueResult ? toFortescueFaultResultEntity(faultResult, allShortCircuitLimits.get(faultResult.getFault().getId())) : toMagnitudeFaultResultEntity(faultResult, allShortCircuitLimits.get(faultResult.getFault().getId()))).collect(Collectors.toSet());
53+
private static ShortCircuitAnalysisResultEntity toResultEntity(UUID resultUuid, ShortCircuitAnalysisResult result, Map<String, ShortCircuitLimits> allShortCircuitLimits) {
54+
Set<FaultResultEntity> faultResults = result.getFaultResults()
55+
.stream()
56+
.map(faultResult -> {
57+
if (faultResult instanceof FailedFaultResult failedFaultResult) {
58+
return toGenericFaultResultEntity(failedFaultResult, null);
59+
} else if (faultResult instanceof FortescueFaultResult fortescueFaultResult) {
60+
return toFortescueFaultResultEntity(fortescueFaultResult, allShortCircuitLimits.get(faultResult.getFault().getId()));
61+
} else if (faultResult instanceof MagnitudeFaultResult magnitudeFaultResult) {
62+
return toMagnitudeFaultResultEntity(magnitudeFaultResult, allShortCircuitLimits.get(faultResult.getFault().getId()));
63+
} else {
64+
log.warn("Unknown FaultResult class: {}", faultResult.getClass());
65+
return toGenericFaultResultEntity(faultResult, allShortCircuitLimits.get(faultResult.getFault().getId()));
66+
}
67+
})
68+
.collect(Collectors.toSet());
5469
//We need to limit the precision to avoid database precision storage limit issue (postgres has a precision of 6 digits while h2 can go to 9)
5570
return new ShortCircuitAnalysisResultEntity(resultUuid, ZonedDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.MICROS), faultResults);
5671
}
5772

58-
private static FaultResultEntity toMagnitudeFaultResultEntity(FaultResult faultResult, ShortCircuitLimits shortCircuitLimits) {
59-
Fault fault = faultResult.getFault();
60-
double current = ((MagnitudeFaultResult) faultResult).getCurrent();
61-
double shortCircuitPower = faultResult.getShortCircuitPower();
62-
FaultEmbeddable faultEmbedded = new FaultEmbeddable(fault.getId(), fault.getElementId(), fault.getFaultType());
63-
List<LimitViolationEmbeddable> limitViolations = extractLimitViolations(faultResult);
64-
List<FeederResultEmbeddable> feederResults = faultResult.getFeederResults().stream()
65-
.map(feederResult -> new FeederResultEmbeddable(feederResult.getConnectableId(),
66-
((MagnitudeFeederResult) feederResult).getCurrent(), null))
67-
.collect(Collectors.toList());
68-
73+
private static FaultResultEntity toGenericFaultResultEntity(final FaultResult faultResult, final ShortCircuitLimits shortCircuitLimits) {
74+
final Fault fault = faultResult.getFault();
6975
double ipMax = Double.NaN;
7076
double ipMin = Double.NaN;
71-
double deltaCurrentIpMin = Double.NaN;
72-
double deltaCurrentIpMax = Double.NaN;
7377
if (shortCircuitLimits != null) {
7478
ipMax = shortCircuitLimits.getIpMax();
7579
ipMin = shortCircuitLimits.getIpMin();
76-
deltaCurrentIpMin = current - ipMin / 1000;
77-
deltaCurrentIpMax = current - ipMax / 1000;
7880
}
79-
return new FaultResultEntity(faultEmbedded, current, shortCircuitPower, limitViolations, feederResults, ipMin, ipMax, null, null, deltaCurrentIpMin, deltaCurrentIpMax);
80-
}
81-
82-
private static FaultResultEntity toFortescueFaultResultEntity(FaultResult faultResult, ShortCircuitLimits shortCircuitLimits) {
83-
Fault fault = faultResult.getFault();
84-
double shortCircuitPower = faultResult.getShortCircuitPower();
85-
FaultEmbeddable faultEmbedded = new FaultEmbeddable(fault.getId(), fault.getElementId(), fault.getFaultType());
86-
List<LimitViolationEmbeddable> limitViolations = extractLimitViolations(faultResult);
87-
List<FeederResultEmbeddable> feederResults = faultResult.getFeederResults().stream()
88-
.map(feederResult -> {
89-
FortescueValue feederFortescueCurrent = ((FortescueFeederResult) feederResult).getCurrent();
90-
FortescueValue.ThreePhaseValue feederFortescueThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(feederFortescueCurrent);
91-
return new FeederResultEmbeddable(feederResult.getConnectableId(),
92-
Double.NaN, new FortescueResultEmbeddable(feederFortescueCurrent.getPositiveMagnitude(), feederFortescueCurrent.getZeroMagnitude(), feederFortescueCurrent.getNegativeMagnitude(), feederFortescueCurrent.getPositiveAngle(), feederFortescueCurrent.getZeroAngle(), feederFortescueCurrent.getNegativeAngle(), feederFortescueThreePhaseValue.getMagnitudeA(), feederFortescueThreePhaseValue.getMagnitudeB(), feederFortescueThreePhaseValue.getMagnitudeC(), feederFortescueThreePhaseValue.getAngleA(), feederFortescueThreePhaseValue.getAngleB(), feederFortescueThreePhaseValue.getAngleC()));
93-
})
94-
.collect(Collectors.toList());
81+
return new FaultResultEntity(
82+
new FaultEmbeddable(fault.getId(), fault.getElementId(), fault.getFaultType()),
83+
Double.NaN,
84+
faultResult.getShortCircuitPower(),
85+
extractLimitViolations(faultResult),
86+
null,
87+
ipMin, ipMax,
88+
null, null,
89+
Double.NaN, Double.NaN
90+
);
91+
}
9592

96-
double ipMax = Double.NaN;
97-
double ipMin = Double.NaN;
98-
double deltaCurrentIpMin = Double.NaN;
99-
double deltaCurrentIpMax = Double.NaN;
100-
FortescueValue current = ((FortescueFaultResult) faultResult).getCurrent();
93+
private static FaultResultEntity toMagnitudeFaultResultEntity(MagnitudeFaultResult faultResult, ShortCircuitLimits shortCircuitLimits) {
94+
FaultResultEntity entity = toGenericFaultResultEntity(faultResult, shortCircuitLimits);
95+
final double current = faultResult.getCurrent();
96+
entity.setCurrent(current);
97+
entity.setFeederResults(faultResult.getFeederResults().stream()
98+
.map(feederResult -> new FeederResultEmbeddable(feederResult.getConnectableId(),
99+
((MagnitudeFeederResult) feederResult).getCurrent(), null))
100+
.collect(Collectors.toList()));
101101
if (shortCircuitLimits != null) {
102-
ipMax = shortCircuitLimits.getIpMax();
103-
ipMin = shortCircuitLimits.getIpMin();
104-
deltaCurrentIpMin = current.getPositiveMagnitude() - ipMin / 1000;
105-
deltaCurrentIpMax = current.getPositiveMagnitude() - ipMax / 1000;
102+
entity.setDeltaCurrentIpMin(current - entity.getIpMin() / 1000.0);
103+
entity.setDeltaCurrentIpMax(current - entity.getIpMax() / 1000.0);
104+
}
105+
return entity;
106+
}
107+
108+
private static FaultResultEntity toFortescueFaultResultEntity(FortescueFaultResult faultResult, ShortCircuitLimits shortCircuitLimits) {
109+
FaultResultEntity entity = toGenericFaultResultEntity(faultResult, shortCircuitLimits);
110+
entity.setFeederResults(faultResult.getFeederResults().stream()
111+
.map(feederResult -> {
112+
final FortescueValue feederFortescueCurrent = ((FortescueFeederResult) feederResult).getCurrent();
113+
final FortescueValue.ThreePhaseValue feederFortescueThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(feederFortescueCurrent);
114+
return new FeederResultEmbeddable(feederResult.getConnectableId(), Double.NaN, new FortescueResultEmbeddable(
115+
feederFortescueCurrent.getPositiveMagnitude(), feederFortescueCurrent.getZeroMagnitude(),
116+
feederFortescueCurrent.getNegativeMagnitude(), feederFortescueCurrent.getPositiveAngle(),
117+
feederFortescueCurrent.getZeroAngle(), feederFortescueCurrent.getNegativeAngle(),
118+
feederFortescueThreePhaseValue.getMagnitudeA(), feederFortescueThreePhaseValue.getMagnitudeB(),
119+
feederFortescueThreePhaseValue.getMagnitudeC(), feederFortescueThreePhaseValue.getAngleA(),
120+
feederFortescueThreePhaseValue.getAngleB(), feederFortescueThreePhaseValue.getAngleC()));
121+
})
122+
.collect(Collectors.toList()));
123+
124+
final FortescueValue current = faultResult.getCurrent();
125+
if (shortCircuitLimits != null) {
126+
entity.setDeltaCurrentIpMin(current.getPositiveMagnitude() - entity.getIpMin() / 1000.0);
127+
entity.setDeltaCurrentIpMax(current.getPositiveMagnitude() - entity.getIpMax() / 1000.0);
106128
}
107129

108-
FortescueValue voltage = ((FortescueFaultResult) faultResult).getVoltage();
109-
//We here use the function toThreePhaseValue from the utils class instead of FortescueValue's one because it is curently privated by mistake, to be changed once Powsybl core 6.0.0 is out
110-
FortescueValue.ThreePhaseValue currentThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(current);
111-
FortescueValue.ThreePhaseValue voltageThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(voltage);
112-
FortescueResultEmbeddable fortescueCurrent = new FortescueResultEmbeddable(current.getPositiveMagnitude(), current.getZeroMagnitude(), current.getNegativeMagnitude(), current.getPositiveAngle(), current.getZeroAngle(), current.getNegativeAngle(), currentThreePhaseValue.getMagnitudeA(), currentThreePhaseValue.getMagnitudeB(), currentThreePhaseValue.getMagnitudeC(), currentThreePhaseValue.getAngleA(), currentThreePhaseValue.getAngleB(), currentThreePhaseValue.getAngleC());
113-
FortescueResultEmbeddable fortescueVoltage = new FortescueResultEmbeddable(voltage.getPositiveMagnitude(), voltage.getZeroMagnitude(), voltage.getNegativeMagnitude(), voltage.getPositiveAngle(), voltage.getZeroAngle(), voltage.getNegativeAngle(), voltageThreePhaseValue.getMagnitudeA(), voltageThreePhaseValue.getMagnitudeB(), voltageThreePhaseValue.getMagnitudeC(), voltageThreePhaseValue.getAngleA(), voltageThreePhaseValue.getAngleB(), voltageThreePhaseValue.getAngleC());
114-
return new FaultResultEntity(faultEmbedded, Double.NaN, shortCircuitPower, limitViolations, feederResults, ipMin, ipMax, fortescueCurrent, fortescueVoltage, deltaCurrentIpMin, deltaCurrentIpMax);
130+
//We here use the function toThreePhaseValue from the utils class instead of FortescueValue's one because it is currently private by mistake, to be changed once Powsybl core 6.0.0 is out
131+
final FortescueValue.ThreePhaseValue currentThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(current);
132+
entity.setFortescueCurrent(new FortescueResultEmbeddable(current.getPositiveMagnitude(), current.getZeroMagnitude(), current.getNegativeMagnitude(), current.getPositiveAngle(), current.getZeroAngle(), current.getNegativeAngle(), currentThreePhaseValue.getMagnitudeA(), currentThreePhaseValue.getMagnitudeB(), currentThreePhaseValue.getMagnitudeC(), currentThreePhaseValue.getAngleA(), currentThreePhaseValue.getAngleB(), currentThreePhaseValue.getAngleC()));
133+
final FortescueValue voltage = faultResult.getVoltage();
134+
final FortescueValue.ThreePhaseValue voltageThreePhaseValue = ShortcircuitUtils.toThreePhaseValue(voltage);
135+
entity.setFortescueVoltage(new FortescueResultEmbeddable(voltage.getPositiveMagnitude(), voltage.getZeroMagnitude(), voltage.getNegativeMagnitude(), voltage.getPositiveAngle(), voltage.getZeroAngle(), voltage.getNegativeAngle(), voltageThreePhaseValue.getMagnitudeA(), voltageThreePhaseValue.getMagnitudeB(), voltageThreePhaseValue.getMagnitudeC(), voltageThreePhaseValue.getAngleA(), voltageThreePhaseValue.getAngleB(), voltageThreePhaseValue.getAngleC()));
136+
137+
return entity;
115138
}
116139

117140
private static GlobalStatusEntity toStatusEntity(UUID resultUuid, String status) {
@@ -126,10 +149,10 @@ public void insertStatus(List<UUID> resultUuids, String status) {
126149
}
127150

128151
@Transactional
129-
public void insert(UUID resultUuid, ShortCircuitAnalysisResult result, Map<String, ShortCircuitLimits> allCurrentLimits, boolean isWithFortescueResult, String status) {
152+
public void insert(UUID resultUuid, ShortCircuitAnalysisResult result, Map<String, ShortCircuitLimits> allCurrentLimits, String status) {
130153
Objects.requireNonNull(resultUuid);
131-
if (result != null) {
132-
resultRepository.save(toResultEntity(resultUuid, result, allCurrentLimits, isWithFortescueResult));
154+
if (result != null && result.getFaultResults().stream().map(FaultResult::getStatus).noneMatch(FaultResult.Status.NO_SHORT_CIRCUIT_DATA::equals)) {
155+
resultRepository.save(toResultEntity(resultUuid, result, allCurrentLimits));
133156
}
134157
globalStatusRepository.save(toStatusEntity(resultUuid, status));
135158
}

src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitWorkerService.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717
import com.powsybl.iidm.network.extensions.IdentifiableShortCircuit;
1818
import com.powsybl.network.store.client.NetworkStoreService;
1919
import com.powsybl.network.store.client.PreloadingStrategy;
20-
import com.powsybl.shortcircuit.BusFault;
21-
import com.powsybl.shortcircuit.Fault;
22-
import com.powsybl.shortcircuit.ShortCircuitAnalysis;
23-
import com.powsybl.shortcircuit.ShortCircuitAnalysisResult;
20+
import com.powsybl.shortcircuit.*;
2421
import org.apache.commons.lang3.StringUtils;
2522
import org.gridsuite.shortcircuit.server.dto.ShortCircuitAnalysisStatus;
2623
import org.gridsuite.shortcircuit.server.dto.ShortCircuitLimits;
@@ -237,13 +234,20 @@ public Consumer<Message<String>> consumeRun() {
237234
long nanoTime = System.nanoTime();
238235
LOGGER.info("Just run in {}s", TimeUnit.NANOSECONDS.toSeconds(nanoTime - startTime.getAndSet(nanoTime)));
239236

240-
resultRepository.insert(resultContext.getResultUuid(), result, shortCircuitLimits, resultContext.getRunContext().getParameters().isWithFortescueResult(), ShortCircuitAnalysisStatus.COMPLETED.name());
237+
resultRepository.insert(resultContext.getResultUuid(), result, shortCircuitLimits, ShortCircuitAnalysisStatus.COMPLETED.name());
241238
long finalNanoTime = System.nanoTime();
242239
LOGGER.info("Stored in {}s", TimeUnit.NANOSECONDS.toSeconds(finalNanoTime - startTime.getAndSet(finalNanoTime)));
243240

244241
if (result != null) { // result available
245-
notificationService.sendResultMessage(resultContext.getResultUuid(), resultContext.getRunContext().getReceiver(), resultContext.getRunContext().getBusId());
246-
LOGGER.info("Short circuit analysis complete (resultUuid='{}')", resultContext.getResultUuid());
242+
if (result.getFaultResults().stream().map(FaultResult::getStatus).anyMatch(FaultResult.Status.NO_SHORT_CIRCUIT_DATA::equals)) {
243+
LOGGER.error("Short circuit analysis failed (resultUuid='{}')", resultContext.getResultUuid());
244+
notificationService.publishFail(resultContext.getResultUuid(), resultContext.getRunContext().getReceiver(),
245+
"Missing short-circuit extension data",
246+
resultContext.getRunContext().getUserId(), resultContext.getRunContext().getBusId());
247+
} else {
248+
notificationService.sendResultMessage(resultContext.getResultUuid(), resultContext.getRunContext().getReceiver(), resultContext.getRunContext().getBusId());
249+
LOGGER.info("Short circuit analysis complete (resultUuid='{}')", resultContext.getResultUuid());
250+
}
247251
} else { // result not available : stop computation request
248252
if (cancelComputationRequests.get(resultContext.getResultUuid()) != null) {
249253
cleanShortCircuitAnalysisResultsAndPublishCancel(resultContext.getResultUuid(), cancelComputationRequests.get(resultContext.getResultUuid()).getReceiver());

0 commit comments

Comments
 (0)